API 디자인

AI 도움으로 API를 설계하는 방법을 배웁니다. RESTful API 설계 원칙과 실전 팁을 알아봅니다.

개요

좋은 API 설계는 개발자 경험을 좌우합니다. AI를 활용하여 일관되고 사용하기 쉬운 API를 설계할 수 있습니다.

📋 RESTful API 원칙
  • 자원의 명사 사용: /users, /posts
  • HTTP 메서드 적절히 사용: GET, POST, PUT, DELETE
  • 계층적 URL: /users/123/posts
  • 일관된 응답 형식: JSON
  • 무상태 (Stateless): 각 요청이 독립적
  • 클라이언트-서버 분리: 관심사 분리
REST API 요청 처리 흐름도 클라이언트 웹 / 모바일 / CLI HTTP 요청 GET / POST PUT / DELETE API 게이트웨이 라우팅 / 로드밸런싱 요청 분배 인증 / 인가 JWT / OAuth 검증 권한 확인 속도 제한 Rate Limiting 요청 수 제어 컨트롤러 요청 파싱 / 검증 파라미터 바인딩 서비스 계층 비즈니스 로직 트랜잭션 처리 데이터베이스 CRUD 연산 데이터 영속화 응답 (JSON) 상태 코드 + 데이터 { status, data, message } 점선: 응답 반환 경로 진입/응답 단계 처리 단계 보안/데이터 단계

HTTP 메서드 이해하기

각 HTTP 메서드의 특성을 이해하고 올바르게 사용하는 것이 RESTful API의 핵심입니다.

메서드 용도 멱등성 안전성 예시
GET 리소스 조회 ✅ O ✅ O GET /users/123
POST 리소스 생성 ❌ X ❌ X POST /users
PUT 리소스 전체 수정/생성 ✅ O ❌ X PUT /users/123
PATCH 리소스 부분 수정 △ 경우에 따라 ❌ X PATCH /users/123
DELETE 리소스 삭제 ✅ O ❌ X DELETE /users/123
💡 멱등성(Idempotent)과 안전성(Safe)이란?
  • 멱등성: 같은 요청을 여러 번 보내도 결과가 동일 (서버 상태가 같음)
  • 안전성: 서버의 상태를 절대 변경하지 않음 (읽기 전용)

⚠️ 실무 주의사항: GET 요청에 데이터 변경 로직을 넣으면 안 됩니다!

API 유형

프로젝트에 맞는 API 유형을 선택하세요.

  • REST API: 가장 널리 사용, HTTP 캐시 활용
  • GraphQL: 클라이언트가 원하는 데이터 선택, Over-fetching 방지
  • gRPC: 고성능, Protocol Buffers, 마이크로서비스
  • WebSocket: 실시간 양방향 통신
  • Webhook: 이벤트 기반 알림
💡 API 유형 선택 가이드
  • 단순 CRUD: REST API
  • 복잡한 데이터 관계: GraphQL
  • 실시간 업데이트: WebSocket
  • 마이크로서비스: gRPC

엔드포인트 설계

API 엔드포인트를 설계합니다. 자원과 행동을 명확히 분리하면 일관된 API를 만들 수 있습니다.

엔드포인트 설계 요청

AI에게 요청
블로그 API의 엔드포인트를 설계해줘.

리소스:
- 사용자 (users)
- 게시물 (posts)
- 댓글 (comments)
- 카테고리 (categories)

요구:
- CRUD 엔드포인트
- 페이지네이션
- 필터링
- 정렬

명명 규칙

일관된 명명 규칙을 적용하세요.

AI에게 요청
RESTful 명명 규칙을 적용한 엔드포인트를 작성해줘:

리소스: orders (주문)

기본 CRUD:
- GET    /orders          # 전체 조회
- GET    /orders/:id      # 단일 조회
- POST   /orders          # 생성
- PUT    /orders/:id      # 전체 수정
- PATCH  /orders/:id      # 부분 수정
- DELETE /orders/:id      # 삭제

특정 행동:
- POST   /orders/:id/cancel    # 주문 취소
- POST   /orders/:id/refund   # 환불 요청

관계 리소스:
- GET /orders/:id/items        # 주문 상품 목록
- GET /users/:id/orders        # 사용자의 주문 목록

쿼리 파라미터

필터링, 정렬, 페이지네이션을 위한 표준 파라미터를 정의하세요.

AI에게 요청
쿼리 파라미터 표준을 설계해줘:

페이지네이션:
- page: 페이지 번호 (기본값 1)
- limit: 페이지당 항목 수 (기본값 20, 최대 100)
- 예: /posts?page=2&limit=10

필터링:
- 필드명=값 형식
- 여러 필터: &로 연결
- 예: /posts?status=published&author_id=1

정렬:
- sort: 필드명
- order: asc | desc
- 예: /posts?sort=created_at&order=desc

검색:
- q: 검색어
- 예: /posts?q=안녕하세요

REST vs GraphQL

⚠️ REST와 GraphQL 선택
기준 REST GraphQL
데이터_fetching 엔드포인트당 고정 클라이언트가 선택
Over-fetching 많을 수 있음 없음
캐시 HTTP 캐시 활용 커스텀 필요
학습 곡선 낮음 보통

요청/응답 형식

API 요청과 응답의 형식을 정의합니다. 일관된 형식은 개발자 경험을 크게 향상시킵니다.

응답 형식 요청

AI에게 요청
API 응답 형식을 표준화해줘.

성공 응답:
- success: boolean
- data: object
- message: string (선택)
- pagination: object (선택)

에러 응답:
- success: false
- error: object
  - code: string
  - message: string
  - details: object (선택)

성공 응답 예시

단일 리소스 응답
{
  "success": true,
  "data": {
    "id": 1,
    "title": "첫 번째 게시물",
    "content": "내용...",
    "author": {
      "id": 1,
      "name": "홍길동"
    },
    "createdAt": "2024-01-15T10:30:00Z"
  }
}
목록 응답 (페이지네이션)
{
  "success": true,
  "data": [
    { "id": 1, "title": "게시물 1" },
    { "id": 2, "title": "게시물 2" }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 100,
    "totalPages": 10
  }
}

에러 응답 예시

유효성 검사 에러
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "입력 데이터가 유효하지 않습니다",
    "details": [
      { "field": "email", "message": "올바른 이메일을 입력해주세요" },
      { "field": "password", "message": "비밀번호는 8자 이상이어야 합니다" }
    ]
  }
}

요청 본문Validation

AI에게 요청
사용자 생성 API의 요청 스키마를 작성해줘:

요구사항:
- email: 필수, 유효한 이메일 형식
- password: 필수, 8~20자, 영문+숫자+특수문자
- name: 필수, 2~50자
- age: 선택, 1~150 사이의 숫자
- role: 선택, 기본값 'user', enum ['user', 'admin']

도구: Zod 스키마로

에러 처리

일관된 에러 처리는 문제 진단과 디버깅을 쉽게 만듭니다.

HTTP 상태 코드

코드 의미 사용 상황
200 OK 성공적인 GET, PUT
201 Created 리소스 생성 성공
204 No Content DELETE 성공, 응답 본문 없음
400 Bad Request 잘못된 요청 구문
401 Unauthorized 인증 필요
403 Forbidden 권한 없음
404 Not Found 리소스 없음
409 Conflict 데이터 충돌 (중복 등)
422 Unprocessable Entity 유효성 검사 실패
429 Too Many Requests Rate Limit 초과
500 Server Error 서버 내부 오류
503 Service Unavailable 서비스 일시 중단

에러 코드 시스템

AI에게 요청
API 에러 코드 시스템을 설계해줘:

카테고리:
- AUTH_*: 인증/인가 관련
- VALIDATION_*: 유효성 검사
- RESOURCE_*: 리소스 관련
- INTERNAL_*: 서버 내부

예시:
- AUTH_TOKEN_EXPIRED
- AUTH_INVALID_CREDENTIALS
- VALIDATION_EMAIL_INVALID
- RESOURCE_NOT_FOUND
- RESOURCE_ALREADY_EXISTS

에러 처리 베스트 프랙티스

💡 에러 처리 원칙
  • 일관성: 모든 에러 응답 동일한 구조
  • 정보 제공: 디버깅에 필요한 정보 포함
  • 보안: 민감한 정보는 제외
  • 로깅: 서버 측 에러는 반드시 로깅

API 버전 관리

API 버전을 관리하는 전략입니다. 클라이언트에게 호환성을 유지하면서 API를 발전시킬 수 있습니다.

버전 관리 요청

AI에게 요청
API 버전 관리 전략을 설계해줘.

요구사항:
1. URL 기반 버전 (v1, v2)
2. 호환성이 깨진 변경은 새 버전에서
3.이전 버전은 최소 6개월 지원
4. deprecation 알림 헤더

버전 관리 전략 비교

전략 장점 단점
URL 경로 (v1/users) 명확함, 캐시 용이 코드 중복 가능성
헤더 (Accept: v1+json) URL 간결 캐시 어려움
쿼리 파라미터 (?version=1) 간편함 캐시 어려움

Deprecation 정책

Deprecation 헤더 예시
Deprecation: true
Link: <https://api.example.com/v2/users>; rel="successor-version"
Sunset: Sat, 01 Jun 2024 00:00:00 GMT
⚠️ 호환성 유지 원칙
  • 추가만: 기존 필드 제거 금지
  • 필드명 변경: 새 필드 추가, 기존 필드 비권장 처리
  • 응답 형식: 기존 구조 유지
  • 기능 제거: Deprecation 기간 후에만

API 문서화

API 문서를 자동으로 생성합니다. 좋은 문서는 개발자 경험의 핵심입니다.

문서 생성 요청

AI에게 요청
OpenAPI (Swagger) 문서를 생성해줘.

포함 내용:
- 모든 엔드포인트 설명
- 요청/응답 스키마
- 에러 응답 예시
- 인증 요구사항

OpenAPI 스키마 예시

AI에게 요청
OpenAPI 3.0 스키마를 작성해줘:

엔드포인트: POST /api/users
요청:
- email: string, required, format email
- password: string, required, minLength 8
- name: string, required

응답:
- 201: user object
- 400: validation error
- 409: duplicate email error

스키마:
- components/schemas/User
- components/schemas/Error
- components/securitySchemes/BearerAuth

인증 및 권한

API 인증 및 권한 관리를 설계합니다.

인증 전략

방식 장점 사용 상황
JWT 무상태, 확장성 모바일, SPA
OAuth 2.0 타사 인증 가능 소셜 로그인
API Key 단순함 서버 간 통신
Session 서버 통제 전통적 웹 앱

인증 구현 요청

AI에게 요청
JWT 인증 시스템을 설계해줘:

요구사항:
- Access Token: 15분 유효
- Refresh Token: 7일 유효
- 저장소: httpOnly Cookie
- 보안: httpOnly, secure, sameSite
- 갱신 엔드포인트 포함

환경: Express.js + TypeScript

CORS 보안 설정

Cross-Origin Resource Sharing(CORS)는 웹 브라우저에서 다른 도메인의 리소스에 접근할 수 있도록 허용하는 메커니즘입니다.

⚠️ CORS 기본 설정의 위험성

app.use(cors())모든 도메인에서의 요청을 허용합니다.

프로덕션 환경에서는 절대 사용하면 안 됩니다!

  • 악의적인 웹사이트에서 API 호출 가능
  • 사용자 데이터 유출 위험
  • CSRF(Cross-Site Request Forgery) 공격 가능

개발 환경: 모든 도메인 허용

JavaScript
const express = require('express');
const cors = require('cors');

const app = express();

// 개발 환경에서만 사용!
app.use(cors());

프로덕션 환경: 특정 도메인만 허용

JavaScript
const corsOptions = {
  origin: [
    'https://myapp.com',
    'https://www.myapp.com',
    'https://admin.myapp.com'
  ],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true,  // 쿠키 포함 허용
  maxAge: 86400      // preflight 캐시 시간 (24시간)
};

app.use(cors(corsOptions));

동적 Origin 검증

JavaScript
const allowedOrigins = process.env.NODE_ENV === 'production'
  ? ['https://myapp.com', 'https://www.myapp.com']
  : ['http://localhost:3000', 'http://localhost:5173'];

const corsOptions = {
  origin: (origin, callback) => {
    // origin이 없는 경우 허용 (같은 도메인 요청, Postman 등)
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
};

app.use(cors(corsOptions));

환경 변수 활용

.env
NODE_ENV=production
ALLOWED_ORIGINS=https://myapp.com,https://www.myapp.com
JavaScript
const allowedOrigins = process.env.ALLOWED_ORIGINS
  ? process.env.ALLOWED_ORIGINS.split(',')
  : ['http://localhost:3000'];

const corsOptions = {
  origin: allowedOrigins,
  credentials: true
};

app.use(cors(corsOptions));
💡 CORS 디버깅 팁
  • 브라우저 개발자 도구: Console에서 CORS 에러 메시지 확인
  • Preflight 요청: OPTIONS 메서드 요청이 성공하는지 확인
  • 응답 헤더: Access-Control-Allow-Origin 헤더가 올바른지 확인
  • Credentials: 쿠키를 사용한다면 credentials: true 필수

CORS 테스트

curl로 테스트
# Preflight 요청 테스트
curl -X OPTIONS http://localhost:3000/api/users \
  -H "Origin: https://myapp.com" \
  -H "Access-Control-Request-Method: POST" \
  -v

# 실제 요청 테스트
curl -X GET http://localhost:3000/api/users \
  -H "Origin: https://myapp.com" \
  -v

Rate Limiting

API 요청 제한을 설계합니다.

Rate Limit 요청

AI에게 요청
Rate Limiting 전략을 설계해줘:

요구사항:
- 일반 사용자: 100 req/min
- 프리미엄 사용자: 1000 req/min
- 특정 엔드포인트: 별도 제한
- Rate Limit 헤더 포함

헤더:
- X-RateLimit-Limit
- X-RateLimit-Remaining
- X-RateLimit-Reset

환경: Express.js

캐싱 전략

API 응답 캐싱을 설계합니다.

캐싱 전략

💡 캐싱 적용 가이드
  • CDN: 정적 자산, 공개 데이터
  • API Gateway: 응답 캐싱
  • 애플리케이션:Redis 활용
  • HTTP 캐시: ETags, Last-Modified
AI에게 요청
캐싱 전략을 설계해줘:

시나리오:
- 사용자 프로필: 5분 캐시
- 상품 목록: 1분 캐시
- 실시간 재고: 캐시 안 함
- 인기 검색어: 10분 캐시

요구사항:
- Redis 사용
- Cache-Control 헤더
- Invalidation 전략

다음 단계

API 개발에 대해 더 자세히 배워보세요!

REST API 구축

실전 튜토리얼

REST API 구축 →

백엔드 Vibe Coding

백엔드 개발 가이드

백엔드 Vibe Coding →

데이터베이스 프롬프트

DB 설계도 AI로!

데이터베이스 프롬프트 →

핵심 정리

  • 엔드포인트: 리소스 기반 URL 설계
  • 응답 형식: 일관된 JSON 구조
  • 에러 처리: 적절한 HTTP 상태 코드
  • 버전 관리: URL 기반 버전 관리
  • 문서화: OpenAPI/Swagger