HTTP API 설계 기초
HTTP API는 웹 애플리케이션이나 서비스에서 데이터를 주고받기 위해 설계되는 인터페이스이다.
API를 설계할 때 가장 중요한 요소 중 하나는 리소스 식별(Resource Identification) 이다.
API 요구사항 예시
회원 정보를 관리하는 API를 설계한다고 가정한다.
기능 요구사항은 다음과 같다.
- 회원 목록 조회
- 회원 조회
- 회원 등록
- 회원 수정
- 회원 삭제
리소스 식별의 중요성
API 설계에서 가장 중요한 점은 각 요청이 어떤 리소스를 대상으로 하는지 명확히 식별하는 것이다.
- URI를 통해 리소스를 정확히 구분해야 한다.
- 같은 리소스라도 다양한 동작(GET, POST, PUT, DELETE)에 따라 URI 설계를 달리할 수 있다.
- 리소스 식별이 명확하지 않으면 API 사용자가 혼란을 겪고, 유지보수도 어려워진다.
설계 팁
- 컬렉션과 단일 리소스를 구분
- /members → 회원 전체(컬렉션)
- /members/{id} → 특정 회원(단일 리소스)
- 동작은 HTTP 메서드로 표현
- /create-member, /update-member 같은 URI는 지양
API 설계에서 URI와 리소스 식별
API를 설계할 때 가장 중요한 개념 중 하나는 리소스(Resource) 식별이다.
URI(Uniform Resource Identifier)는 인터넷에서 리소스를 구분하고 접근하기 위해 사용되는데, 단순히 기능이나 동작을 URI에 포함하는 것이 아니라 리소스 자체를 명확히 표현해야 한다.
리소스란 무엇인가?
많은 초보자들이 API를 설계할 때 “회원 등록”, “회원 수정”과 같은 동작 자체를 URI로 만들곤 한다.
그러나 이것은 잘못된 접근이다.
- 리소스란 데이터의 개념, 객체 자체를 의미한다.
- “회원”이라는 개념 자체가 바로 리소스이다.
- 따라서 URI는 회원이라는 리소스를 식별하도록 설계해야 한다.
즉, 등록, 수정, 조회 등 동작은 URI가 아니라 HTTP 메서드(GET, POST, PUT, DELETE) 로 구분하는 것이 올바른 설계이다.
리소스와 행위 분리
URI /members/{id}만 사용하면 동작을 구분할 수 없다는 문제점이 있다.
해결 방법은 다음과 같다.
- 리소스 식별은 URI
- 예: 회원 → /members 또는 /members/{id}
- 행위 구분은 HTTP 메서드
- GET → 조회
- POST → 등록
- PUT → 수정
- DELETE → 삭제
정리
- URI = 리소스 식별
- HTTP 메서드 = 리소스를 대상으로 하는 행위
- RESTful 설계를 따르면 API가 직관적이고 유지보수가 용이하다
HTTP 메서드: GET
HTTP에서 GET 메서드는 리소스를 조회할 때 사용된다.
클라이언트가 서버로부터 데이터를 가져오는 용도로만 사용하며, 서버의 상태를 변경하지 않는 것이 원칙이다.
GET 요청 시 데이터 전달
GET 요청에서는 서버에 전달할 데이터를 일반적으로 **쿼리 파라미터(Query Parameter, Query String)**를 통해 전달한다.
- URL 예시:
GET /members?age=20&city=Seoul HTTP/1.1
- ? 뒤에 key=value 형태로 데이터를 붙이며, 여러 개는 &로 구분한다.
참고: GET 요청에서 메시지 바디를 사용해 데이터를 보내는 것도 가능하지만, 대부분의 서버나 라이브러리에서 제대로 지원하지 않기 때문에 권장하지 않는다.
GET 요청 흐름
- 리소스 조회 - 메시지 전달
클라이언트가 요청 URL과 쿼리 파라미터를 포함한 GET 메시지를 생성한다. - 리소스 조회 - 서버 도착
TCP/IP를 통해 GET 요청이 서버에 도착한다.
서버는 요청을 파싱하여 어떤 리소스를 조회할지 결정한다. - 리소스 조회 - 응답 데이터 반환
서버는 요청한 리소스를 조회한 후, HTTP 응답 메시지의 바디에 데이터를 담아 클라이언트로 전송한다.
GET 메서드는 읽기 전용 작업에 적합하며, 조회 대상과 필요한 데이터를 URI로 명확히 전달하는 것이 중요하다.
HTTP 메서드: POST
HTTP에서 POST 메서드는 서버에 데이터를 전달하고 처리할 때 사용된다.
주로 신규 리소스를 등록하거나, 요청 데이터를 기반으로 서버 측 프로세스를 수행하는 용도로 사용된다.
POST 요청 데이터 전달
- POST 요청은 데이터를 **메시지 바디(Message Body)**에 담아 서버로 전송한다.
- 서버는 메시지 바디에 담긴 데이터를 받아 처리하며, 신규 리소스 생성, 데이터 추가, 특정 프로세스 실행 등 다양한 작업을 수행할 수 있다.
- 예시
POST /members HTTP/1.1
Content-Type: application/json
{
"name": "홍길동",
"email": "hong@example.com",
"age": 25
}
참고: GET과 달리 POST는 데이터를 URL에 담지 않고 메시지 바디를 사용하기 때문에 전송할 수 있는 데이터 용량이 크다.
POST 요청 흐름
- 리소스 등록 - 메시지 전달
클라이언트가 POST 메시지에 요청 데이터를 포함하여 서버로 전송한다. - 리소스 등록 - 신규 리소스 생성
서버는 전달된 데이터를 처리하여 신규 리소스를 생성하거나, 기존 리소스에 데이터를 추가한다. - 리소스 등록 - 응답 데이터 반환
서버는 처리 결과를 HTTP 응답 메시지로 클라이언트에게 반환한다.
POST 요청의 의미
스펙상 POST 메서드는 대상 리소스가 요청에 포함된 표현을 처리하도록 요청하는 것이다.
즉, “이 URI에 도착한 데이터를 어떻게 처리할지”는 리소스마다 정의되어야 한다.
활용 사례
- HTML Form 데이터 처리
- 회원가입, 주문, 설문 응답 제출 등
- 게시판, 뉴스, 블로그 게시
- 게시글 작성, 댓글 달기
- 신규 리소스 생성
- 아직 서버가 식별하지 않은 주문, 문서, 상품 등
- 기존 리소스에 데이터 추가
- 문서 끝에 내용 추가, 기존 리스트에 항목 추가
요약
POST 요청은 크게 세 가지 경우에 사용된다.
- 새 리소스를 생성(등록)할 때
- 요청 데이터를 처리해야 할 때
- 다른 HTTP 메서드로 처리하기 애매한 경우
POST는 서버에 데이터를 전달하고 처리하는 범용적인 메서드이며, 리소스 설계와 처리 로직에 따라 다양하게 활용된다.
HTTP 메서드: PUT
HTTP에서 PUT 메서드는 특정 리소스를 완전히 대체하거나, 해당 리소스가 존재하지 않을 경우 새로 생성할 때 사용된다.
특징
- 클라이언트가 리소스를 식별
- PUT 요청에서는 클라이언트가 수정하거나 생성할 리소스의 URI를 명확히 알고 지정한다.
- 예: /members/123 → ID 123 회원 리소스를 대상으로 지정
- 리소스 전체 교체
- 요청에 포함된 데이터를 기반으로 기존 리소스를 완전히 대체한다.
- 일부만 변경하는 것이 아니라, 리소스 전체가 요청 데이터로 바뀐다.
- 리소스가 없으면 생성
- 지정된 URI에 리소스가 없으면 새로 생성된다.
POST와의 차이점
| 항목 | POST | PUT |
| 리소스 위치 결정 | 서버가 결정 | 클라이언트가 URI 지정 |
| 리소스 생성 | 서버가 처리 | 클라이언트가 URI로 직접 지정 가능 |
| 리소스 변경 | 새로운 리소스 생성 또는 프로세스 실행 | 기존 리소스 전체 대체 |
예시
PUT /members/123 HTTP/1.1
Content-Type: application/json
{
"name": "홍길동",
"email": "hong_new@example.com",
"age": 26
}
- 서버는 회원 ID 123 리소스를 요청 데이터로 전체 대체한다.
- 만약 ID 123 회원이 없다면, 새로 생성된다.
PUT은 클라이언트가 리소스를 명확히 식별하고, 리소스를 전체적으로 교체하거나 생성할 때 사용하는 정확하고 예측 가능한 메서드이다.
HTTP 메서드: PATCH
HTTP에서 PATCH 메서드는 리소스 전체가 아니라 일부 속성만 변경할 때 사용된다.
PUT과 달리 리소스를 완전히 대체하지 않고, 필요한 부분만 수정할 수 있어 효율적이다.
특징
- 부분 수정
- 요청에 포함된 데이터만 리소스에 적용된다.
- 전체 데이터를 전송할 필요가 없어 네트워크와 서버 리소스를 절약할 수 있다.
- 리소스 식별 필요
- URI로 어떤 리소스를 수정할지 지정해야 한다.
- 효율적 업데이트
- 작은 변경 사항만 서버에 전달하고 처리할 수 있다.
예시
PATCH /members/123 HTTP/1.1
Content-Type: application/json
{
"email": "hong_patch@example.com"
}
- 서버는 회원 ID 123의 이메일 속성만 업데이트한다.
- 나머지 리소스 데이터는 변경되지 않는다.
PATCH는 일부 데이터만 수정하고 싶을 때 사용되며, PUT보다 효율적이지만 전체 교체가 필요한 경우에는 PUT을 사용해야 한다.
HTTP 메서드: DELETE
HTTP에서 DELETE 메서드는 특정 리소스를 삭제할 때 사용된다.
특징
- 리소스 식별 필요
- URI로 어떤 리소스를 삭제할지 명확히 지정해야 한다.
- 예: /members/123 → ID 123 회원 리소스를 삭제
- 서버 상태 변경
- DELETE 요청은 서버에 저장된 리소스를 제거하므로 서버 상태를 변경한다.
- 메시지 바디 사용 거의 없음
- 일반적으로 DELETE 요청에서는 메시지 바디를 포함하지 않는다.
- 필요한 경우 서버에서 별도로 지원할 수 있지만 표준은 아니다.
예시
DELETE /members/123 HTTP/1.1
- 서버는 회원 ID 123 리소스를 삭제하고, 성공 여부를 상태 코드(예: 200 OK, 204 No Content)로 반환한다.
DELETE 메서드는 리소스를 제거할 때 명확하고 직관적인 방법을 제공하며, RESTful API 설계에서 필수적인 동작이다.
HTTP 메서드의 속성: Safe, Idempotent, Cacheable
HTTP 메서드는 단순히 동작(GET, POST, PUT 등)을 구분하는 것 외에도, 속성에 따라 안전성과 반복 호출 가능성, 캐시 여부 등을 정의할 수 있다.
이러한 속성을 이해하면 RESTful API 설계와 클라이언트/서버 동작을 예측하는 데 유리하다.
1. Safe (안전)
- 정의: 호출해도 리소스를 변경하지 않는 메서드
- 주로 조회 목적의 메서드가 안전하다.
- 예시:
- GET: 리소스를 조회할 뿐 서버 상태를 변경하지 않는다.
- HEAD: 리소스 헤더만 조회, 변경 없음
Safe 메서드는 서버 상태를 변경하지 않으므로, 여러 번 호출해도 안전하게 사용 가능하다.
2. Idempotent (멱등)
- 정의: 같은 요청을 한 번 호출하든, 여러 번 호출하든 최종 결과가 동일한 메서드
- 반복 호출 시 서버 상태 변화가 일정함을 보장한다.
예시
| 메서드 | 멱등 여부 | 설명 |
| GET | O | 여러 번 조회해도 리소스 상태가 변하지 않음 |
| PUT | O | 리소스를 요청 데이터로 대체, 여러 번 호출해도 최종 결과 동일 |
| DELETE | O | 리소스를 삭제, 여러 번 호출해도 삭제된 상태는 동일 |
| POST | X | 반복 호출 시 새로운 리소스 생성 가능, 중복 처리 필요 |
POST는 멱등하지 않으므로 결제, 회원가입 등에서는 주의가 필요하다.
3. Cacheable (캐시 가능)
- 정의: 서버 응답을 클라이언트나 프록시가 캐시해도 되는가
- 캐시 가능 여부에 따라 불필요한 네트워크 호출을 줄일 수 있다.
예시
| 메서드 | 캐시 가능 여부 | 설명 |
| GET | O | 주로 캐시로 사용, 서버 상태 변경 없음 |
| HEAD | O | 응답 헤더 캐시 가능 |
| POST | O* | 가능하지만 본문까지 캐시 키로 고려해야 해 실제 사용 어려움 |
| PATCH | O* | 부분 수정 응답 캐시 가능하지만 구현 어려움 |
실제로 캐시로 사용되는 메서드는 대부분 GET과 HEAD가 중심이다.
HTTP 메서드 속성을 이해하면 API 호출의 안전성, 반복 처리, 성능 최적화 측면에서 설계와 사용이 훨씬 명확해진다.