HTTP 메서드와 상태 코드는 클라이언트와 서버 간의 의사소통 규약이다. 메서드는 클라이언트가 서버에게 무엇을 원하는지 표현하고, 상태 코드는 서버가 요청을 어떻게 처리했는지 알려준다.
RESTful API 설계에서 HTTP 메서드와 상태 코드를 올바르게 사용하는 것은 직관적이고 예측 가능한 인터페이스를 만드는 핵심이다. 같은 URL이라도 메서드에 따라 완전히 다른 동작을 수행하며, 상태 코드로 성공과 실패를 명확히 구분할 수 있다.
HTTP 메서드
HTTP 메서드는 리소스에 대해 수행할 작업을 정의한다. 각 메서드는 고유한 의미와 특성을 가진다.
GET
GET은 리소스를 조회할 때 사용한다. 서버에 저장된 데이터를 가져오지만, 데이터를 변경하지는 않아 안전(Safe) 하다. 서버의 상태를 변경하지 않으므로 여러 번 호출해도 동일한 결과를 얻는다.
GET 요청은 같은 요청을 여러 번 보내도 결과가 동일한 멱등성(Idempotent) 을 가져 브라우저는 GET 요청을 캐시한다.
GET 요청은 본문이 없이 모든 파라미터는 URL 쿼리 스트링으로 전달한다.
POST
POST는 새로운 리소스를 생성할 때 사용되며 서버에 데이터를 전송해 새로운 엔티티를 만든다. 같은 요청을 여러 번 보내면 매번 새로운 리소스가 생성된다. 같은 사용자 생성 요청을 두 번 보내면 중복된 사용자가 만들어질 수 있다.
POST 응답은 생성된 리소스의 위치를 Location 헤더로 반환하는 것이 일반적이다.
PUT
PUT은 리소스를 완전히 대체할 때 사용한다. 기존 리소스가 있으면 전체를 교체하고, 없으면 새로 생성한다.
PUT은 멱등성을 가져 같은 요청을 여러 번 보내도 결과는 동일하다. 리소스가 마지막 요청의 내용으로 덮어씌워진다.
일부 필드만 전송하면 나머지 필드는 삭제되거나 기본값으로 초기화될 수 있어 모든 필드를 포함해야 한다.
PATCH
PATCH는 리소스를 부분적으로 수정할 때 사용한다. PUT과 달리 변경할 필드만 전송한다.
PATCH는 일반적으로 멱등성을 가지지만, 구현에 따라 다를 수 있다. 단순 필드 교체는 멱등적이지만, 증감 연산과 같은 멱등적이지 않은 경우도 있다..
DELETE
DELETE는 리소스를 삭제할 때 사용한다.
같은 리소스를 여러 번 삭제해도 결과는 동일한 멱등성을 갖는다. 두 번째 요청부터는 이미 삭제된 상태이므로 404 Not Found를 반환할 수 있지만, 리소스가 없다는 상태는 동일하다.
일반적으로 DELETE 응답은 본문을 포함하지 않는다.
HEAD
HEAD는 GET과 동일하지만 응답 본문을 포함하지 않는다. 헤더 정보만 필요할 때 사용한다.
리소스의 존재 여부를 확인하거나, 메타데이터만 조회할 때 유용하다. Content-Length로 파일 크기를 확인하거나, Last-Modified로 수정 시간을 체크할 수 있다.
OPTIONS
OPTIONS는 서버가 지원하는 메서드를 조회할 때 사용하며 특정 리소스에 대해 어떤 메서드가 허용되는지 확인한다. 서버는 Allow 헤더로 지원하는 메서드를 반환한다.
CORS(Cross-Origin Resource Sharing)에서 Preflight 요청으로 사용된다. 브라우저는 실제 요청 전에 OPTIONS로 서버가 해당 출처의 요청을 허용하는지 확인한다.
HTTP 상태 코드
HTTP 상태 코드는 요청 처리 결과를 나타내는 3자리 숫자다. 첫 번째 자리는 응답의 클래스를 나타낸다.
-
1xx: 정보성 응답으로 요청을 받았으며 처리가 진행 중임을 나타내며 실무에서 거의 사용되지 않는다.
-
100 Continue: 클라이언트가 요청 본문을 계속 전송해도 됨을 의미한다. 큰 파일을 업로드할 때 사용된다.
-
101 Switching Protocols: 프로토콜 전환 요청을 수락했음을 나타낸다. WebSocket 연결 시 HTTP에서 WebSocket으로 전환할 때 사용된다.
-
-
2xx: 요청이 성공적으로 처리되었음을 나타낸다.
-
200 OK: 요청이 성공함을 의미하며 가장 일반적인 응답으로, GET 요청의 결과를 반환하거나 처리 완료를 알린다.
-
201 Created: 새로운 리소스가 생성될때 POST 요청 성공 시 사용하며,
Location헤더로 생성된 리소스 위치를 제공한다. -
204 No Content: 요청은 성공했지만 응답 본문이 없고, DELETE 성공 시나 업데이트 후 반환할 데이터가 없을 때 사용한다.
-
202 Accepted: 요청이 접수되었지만 처리가 완료되지 않은 비동기 처리나 배치 작업에 사용된다.
-
-
3xx: 클라이언트가 요청을 완료하려면 추가 작업이 필요한 리디렉션을 나타낸다.
-
301 Moved Permanently: 리소스가 영구적으로 이동해 검색 엔진은 새 URL을 색인한다.
-
302 Found: 리소스가 일시적으로 다른 위치에 있어 원래 URL을 계속 사용해야 한다.
-
304 Not Modified: 리소스가 수정되지 않아 캐시된 버전을 사용할 수 있다.
If-Modified-Since나If-None-Match헤더와 함께 사용된다. -
307 Temporary Redirect: 302와 유사하지만, 메서드와 본문을 변경하지 않고 리다이렉트한다. POST 요청은 리다이렉트 후에도 POST로 유지된다.
-
308 Permanent Redirect: 301과 유사하지만, 메서드와 본문을 변경하지 않는다.
-
-
4xx: 클라이언트의 요청에 오류가 있음을 나타낸다.
-
400 Bad Request: 요청이 잘못된 문법 오류, 유효하지 않은 JSON, 필수 필드 누락 등이 원인이다.
-
401 Unauthorized: 인증이 필요한 로그인하지 않았거나 토큰이 만료되었을 때 사용한다.
-
403 Forbidden: 인증은 되었지만 해당 리소스에 접근할 권한이 없는 경우 사용된다.
-
404 Not Found: 존재하지 않는 URL이나 삭제된 경우 리소스를 찾을 수 없을 때 이 코드를 반환한다.
-
405 Method Not Allowed: GET만 지원하는 엔드포인트에 POST를 보낼 때와 같은 메서드가 허용되지 않는 경우 발생한다.
-
409 Conflict: 요청이 현재 서버 상태와 충돌하는 중복된 리소스 생성이나 동시성 문제에 사용한다.
-
429 Too Many Requests: 너무 많은 요청을 보내 Rate limiting에 걸리는 경우 사용된다.
-
-
5xx: 서버가 요청을 처리하는 중 오류가 발생했음을 나타낸다.
-
500 Internal Server Error: 서버 내부 오류인 예상치 못한 예외, 프로그래밍 오류 등이 원인이다.
-
502 Bad Gateway: 게이트웨이나 프록시가 상위 서버로부터 잘못된 응답을 받은 경우 사용되며 업스트림 서버가 다운되었거나 응답이 잘못되었을 때 발생한다.
-
503 Service Unavailable: 서비스를 일시적으로 사용할 수 없다는 의미로 서버 과부하, 유지보수 중일 때 사용한다.
-
504 Gateway Timeout: 게이트웨이나 프록시가 상위 서버로부터 응답을 제시간에 받지 못한 경우로 타임아웃이 발생했을 때 반환한다.
-
RESTful API 설계 원칙
HTTP 메서드와 상태 코드를 올바르게 조합하면 직관적인 API를 만들 수 있다.
- CRUD 매핑: 데이터베이스의 CRUD 작업을 HTTP 메서드로 표현한다.
Create → POST /api/users → 201 Created
Read → GET /api/users/123 → 200 OK
Update → PUT /api/users/123 → 200 OK
Update → PATCH /api/users/123 → 200 OK
Delete → DELETE /api/users/123 → 204 No Content
- 컬렉션과 단일 리소스: 복수형 경로는 컬렉션을, 특정 ID는 단일 리소스를 나타낸다.
GET /api/users # 모든 사용자 조회 → 200 OK
POST /api/users # 새 사용자 생성 → 201 Created
GET /api/users/123 # 특정 사용자 조회 → 200 OK
PUT /api/users/123 # 특정 사용자 전체 수정 → 200 OK
PATCH /api/users/123 # 특정 사용자 부분 수정 → 200 OK
DELETE /api/users/123 # 특정 사용자 삭제 → 204 No Content
- 중첩된 리소스: 리소스 간의 관계를 경로로 표현한다.
GET /api/users/123/posts # 사용자 123의 게시글 목록
POST /api/users/123/posts # 사용자 123의 새 게시글 생성
GET /api/posts/456/comments # 게시글 456의 댓글 목록
- 에러 처리: 명확한 상태 코드와 에러 메시지를 제공한다.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"email": "Invalid email format",
"age": "Must be at least 18"
}
}
- 버전 관리: API 버전을 URL이나 헤더로 명시한다.
# URL 버전
GET /api/v1/users
GET /api/v2/users
# 헤더 버전
GET /api/users
Accept: application/vnd.example.v1+json
실무에서의 활용
같은 리소스는 같은 방식으로 일관성 있는 API 설계가 필요하다. 사용자 조회가 GET /api/users/123이면, 제품 조회도 GET /api/products/456처럼 동일한 패턴을 따른다.
성공은 2xx, 클라이언트 오류는 4xx, 서버 오류는 5xx로 명확히 구분하는 등 적절한 상태 코드 선택해 개발해야한다.
네트워크 불안정으로 요청이 중복될 수 있지만, 멱등성을 가진 메서드(GET, PUT, DELETE)는 재시도해도 안전하다.
HTTP 메서드와 상태 코드는 웹 API의 언어다. 이를 올바르게 사용하면 문서 없이도 직관적으로 이해할 수 있는 API를 만들 수 있다.