REST API
"Representational State Transfer (REST) is an architectural style for distributed hypermedia systems."
— 로이 필딩(Roy Fielding)의 2000년 박사 학위 논문 중.
"REST API의 진짜 매력은 모두가 REST API라고 간판을 걸어 놓았지만, 사실 그 누구도 정형화된 REST의 핵심 제약을 완전히 지키지 않고 있다는 이중성에 있다." 실무에서 HATEOAS를 구현하느니 차라리 노션에 API 문서를 최신화해 두는 게 모두에게 유익하다.(...)
1. 개요
REST API는 웹의 기존 인프라인 HTTP를 그대로 활용하면서도 데이터를 가장 효율적이고 직관적으로 교환하기 위해 정의된 아키텍처 스타일(Architectural Style)이다. 로이 필딩이 2000년 자신의 박사 논문에서 발표한 이후, SOAP 진영의 복잡한 명세 규격을 관속에 집어넣으며 웹 생태계의 표준 API 구조로 독점 군림하게 되었다.
원칙은 명확하고 아름답지만, 실무에서 마주하는 REST API는 대부분 이름만 빌려온 "JSON 전송용 고성능 HTTP API"인 경우가 허다하다. RESTful의 엄격한 교과서적 제약을 고집하면 비즈니스 개발 기간이 3배로 불어나는 마술이 펼쳐지기 때문이다.(...)
2. REST의 핵심 4대 원칙과 URI 디자인
2.1. 자원의 식별과 URI 디자인 (Uniform Resource Identifier)
모든 자원은 고유한 URI(웹 주소)를 통해 표현된다. 명사형 단어를 기반으로 구조적 계층을 표현하는 것이 정석이다.
- Good:
GET /users/123(ID가 123인 유저 조회) - Bad:
POST /get_user_by_id?id=123(행위를 URI에 섞는 혼종 설계)1
2.2. 표현을 통한 자원의 조작 (HTTP Method)
자원의 행위는 오직 HTTP Verbs를 통해서만 나타낸다. 대표적인 CRUD 대응 관계는 다음과 같다:
- GET: 자원 조회 (멱등성 가짐, 캐싱 가능)
- POST: 자원 생성 (비멱등성)
- PUT: 자원 전체 교체 (멱등성 가짐)
- PATCH: 자원 일부 수정 (일반적으로 비멱등성)
- DELETE: 자원 삭제 (멱등성 가짐)
2.3. 무상태성 (Statelessness)
클라이언트의 상태(세션 등)를 서버에 절대 저장하지 않는다. 각 요청은 그 자체로 완전히 독립적이며, 요청에 필요한 모든 컨텍스트(API Key, JWT 등)를 동반해야 한다. 이 무상태성 덕분에 서버는 세션 관리 부담을 덜고 미친 듯이 수평 확장할 수 있게 된다.
2.4. 캐시 가능성 (Cacheability)
HTTP의 캐싱 인프라를 고스란히 사용할 수 있다. GET 요청 시 적절한 캐시 제어 헤더(Cache-Control)를 설정하면 클라이언트나 중간 프록시 서버에 응답을 보관해 두어 데이터베이스 서버의 트래픽을 드라마틱하게 아낄 수 있다.
3. 멱등성(Idempotency)과 실무 타협
3.1. 멱등성 (Idempotency)이란?
동일한 요청을 한 번 보내든, 백 번 보내든 서버의 상태가 똑같아야 함을 의미한다. GET은 단순히 조회만 하므로 당연히 멱등하며, PUT이나 DELETE 역시 여러 번 실행해도 대상이 완전히 대체되거나 이미 삭제되었으므로 결과적으로 서버 상태는 동일하다. 반면 POST는 보낼 때마다 새로운 데이터가 계속 생성되므로 비멱등성이다. 이 멱등성은 네트워크가 흔들려 재요청을 보낼 때 시스템 안정성을 수호하는 최고 수준의 방어막이 된다.
3.2. HATEOAS와 자기 서술성(Self-descriptive)의 장벽
로이 필딩이 말한 진짜 RESTful의 핵심은 메시지가 스스로의 형식을 규정해야 하고(Self-descriptive), 응답 내에 다음 행동을 유도하는 하이퍼링크가 동적으로 포함되어야 한다(HATEOAS)는 것이다. 그러나 현대 프론트엔드 개발자들은 그냥 Swagger API 문서를 켜놓고 하드코딩으로 URI를 엮어 화면을 만든다. 이 때문에 실무에서는 완벽한 HATEOAS를 사치스러운 이론으로 간주하고, 대충 JSON과 HTTP Method만 잘 맞춰도 서로 "우린 아주 RESTful한 API를 만들었다"고 덕담을 주고받는다.2
4. REST API 종교 분쟁과 밈
4.1. 그건 RESTful하지 않네요
사수가 신입 개발자의 Pull Request 코드를 반려할 때 가장 우아하게 공격할 수 있는 치트키 문장이다. URI에 동사가 조금이라도 들어가거나 HTTP 상태 코드를 대충 200 OK로 퉁쳤을 때, 시니어의 날카로운 지적과 함께 키보드 배틀이 유발된다. 하지만 그 시니어가 과거에 작성한 구형 코드들도 정통 REST와는 백만 광년 떨어져 있는 경우가 대반사다.(...)
4.2. POST 만능주의와 GET으로 수정하기
REST 원칙을 지키기 귀찮아하는 레거시 시스템이나 일부 개발자들은 모든 API 호출을 POST 하나로 처리해 버리는 악행을 저지른다. 심지어 보안을 핑계로 GET 주소 창에 민감 정보를 지우겠답시고 모든 조회를 POST로 도배하기도 한다. 반대로, 브라우저 주소창에 주소를 쳐서 손쉽게 값을 수정하려고 GET /users/123/delete 같은 파멸적인 API를 파놓았다가 구글 검색봇이 링크를 긁어가는 바람에 DB가 완파되는 참극도 실존한다.3
5. 여담
- 로이 필딩의 가차 없는 블로그: 로이 필딩은 자신의 개인 블로그에 "HATEOAS와 자기 서술성을 안 지킬 거면 제발 내 아키텍처 명칭(REST)을 무단 도용하지 말고 그냥 HTTP API라고 불러라"라는 글을 직접 박제하며 전 세계 웹 업계에 묵직한 돌직구를 날렸다.
- 대안책 GraphQL의 추격: REST API의 한계인 오버페치(Overfetching - 안 쓰는 필드까지 다 내려옴)와 언더페치(Underfetching - 필요한 데이터를 얻기 위해 여러 번 요청해야 함)를 타파하기 위해 페이스북이 GraphQL을 만들었으나, 이 역시 캐싱 구현이 무지막지하게 까다로워 여전히 대세는 REST API가 지배하고 있다.
- 상태 코드의 디테일: RESTful을 정석으로 준수하는 개발자는 생성 성공 시
201 Created를, 데이터가 없을 때204 No Content를 정확히 뱉어내지만, 귀차니즘에 찌든 실무자들은 그저 무조건200 OK에{ "success": false, "error": "Not Found" }같은 기괴한 바디를 섞어 반환하곤 한다.