학습 / 치트 시트
API 테스트를 위한 HTTP 치트 시트
테스터에게 필요한 HTTP 지식을 한 장에 담았습니다. 어떤 메서드가 안전하고 멱등한지, 상황별로 어떤 상태 코드가 반환되어야 하는지, 검증할 가치가 있는 헤더, 매일 쓰는 cURL 옵션, 그리고 응답마다 확인할 체크리스트입니다.
HTTP 의미론은 RFC 9110, Problem Details는 RFC 9457 기준 기준으로 검증
메서드
| 메서드 | 용도 | 안전 | 멱등 |
|---|---|---|---|
GET | 리소스 또는 컬렉션 조회 | 예 | 예 |
HEAD | GET과 같지만 헤더만 반환 | 예 | 예 |
OPTIONS | 허용된 메서드 확인, CORS 프리플라이트 | 예 | 예 |
POST | 생성 또는 액션 실행 | 아니요 | 아니요 |
PUT | 리소스 전체 교체 | 아니요 | 예 |
PATCH | 일부 필드 변경 | 아니요 | 보장되지 않음 |
DELETE | 리소스 삭제 | 아니요 | 예 |
멱등이란 같은 요청을 반복해도 서버 상태가 동일하게 유지된다는 뜻입니다. 응답은 다를 수 있습니다. 두 번째 DELETE는 404를 반환할 수 있습니다.
검증할 상태 코드
| 코드 | 의미 | 대표적인 테스트 |
|---|---|---|
200 OK | 성공, 본문 있음 | 존재하는 리소스 GET |
201 Created | 리소스 생성됨 | 유효한 데이터 POST, Location 헤더 확인 |
204 No Content | 성공, 본문 없음 | DELETE, 또는 아무것도 반환하지 않는 PUT |
301 / 308 | 영구 이동 | 이전 URL이 리디렉션됨. 308은 메서드를 유지 |
304 Not Modified | 캐시된 사본이 여전히 유효 | If-None-Match: <etag>를 붙인 GET |
400 Bad Request | 잘못된 형식의 요청 | 유효하지 않은 JSON, 잘못된 타입 |
401 Unauthorized | 인증되지 않음 | 토큰 누락 또는 만료 |
403 Forbidden | 인증됐지만 권한 없음 | 다른 사용자의 리소스에 접근 |
404 Not Found | 해당 리소스 없음 | 알 수 없는 ID (또는 볼 권한이 없는 리소스 숨김) |
405 Method Not Allowed | 이 URL에 맞지 않는 메서드 | 읽기 전용 엔드포인트에 DELETE |
409 Conflict | 현재 상태와 충돌 | 중복 이메일, 오래된 버전 |
415 Unsupported Media Type | 허용되지 않는 본문 형식 | JSON 엔드포인트에 text/plain 전송 |
422 Unprocessable Content | JSON은 유효하지만 값이 잘못됨 | 비즈니스 규칙 검증 오류 |
429 Too Many Requests | 요청 한도 초과(rate limit) | 요청을 몰아서 보내고 Retry-After 확인 |
500 Internal Server Error | 서버 버그 | 절대 예상된 결과가 아님: 항상 결함 |
502 / 503 / 504 | 업스트림 실패, 서비스 불가, 타임아웃 | 의존 서비스 다운, 재시도 동작 확인 |
확인할 가치가 있는 헤더
| 헤더 | 예시 | 이유 |
|---|---|---|
Content-Type | application/json; charset=utf-8 | 응답 형식이 본문과 일치하는지 |
Accept | application/json | 클라이언트가 형식을 요청함. 지원하지 않으면 406 기대 |
Authorization | Bearer eyJhbGciOi… | 토큰 인증. 누락 시 → 401 |
Location | /api/orders/1043 | 201 Created와 리디렉션에서 설정됨 |
Cache-Control | no-store | 개인 정보나 민감한 데이터는 캐시되면 안 됨 |
ETag / If-None-Match | "a1b2c3" | 조건부 GET → 304 |
Retry-After | 30 | 429 또는 503과 함께 전송됨 |
Set-Cookie | sid=…; HttpOnly; Secure; SameSite=Lax | 세션 쿠키에는 HttpOnly와 Secure가 필요 |
Access-Control-Allow-Origin | https://app.example.com | CORS: 자격 증명이 포함된 요청에는 절대 * 사용 금지 |
cURL
| 작업 | 코드 |
|---|---|
| 상태와 헤더 표시 | curl -i https://api.example.com/users/1 |
| 요청/응답 전체 추적 | curl -v https://api.example.com/users/1 |
| JSON POST | curl -X POST https://api.example.com/users \
-H 'Content-Type: application/json' \
-d '{"email":"qa@example.com"}' |
| Bearer 토큰 | curl -H "Authorization: Bearer $TOKEN" https://api.example.com/me |
| Basic 인증 | curl -u user:pass https://api.example.com/admin |
| 리디렉션 따라가기 | curl -L https://example.com/old |
| 상태 코드만 출력 | curl -s -o /dev/null -w '%{http_code}' https://api.example.com/health |
| 스크립트에서 4xx/5xx면 실패 처리 | curl --fail-with-body https://api.example.com/health |
Windows cmd에서는 작은따옴표를 큰따옴표로 바꾸고 안쪽 따옴표는 이스케이프하세요.
모든 응답에 대한 체크리스트
| 확인 항목 | 예시 |
|---|---|
| 상태 코드 | "아무 2xx"가 아니라 정확히 201 |
| 본문 스키마 | 필수 필드 존재, 올바른 타입, 불필요한 민감 필드 없음 |
| 값 | 입력한 값이 그대로 반환되고, 계산된 필드(합계, 날짜)가 정확함 |
| 헤더 | Content-Type, Location, Cache-Control |
| 오류 형태 | 유용한 메시지를 담은 일관된 오류 형식 (예: RFC 9457 problem details) |
| 부수 효과 | 다시 GET했을 때 레코드가 있는지(또는 없는지) |
| 응답 시간 | 합의된 기준 이내 |