2025-09-22 21:51
-
RESTful API는 HTTP 프로토콜을 기반으로 자원(Resource)을 정의하고, 그 자원에 대한 상태(State)를 주고받는 웹 서비스 아키텍처 원칙이다.
-
클라이언트-서버 분리, 무상태성 등 6가지 제약 조건을 통해 확장 가능하고 유연한 시스템을 구축하는 것을 목표로 한다.
-
URI는 자원을 명사로 표현하고, 행위는 GET, POST, PUT, DELETE 등 HTTP 메서드를 사용해 명확히 구분하여 설계한다.
개발자 필수 교양 RESTful API 완벽 정복 핸드북
오늘날 우리가 사용하는 대부분의 웹 서비스와 애플리케이션은 보이지 않는 곳에서 서로 끊임없이 대화한다. 날씨 앱이 기상청 서버에서 최신 정보를 가져오고, 쇼핑 앱이 결제 시스템과 연동하는 이 모든 과정의 중심에는 API(Application Programming Interface)가 있다. 그중에서도 웹 개발의 표준처럼 자리 잡은 ‘RESTful API’는 현대 소프트웨어 개발자라면 반드시 이해해야 할 핵심 개념이다.
이 핸드북은 RESTful API가 무엇인지, 왜 만들어졌는지 그 탄생 배경부터 시작하여 핵심 구조와 제약 조건, 올바른 사용법, 그리고 더 나아가 깊이 있는 심화 내용까지 모든 것을 담았다. 단순히 정보를 나열하는 것을 넘어, 비유와 예시를 통해 REST의 철학을 온전히 이해하고 실무에 적용할 수 있도록 안내하는 것이 이 글의 목표다.
1. REST의 탄생 배경 혼돈의 시대에 나타난 구원자
REST가 등장하기 전 1990년대 후반, 웹 서비스들은 각자의 방식으로 통신하는 ‘춘추전국시대’를 겪고 있었다. CORBA, DCOM, SOAP(XML-RPC) 등 다양한 기술들이 있었지만, 이들은 특정 플랫폼이나 프로그래밍 언어에 종속되거나, 구조가 지나치게 복잡하여 시스템 간의 연동을 어렵게 만들었다. 특히 SOAP는 XML을 기반으로 정해진 규칙(규약)이 너무 많고 무거워 간단한 데이터를 주고받는 데도 큰 비용이 들었다.
마치 각기 다른 언어와 도량형을 사용하는 여러 나라가 교역을 하려는 것과 같았다. 무역을 할 때마다 복잡한 통역과 환산 과정을 거쳐야 했고, 이는 전체 시스템의 유연성과 확장성을 크게 저해했다.
이러한 문제를 해결하기 위해 **로이 필딩(Roy Fielding)**은 2000년 그의 박사학위 논문에서 REST(REpresentational State Transfer)라는 아키텍처 스타일을 제안했다. 그의 목표는 거대하고 복잡한 월드 와이드 웹(WWW) 그 자체를 성공적으로 만든 아키텍처 원칙들을 정리하고, 이를 웹 서비스 설계에 적용하여 **느슨한 결합(Loose Coupling)**과 **확장성(Scalability)**을 극대화하는 것이었다. REST는 새로운 기술이 아니라, 이미 성공적으로 동작하고 있는 웹의 장점을 최대한 활용하자는 일종의 ‘설계 철학’ 또는 ‘원칙들의 집합’이다.
2. REST의 핵심 구조와 6가지 제약 조건
REST를 제대로 이해하려면 그 이름부터 뜯어봐야 한다. ‘Representational State Transfer’는 ‘자원의 표현을 통한 상태 전달’로 번역할 수 있다.
-
자원 (Resource): 웹상에 존재하는 모든 것(문서, 이미지, 데이터 등)을 의미한다. 예를 들어 ‘사용자 정보’, ‘게시글’ 등이 모두 자원이다. 각 자원은 고유한 식별자(URI)를 가진다.
-
표현 (Representation): 자원을 표현하는 방식이다. 같은 ‘사용자 정보’ 자원이라도 JSON, XML, HTML 등 다양한 형태로 표현될 수 있다. 클라이언트와 서버는 이 ‘표현’을 주고받는다.
-
상태 전달 (State Transfer): 클라이언트가 서버에 요청을 보내면, 서버의 자원 상태가 변경되거나(Create, Update, Delete), 자원의 상태가 표현을 통해 클라이언트로 전달(Read)되는 것을 의미한다.
이 개념을 커피숍에 비유해 보자.
-
자원: ‘아이스 아메리카노’, ‘라떼’ 등 가게의 모든 메뉴
-
표현: 주문서에 적힌 “아이스 아메리카노, 사이즈 업, 샷 추가”라는 텍스트 (JSON 데이터에 해당)
-
상태 전달: 당신이 주문서를 점원에게 전달하는 행위. 이 행위를 통해 가게의 재고(상태)가 바뀌고, 당신은 커피(자원의 표현)를 받게 된다.
로이 필딩은 REST 아키텍처가 제대로 동작하기 위해 반드시 지켜야 할 6가지 제약 조건(Constraints)을 정의했다. 이 조건들을 충족하는 시스템을 ‘RESTful’ 하다고 부른다.
1) 클라이언트-서버 (Client-Server) 아키텍처
클라이언트와 서버의 역할을 명확히 분리하는 원칙이다.
-
클라이언트: 사용자 인터페이스(UI)와 사용자 경험(UX)에 집중. 서버에 자원을 요청한다. (예: 스마트폰 앱, 웹 브라우저)
-
서버: 자원을 관리하고 비즈니스 로직을 처리하는 데 집중. 클라이언트의 요청에 응답한다. (예: 데이터베이스, API 서버)
라이선스 제공자: Google
이는 마치 식당의 손님(클라이언트)과 주방(서버)이 분리된 것과 같다. 손님은 메뉴판을 보고 주문만 하면 되고, 주방 내부에서 어떤 요리사가 어떤 순서로 요리하는지는 알 필요가 없다. 이러한 분리 덕분에 클라이언트와 서버는 서로에게 의존하지 않고 독립적으로 개발하고 발전할 수 있다.
2) 무상태성 (Stateless)
서버가 클라이언트의 이전 상태를 저장하거나 기억하지 않는다는 원칙이다. 각 요청은 그 자체로 완전한 정보를 담고 있어야 한다.
식당 점원이 당신이 이전에 무엇을 주문했는지 기억하지 않는다고 생각하면 쉽다. 당신은 주문할 때마다 “아이스 아메리카노 한 잔 주세요”라고 처음부터 끝까지 명확하게 말해야 한다.
장점:
-
확장성: 서버는 클라이언트 상태를 관리할 필요가 없으므로, 요청이 들어오는 대로 어떤 서버가 처리해도 상관없다. 이는 서버를 수평적으로 확장(Scale-out)하기 매우 용이하게 만든다.
-
단순성: 서버의 구현이 단순해진다.
-
신뢰성: 특정 서버에 장애가 발생해도 다른 서버가 요청을 이어받아 처리할 수 있다.
3) 캐시 가능 (Cacheable)
클라이언트는 서버의 응답을 캐싱(임시 저장)할 수 있어야 한다. 서버는 응답 데이터가 캐싱이 가능한지 아닌지를 HTTP 헤더를 통해 명시해야 한다.
매번 똑같이 “물 한 잔 주세요”라고 요청할 때마다 주방 깊숙한 곳에서 물을 떠오는 것이 아니라, 점원이 가까운 정수기(캐시)에서 바로 물을 따라주는 것과 같다. 이는 서버의 부하를 줄이고, 클라이언트의 응답 속도를 크게 향상시킨다.
4) 계층화 시스템 (Layered System)
클라이언트는 자신이 직접 통신하는 서버만 알 뿐, 그 뒤에 프록시 서버, 로드 밸런서, 암호화 계층 등 다른 서버들이 존재하는지 알 수 없다.
손님은 오직 웨이터와만 소통한다. 주문을 받은 웨이터가 주방장에게 전달하든, 보조 요리사에게 전달하든 손님은 신경 쓰지 않는다. 이러한 구조는 시스템의 유연성과 보안을 높여준다.
5) 균일한 인터페이스 (Uniform Interface)
REST를 가장 REST답게 만드는 핵심 원칙이며, 4개의 하위 제약 조건으로 나뉜다. 시스템 전체를 단순화하고 각 부분의 독립적인 진화를 가능하게 한다.
5-1. 자원의 식별 (Identification of Resources)
자원은 URI(Uniform Resource Identifier)를 통해 고유하게 식별되어야 한다.
5-2. 표현을 통한 자원 조작 (Manipulation of Resources Through Representations)
클라이언트는 자원의 표현(JSON, XML 등)과 메타데이터를 통해 자원의 상태를 변경할 수 있어야 한다.
5-3. 자기 서술적 메시지 (Self-descriptive Messages)
각 메시지는 자신을 어떻게 처리해야 하는지에 대한 충분한 정보를 담고 있어야 한다. 예를 들어, HTTP 헤더에 Content-Type: application/json이라고 명시하여 메시지 본문이 JSON 형식임을 알려주는 것이다.
5-4. 하이퍼미디어 애플리케이션 상태의 엔진 (HATEOAS)
클라이언트는 URI를 미리 알고 있을 필요 없이, 서버로부터 받은 응답에 포함된 링크를 통해 다음에 수행할 수 있는 동작을 파악할 수 있어야 한다. (심화 내용에서 자세히 다룸)
6) 주문형 코드 (Code-On-Demand) - 선택 사항
서버가 클라이언트에 실행 가능한 코드(예: JavaScript)를 전송하여 클라이언트의 기능을 일시적으로 확장할 수 있게 하는 원칙이다. 유일하게 선택적으로 적용 가능한 제약 조건이다.
3. RESTful API 사용법 실전 가이드
이론을 알았다면 이제 실제로 RESTful API를 어떻게 설계하고 사용하는지 알아보자.
1) URI 설계: 자원을 명확하게 표현하라
URI는 자원을 나타내는 주소다. RESTful한 URI는 동사가 아닌 명사를 사용하여 자원을 표현하고, 계층 구조를 나타내는 것이 좋다.
| 좋은 예 (Good) | 나쁜 예 (Bad) | 설명 |
|---|---|---|
/users | /getUsers | 행위(get)는 URI에 포함하지 않는다. |
/users/123 | /getUserById?id=123 | 특정 자원을 명확히 식별한다. |
/users/123/posts | /getPostsByUser?userId=123 | 자원 간의 관계를 계층적으로 표현한다. |
/posts?author=john&page=2 | /searchPostsByAuthorJohnPage2 | 필터링, 정렬 등은 쿼리 파라미터를 사용한다. |
Sheets로 내보내기
2) HTTP 메서드: 자원에 대한 행위를 정의하라
URI가 자원을 나타내는 명사라면, HTTP 메서드는 그 자원에 대한 행위를 나타내는 동사다.
| 메서드 | 목적 | 설명 |
|---|---|---|
| GET | 자원 조회 (Read) | 서버의 데이터를 변경하지 않고, 특정 자원의 정보를 가져온다. |
| POST | 자원 생성 (Create) | 서버에 새로운 자원을 생성한다. 요청 본문(Payload)에 생성할 자원의 정보를 담아 보낸다. |
| PUT | 자원 전체 교체/수정 (Update/Replace) | 특정 자원의 전체 정보를 새로운 정보로 교체한다. 일부만 보내면 나머지는 null로 처리될 수 있다. |
| PATCH | 자원 일부 수정 (Partial Update) | 특정 자원의 일부 정보만 수정한다. |
| DELETE | 자원 삭제 (Delete) | 특정 자원을 삭제한다. |
Sheets로 내보내기
예시: 블로그 게시물(Post) 관리
-
POST /posts: 새 게시물 생성 -
GET /posts: 모든 게시물 목록 조회 -
GET /posts/123: ID가 123인 게시물 조회 -
PUT /posts/123: ID가 123인 게시물의 전체 내용 교체 -
PATCH /posts/123: ID가 123인 게시물의 제목만 수정 -
DELETE /posts/123: ID가 123인 게시물 삭제
3) HTTP 상태 코드: 처리 결과를 명확하게 알려라
서버는 클라이언트의 요청에 대한 처리 결과를 **상태 코드(Status Code)**로 응답해야 한다. 클라이언트는 이 코드를 보고 성공, 실패, 또는 다른 상황을 인지하고 후속 조치를 취할 수 있다.
| 코드 범위 | 의미 | 대표적인 코드 |
|---|---|---|
| 2xx | 성공 (Success) | 200 OK, 201 Created (자원 생성 성공), 204 No Content (응답 본문 없음) |
| 3xx | 리다이렉션 (Redirection) | 301 Moved Permanently |
| 4xx | 클라이언트 오류 (Client Error) | 400 Bad Request, 401 Unauthorized (인증 필요), 403 Forbidden (권한 없음), 404 Not Found (자원 없음) |
| 5xx | 서버 오류 (Server Error) | 500 Internal Server Error, 503 Service Unavailable |
Sheets로 내보내기
상태 코드를 명확하게 사용하면 클라이언트 개발자는 오류의 원인을 빠르게 파악하고 디버깅할 수 있다.
4. 심화 내용 더 깊은 REST의 세계로
기본적인 내용을 숙지했다면, 이제 REST를 더욱 깊이 있게 이해하기 위한 몇 가지 개념을 살펴보자.
1) HATEOAS 하이퍼미디어를 통한 길 안내
HATEOAS(Hypermedia as the Engine of Application State)는 ‘애플리케이션의 상태를 관리하는 엔진으로서의 하이퍼미디어’를 의미한다. 어렵게 들리지만, 핵심은 **“응답에 다음에 할 수 있는 액션에 대한 링크를 포함시켜라”**는 것이다.
우리가 웹 서핑을 할 때, 페이지에 있는 링크(하이퍼링크)를 클릭하며 자연스럽게 다른 페이지로 이동한다. 모든 페이지의 주소를 외우고 직접 입력하지 않는다. HATEOAS는 API도 이와 같아야 한다는 철학이다.
HATEOAS가 적용되지 않은 응답:
JSON
// GET /users/123
{
"id": 123,
"name": "John Doe"
}
이 응답을 받은 클라이언트는 ‘John Doe의 게시물을 보려면 /users/123/posts로 요청해야 한다’는 사실을 미리 알고 있어야 한다. 즉, 서버의 URI 구조에 강하게 결합된다.
HATEOAS가 적용된 응답:
JSON
// GET /users/123
{
"id": 123,
"name": "John Doe",
"_links": {
"self": { "href": "/users/123" },
"posts": { "href": "/users/123/posts" },
"edit": { "href": "/users/123", "method": "PUT" }
}
}
이 응답은 사용자 정보뿐만 아니라, 이 자원과 관련된 다음 행동(게시물 목록 보기, 정보 수정 등)을 할 수 있는 링크를 함께 제공한다. 클라이언트는 이 링크 정보를 보고 다음 요청을 동적으로 생성할 수 있다. 이는 서버의 URI 구조가 변경되어도 클라이언트에 미치는 영향을 최소화하는 느슨한 결합을 가능하게 한다.
2) 멱등성(Idempotence)과 안전성(Safety)
HTTP 메서드의 중요한 특성 두 가지다.
-
안전성 (Safe): 해당 메서드를 호출해도 서버의 자원 상태가 변경되지 않음을 의미한다.
GET메서드가 대표적이다. -
멱등성 (Idempotent): 해당 메서드를 한 번 호출하든, 여러 번 연속으로 호출하든 결과가 똑같음을 의미한다.
-
GET: 여러 번 조회해도 자원이 변하지 않으므로 멱등성을 가진다. -
PUT: 특정 자원을 같은 내용으로 여러 번 교체해도 최종 결과는 동일하므로 멱등성을 가진다. -
DELETE: 특정 자원을 한 번 삭제한 후 다시 삭제 요청을 보내도 (이미 없으므로) 결과는 동일하게 ‘삭제된 상태’이므로 멱등성을 가진다. -
POST: 호출할 때마다 새로운 자원이 생성되므로 멱등성을 가지지 않는다.
-
네트워크 오류 등으로 클라이언트가 서버의 응답을 받지 못했을 때, 멱등성이 보장되는 메서드는 안심하고 재시도할 수 있다.
3) REST API 설계 أفضل الممارسات
-
버전 관리 (Versioning): API는 계속해서 변화하고 발전한다. 하위 호환성을 유지하기 위해 API 버전을 명시하는 것이 좋다.
-
URI에 포함:
https://api.example.com/v1/users -
HTTP 헤더에 포함:
Accept: application/vnd.myapi.v1+json
-
-
필터링, 정렬, 페이지네이션: 많은 양의 데이터를 효율적으로 다루기 위해 쿼리 파라미터를 활용한다.
GET /posts?status=published&sort=-createdAt&page=1&limit=20
4) REST vs SOAP vs GraphQL
| 구분 | REST (Representational State Transfer) | SOAP (Simple Object Access Protocol) | GraphQL (Graph Query Language) |
|---|---|---|---|
| 패러다임 | 자원 중심 아키텍처 스타일 | RPC 기반 프로토콜 | 클라이언트 중심 쿼리 언어 |
| 데이터 형식 | JSON (주로 사용), XML, HTML 등 다양 | XML만 사용 | JSON |
| 전송 프로토콜 | HTTP(S) | HTTP, SMTP 등 다양 | HTTP(S) |
| 장점 | 가볍고 유연함, 웹 표준 활용 | 높은 보안성, 트랜잭션 지원, 표준화 | 데이터 과다/과소 요청 방지(Over/Under-fetching), 유연한 데이터 요청 |
| 단점 | 표준 규약 부재, HATEOAS 구현 어려움 | 무겁고 복잡함, 낮은 성능 | 캐싱 복잡, 파일 업로드 등 구현 어려움 |
Sheets로 내보내기
5. 결론 REST, 여전히 웹 통신의 중심
REST는 지난 20년간 웹 서비스 아키텍처의 사실상 표준으로 군림하며 수많은 시스템의 기반이 되었다. GraphQL과 같은 새로운 대안들이 등장하며 특정 문제(특히 모바일 환경에서의 데이터 효율성)를 해결하고 있지만, REST의 단순함과 명확함, 그리고 웹의 기본 철학을 그대로 담고 있다는 장점은 여전히 강력하다.
이 핸드북을 통해 REST의 탄생 철학부터 실용적인 설계 방법까지 깊이 있게 이해했기를 바란다. 중요한 것은 REST를 단순한 기술 규칙의 집합으로 여기는 것이 아니라, 확장 가능하고 유연하며 독립적으로 진화할 수 있는 시스템을 만들기 위한 ‘아키텍처 원칙’으로 이해하는 것이다. 이 원칙들을 제대로 이해하고 적용할 때, 비로소 우리는 진정으로 ‘RESTful’한 시스템을 구축할 수 있을 것이다.