API란 무엇인가
API(Application Programming Interface)는 프론트엔드와 백엔드, 또는 서비스와 서비스가 데이터를 주고받기 위한 약속입니다. 서로 다른 시스템이 표준화된 방식으로 통신할 수 있게 해줍니다.
좋은 API는 예측 가능하고, 일관되며, 이해하기 쉽습니다. 잘못 설계된 API는 팀 전체의 개발 속도를 늦추고 버그의 원인이 됩니다.
RESTful API의 핵심 원칙 6가지
REST(Representational State Transfer)는 가장 보편적인 API 설계 방식입니다.
클라이언트-서버 분리: 프론트엔드와 백엔드는 독립적으로 동작하고 API로만 통신합니다.
무상태성(Stateless): 각 요청은 서버가 이전 요청을 기억하지 않아도 독립적으로 처리될 수 있어야 합니다. 인증 정보는 매 요청에 포함해야 합니다.
캐시 가능: 응답은 캐시 가능 여부를 명시해야 합니다. 캐싱이 가능한 데이터는
Cache-Control헤더로 표시합니다.계층화된 시스템: 클라이언트는 서버에 직접 연결되는지, 중간 프록시를 통하는지 알 필요가 없습니다.
균일한 인터페이스: URL은 자원(Resource)을 나타내고, HTTP 메서드는 행위를 나타냅니다.
자원 중심 설계: URL에 동사를 사용하지 않고 명사(자원)를 사용합니다.
/getUser대신/users/{id}를 사용합니다.
URL 설계 규칙
# 좋은 예시
GET /posts # 게시글 목록 조회
GET /posts/123 # 특정 게시글 조회
POST /posts # 게시글 생성
PATCH /posts/123 # 게시글 일부 수정
DELETE /posts/123 # 게시글 삭제
GET /users/456/posts # 특정 사용자의 게시글 목록
# 나쁜 예시
GET /getPosts
POST /createPost
GET /deletePost?id=123
URL은 소문자, 하이픈(-) 사용, 복수형 명사를 원칙으로 합니다.
HTTP 상태 코드 완전 정리
HTTP 상태 코드는 요청의 결과를 표준화된 숫자로 나타냅니다.
2xx 성공
- 200 OK: 요청 성공. GET, PATCH, DELETE 성공 시 사용
- 201 Created: 자원 생성 성공. POST로 새 데이터를 만들었을 때 사용
- 204 No Content: 성공했지만 응답 본문이 없음. DELETE 후 사용
4xx 클라이언트 오류
- 400 Bad Request: 요청 형식이 잘못됨. 필수 필드 누락, 유효하지 않은 값
- 401 Unauthorized: 인증이 필요함. 로그인이 안 된 상태에서 보호된 API 호출 시
- 403 Forbidden: 인증은 됐지만 권한이 없음. 다른 사용자의 데이터 수정 시도
- 404 Not Found: 자원이 존재하지 않음
- 422 Unprocessable Entity: 형식은 맞지만 비즈니스 규칙 위반 (이미 사용 중인 이메일 등)
- 429 Too Many Requests: Rate Limit 초과
5xx 서버 오류
- 500 Internal Server Error: 서버 내부 오류. 예상치 못한 예외 발생 시
- 503 Service Unavailable: 서버 점검 중 또는 과부하
API 버전 관리 방법
서비스가 성장하면 API를 변경해야 하는 상황이 옵니다. 기존 클라이언트를 깨뜨리지 않으면서 새 API를 배포하려면 버전 관리가 필요합니다.
URL 기반 버전 관리 (가장 일반적)
/v1/posts ← 기존 API 유지
/v2/posts ← 새로운 구조의 API
v1 클라이언트는 계속 /v1을 사용하고, 새 클라이언트는 /v2를 사용합니다. 구형 버전은 sunset 날짜를 공지하고 일정 기간 후 deprecated 처리합니다.
헤더 기반 버전 관리
Accept: application/vnd.myapi.v2+json
URL이 깔끔하게 유지되지만, 테스트와 캐싱이 복잡해지는 단점이 있습니다.
응답 형식 표준화
일관된 응답 구조를 만들면 프론트엔드에서 처리하기 쉬워집니다.
// 성공 응답
{
"success": true,
"data": {
"id": 123,
"title": "첫 번째 게시글",
"created_at": "2026-03-01T12:00:00Z"
}
}
// 목록 응답
{
"success": true,
"data": [...],
"pagination": {
"total": 100,
"page": 1,
"per_page": 20,
"total_pages": 5
}
}
// 에러 응답
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "이메일 형식이 올바르지 않습니다.",
"details": [
{ "field": "email", "message": "유효한 이메일 주소를 입력해주세요." }
]
}
}
API 문서 작성 (Swagger/OpenAPI)
OpenAPI는 API를 YAML/JSON으로 표준화하여 문서화하는 방법입니다. Express + Swagger, FastAPI(자동 문서화), NestJS(데코레이터 기반 자동화)를 활용하면 코드에서 문서가 자동으로 생성됩니다.
# openapi.yaml 예시
paths:
/posts:
get:
summary: 게시글 목록 조회
parameters:
- name: page
in: query
schema:
type: integer
default: 1
responses:
'200':
description: 성공
API 보안 기본
인증 처리
모든 보호된 엔드포인트는 인증 미들웨어로 보호합니다. JWT를 사용한다면 Authorization 헤더에서 토큰을 추출하고 유효성을 검증합니다.
Rate Limiting
같은 IP에서 단시간에 과도한 요청을 차단합니다. Express에서는 express-rate-limit 패키지를 사용합니다.
import rateLimit from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15분
max: 100 // 15분에 최대 100회 요청
})
app.use('/api/', limiter)
입력 검증
클라이언트에서 오는 모든 데이터는 신뢰할 수 없습니다. Zod나 Joi를 사용해 스키마 기반 검증을 적용합니다.
import { z } from 'zod'
const createPostSchema = z.object({
title: z.string().min(1).max(100),
content: z.string().min(10),
is_public: z.boolean().default(false)
})
// 요청 처리
const parsed = createPostSchema.safeParse(req.body)
if (!parsed.success) {
return res.status(400).json({ error: parsed.error })
}
SQL Injection 방지를 위해 raw SQL 대신 ORM(Prisma, Drizzle)이나 파라미터 바인딩을 반드시 사용합니다.