💻 IT/테크

REST API 설계 | RESTful 원칙부터 보안까지

📅 2025년 11월 25일 ⏱️ 10분 읽기 ✍️ kimyido

REST API란?

REST (Representational State Transfer)는 웹 기반 API 설계 아키텍처입니다.

특징:

  • 리소스 기반 (users, posts, comments)
  • HTTP 메소드 활용 (GET, POST, PUT, DELETE)
  • 상태 비저장 (stateless)
  • 캐시 가능

기본 규칙: CRUD

CREATE (생성) → POST /users
                POST /posts

READ (읽기)  → GET /users
               GET /users/1
               GET /posts

UPDATE (수정) → PUT /users/1
               PATCH /posts/1

DELETE (삭제) → DELETE /users/1
               DELETE /posts/1

RESTful API 설계 원칙

1. 리소스 지향 (Resource-Oriented)

❌ 나쁜 설계
GET /getUser?id=1
GET /createPost
DELETE /removeComment?id=5

✅ 좋은 설계
GET /users/1
POST /posts
DELETE /comments/5

2. HTTP 메소드 올바른 사용

GET: 안전 (데이터 변경 없음), 멱등성 있음 (반복해도 같음)
POST: 새 리소스 생성 (멱등성 없음)
PUT: 리소스 전체 교체 (멱등성 있음)
PATCH: 리소스 일부 수정 (멱등성 없음)
DELETE: 리소스 삭제 (멱등성 있음)

3. 상태 코드 올바른 사용

200 OK: 요청 성공
201 Created: 리소스 생성 성공 (POST 응답)
204 No Content: 성공하지만 반환값 없음 (DELETE)
400 Bad Request: 잘못된 요청
401 Unauthorized: 인증 실패
403 Forbidden: 권한 없음
404 Not Found: 리소스 없음
500 Server Error: 서버 오류

예시:

POST /users
응답: 201 Created
{ "id": 1, "name": "John" }

GET /users/999
응답: 404 Not Found
{ "error": "User not found" }

4. 명사 사용 (동사 금지)

❌ 나쁜 예
/getUsers
/createPost
/deleteComment

✅ 좋은 예
/users          (GET으로 조회)
/posts          (POST로 생성)
/comments/5     (DELETE로 삭제)

API 버전 관리

URL 경로에 버전 포함 (권장)

/api/v1/users
/api/v2/users
/api/v3/users

장점:

  • 명확한 버전 구분
  • URL에서 직접 확인 가능

헤더에 버전 포함

GET /users
Accept: application/vnd.api+json;version=1

또는

X-API-Version: 1

쿼리 파라미터

GET /users?api_version=1

인증 (Authentication)

JWT (JSON Web Token) - 가장 인기

// 로그인
POST /auth/login
{ "email": "user@example.com", "password": "123456" }

응답:
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_in": 3600
}

// API 사용
GET /users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

구조:

Header.Payload.Signature

Header: { "alg": "HS256", "typ": "JWT" }
Payload: { "userId": 1, "exp": 1234567890 }
Signature: hmacSHA256(base64(header) + "." + base64(payload), secret)

OAuth 2.0 (소셜 로그인)

사용자가 "Google로 로그인" 클릭
    ↓
구글 로그인 페이지로 리다이렉트
    ↓
구글 인증 후 authorization code 받기
    ↓
우리 앱이 authorization code로 토큰 요청
    ↓
access token 획득
    ↓
API 호출

사용 시기: SNS 연동, 소셜 로그인

에러 처리

일관된 에러 응답 포맷

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is invalid",
    "details": [
      {
        "field": "email",
        "issue": "Must be a valid email address"
      }
    ]
  }
}

에러 코드 정의

VALIDATION_ERROR (400): 입력값 오류
UNAUTHORIZED (401): 인증 실패
FORBIDDEN (403): 권한 없음
NOT_FOUND (404): 리소스 없음
CONFLICT (409): 충돌 (예: 중복 이메일)
INTERNAL_ERROR (500): 서버 오류

페이지네이션

쿼리 파라미터 방식

GET /posts?page=2&limit=10

응답:
{
  "data": [...],
  "pagination": {
    "page": 2,
    "limit": 10,
    "total": 100,
    "pages": 10
  }
}

Cursor 방식 (성능 최고)

GET /posts?limit=10&cursor=abc123

응답:
{
  "data": [...],
  "pagination": {
    "next_cursor": "xyz789",
    "has_more": true
  }
}

Offset vs Cursor:

  • Offset: 간단하지만 느림 (많은 행 스킵)
  • Cursor: 복잡하지만 빠름 (실시간 데이터 최적)

레이트 제한 (Rate Limiting)

X-RateLimit-Limit: 1000       (시간당 최대 요청)
X-RateLimit-Remaining: 850    (남은 요청)
X-RateLimit-Reset: 1234567890 (초기화 시간)

정책:

  • 일반 사용자: 시간당 1,000 요청
  • 유료 사용자: 시간당 10,000 요청
  • 초과 시: 429 Too Many Requests

CORS (Cross-Origin Resource Sharing)

프론트엔드: http://localhost:3000
백엔드 API: http://api.example.com
    ↓
브라우저가 차단 (다른 도메인)
    ↓
백엔드에서 CORS 허용 설정:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

API 문서화 (OpenAPI/Swagger)

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0

paths:
  /users:
    get:
      summary: 모든 사용자 조회
      parameters:
        - name: page
          in: query
          type: integer
      responses:
        200:
          description: 성공
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'

도구:

  • Swagger UI: 자동으로 API 문서 생성
  • Postman: API 테스트 및 문서화

캐싱

// 응답에 캐시 정보 포함
Cache-Control: public, max-age=3600  // 1시간 캐시

GET /posts
    ↓
처음 요청: 데이터베이스에서 가져오기
다시 요청: 캐시에서 즉시 반환 (1시간 내)

→ 데이터베이스 부하 30-50% 감소

보안 체크리스트

✓ HTTPS 필수 (HTTP 금지)
✓ 입력값 검증 (SQL 인젝션 방지)
✓ 출력 인코딩 (XSS 방지)
✓ 인증 및 권한 확인
✓ 레이트 제한 설정
✓ CORS 올바르게 설정
✓ 민감한 정보 노출 금지
✓ 로그 기록 (감사 추적)
✓ 정기 보안 감사

자주 묻는 질문

REST API와 GraphQL의 차이는?

A.

  • REST: 고정된 응답 (간단함, 높은 캐시율)
  • GraphQL: 필요한 데이터만 요청 (유연함, 복잡함)

HTTP 상태 코드는 몇 개나 써야 하나요?

A. 최소 5개 (200, 201, 400, 404, 500) 충분. 더 많으면 클라이언트가 혼동.

API를 개인이 만들어도 되나요?

A. 당신의 데이터라면 자유. 다른 사람의 API를 이용할 때는 약관 확인.

API는 몇 개 버전을 동시에 지원해야 하나요?

A. 보통 2개 (현재 + 이전 버전). 지원 기간을 명시하세요.

모바일 앱은 API 클라이언트 라이브러리를 써야 하나요?

A. 권장합니다 (Retrofit, Alamofire 등). HTTP 라이브러리보다 편함.

결론

좋은 API 설계는:

RESTful 원칙 준수
    ↓
명확한 에러 처리
    ↓
보안 최우선
    ↓
좋은 문서화
    ↓
지속적인 개선

가장 중요한 것: API 사용자의 입장에서 생각하기. 개발자 경험(DX)이 모든 것.

관련 글: 웹개발 로드맵 | 서버 관리 가이드

✍️
김이도 편집팀
정확한 정보 전달을 위해 전문 자료와 공식 통계를 기반으로 콘텐츠를 작성합니다. 최신 정보 반영을 위해 주기적으로 업데이트됩니다.
📅 최종 업데이트: 2025년 11월 25일 · 📧 문의: 연락하기
💻 IT/테크 카테고리 전체 글 보기 →