State in REST API
1. What is State in API?
API에서 말하는 state(상태)란, 보통 클라이언트와 서버 간의 상호작용(요청-응답)에서 어떤 정보를 기억하거나 유지하고 있는지 여부를 의미한다. 이 개념은 주로 Stateless vs Stateful 아키텍처를 설명할 때 사용된다.
API에서의 State란?
state
는 일반적으로 다음과 같은 정보를 포함한다.
- 사용자 상태: 로크인 여부, 인증 토큰, 사용자 정보 등
- 세션 상태: 이전 요청에서 수행한 작업의 맥락 (e.g. 장바구니 상품목록)
- 트랜잭션 상태: 결제, 주문 처리 등에서의 중간 단계 정보
이 정보를 클라이언트에서 가지고 있는가 or 서버에서 가지고 있으면서 유지하는가에 따라 statefull 또는 stateless로 구분한다. 이러한 구분은 서버 아키텍처 설계나 확장성 고려 등에 있어서 매우 중요한 요소이다.
Stateless API
Stateless API는 서버가 클라이언트의 상태 정보를 전혀 저장하지 않고, 모든 요청은 독립적으로 처리된다. 이는 다음과 같은 특징들을 가진다.
- 각 요청은 완전한 정보를 포함해야 함 (e.g. JWT, 모든 파라미터 등)
- 서버 확장에 유리하고, 스케일 아웃이 쉬움
- RESTful API의 핵심 원칙 중 하나
예를 들어, JWT 토큰을 포함한 API 요청에서는 해당 요청만으로 인증 및 로직 수행이 모두 가능해야한다.
1
2
GET /orders/12345
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
→ 이 요청만으로 인증 및 주문 조회가 모두 가능해야 함
Stateful API
Stateful API는 서버가 클라이언트와의 이전 상호작용의 상태를 기억한다. 따라서 다음과 같은 특징을 가진다.
- 세션 ID 등을 통해 상태를 유지
- 사용자의 흐름을 유지하는 데 유리 (e.g. 다단계 폼, 장바구니)
- 분산 시스템에서는 스티키 세션(sticky session) 등이 필요
예를 들어, 아래와 같이 쿠키에 세션ID를 담아서 요청하게 되면, 서버가 장바구니의 상태에 따라 결제를 처리해야한다.
1
2
POST /checkout
Cookie: session_id=abc123
→ 서버는 session_id에 저장된 장바구니 상태를 기반으로 결제를 처리함
API 설계 시 State의 영향
기준 | Stateless API | Stateful API |
---|---|---|
확장성 | 뛰어남 (서버 간 상태 공유 불필요) | 낮음 (세션 공유 필요) |
유지보수 | 상대적으로 쉬움 | 복잡함 (세션 동기화 등 필요) |
캐싱 | 용이 (요청이 독립적) | 어려움 |
보안 | 토큰 기반 인증에서 주의 필요 | 세션 하이재킹 위험 있음 |
API에서 state란 클라이언트의 상태 정보를 서버가 기억하는가에 대한 개념이며, 이 정보를 유지하지 않으면 Stateless, 유지하면 Stateful API라고 한다.
2. What is State in REST API?
REST API에서 state(상태)란, 보통 리소스(Resource)의 특정 시점의 표현(Representation)을 의미한다. 또한 클라이언트와 서버 사이의 상호작용 방식(Stateless 또는 Stateful)에서도 중요한 개념입니다.
리소스의 상태(state of resource)
클라이언트가 API를 통해 요청하는 대상은 리소스(resource)이고, 서버는 이 리소스의 현재 상태(데이터 값 + 메타정보)를 JSON 등으로 표현해서 응답한다. 이 응답이 바로 “state”, 즉 리소스의 상태이다.
예를 들어, 아래와 같은 API를 설계했다고 해보자.
1
2
3
4
5
6
7
GET /users/123
{
"id": 123,
"name": "홍길동",
"email": "hong@example.com",
"status": "ACTIVE"
}
위 JSON이 리소스(/users/123
)의 현재 상태이다. 사용자가 PUT /users/123
요청으로 status
를 "INACTIVE"
로 바꾸면 상태가 전이된다.
서버-클라이언트 사이의 상태(statefulness)
- REST API는 Stateless(무상태)를 기본 원칙으로 한다.
- 서버는 클라이언트의 이전 요청 상태를 저장하지 않는다.
- 클라이언트는 모든 요청에 필요한 정보를 매번 포함해야 한다 (e.g. 인증 토큰, 파라미터 등).
예를 들어, 서버가 로그인 상태, 세션을 기억하지 않고, 클라이언트가 매 요청마다 Authorization: Bearer <JWT>
를 보내야 하는 구조는 stateless이다.
클라이언트는 POST
, PUT
, DELETE
요청 등을 통해 리소스의 상태를 변화시킬 수 있다. 이 과정을 상태 전이(state transition)라고 한다.
좋습니다. 이번에는 REST API에서의 state(상태) 개념을 HATEOAS(Hypermedia As The Engine Of Application State)와 연관지어 설명드릴게요.
3. HATEOAS란?
HATEOAS는 REST 아키텍처의 핵심 개념 중 하나로,
“애플리케이션의 상태 전이는 하이퍼미디어를 통해 이루어진다” 라는 원칙을 따른다.
즉, 클라이언트는 서버로부터 받은 응답 안의 링크(hypermedia)를 이용해 다음에 무엇을 할 수 있는지(어떤 상태로 전이할 수 있는지) 알 수 있어야 한다.
REST API의 상태(state)와 HATEOAS의 관계
상태(state) = 리소스의 현재 상태 + 가능한 전이 경로
이다. 예를 들어, 클라이언트가 /orders/123
에 대해 GET 요청을 보냈다고 하자. 이때 응답에는 주문의 현재 상태(e.g. CREATED
)뿐 아니라, 사용자가 다음에 할 수 있는 행동(상태 전이)에 대한 링크도 포함된다. 다음은 그 예시 응답이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"orderId": 123,
"status": "CREATED",
"items": [...],
"_links": {
"self": {
"href": "/orders/123"
},
"cancel": {
"href": "/orders/123/cancel",
"method": "POST"
},
"pay": {
"href": "/orders/123/pay",
"method": "POST"
}
}
}
이 응답은 단순히 주문 데이터를 넘기는 게 아니라, 현재 상태가 “CREATED”인 주문은 “취소” 또는 “결제” 상태로 전이 가능함을 알려주는 것이다. 이처럼 상태(state)와 상태 전이 가능한 링크(HATEOAS)가 함께 제공된다.
요점 정리
개념 | 설명 |
---|---|
State (상태) | 리소스의 현재 스냅샷 + 가능한 행동(전이 경로) |
HATEOAS | 응답에 하이퍼미디어 링크를 포함해 클라이언트가 어떤 상태로 전이할 수 있는지 안내 |
상태 전이 방식 | 클라이언트가 링크에 따라 액션을 수행하며 상태를 변경 (ex. /pay , /cancel ) |
HATEOAS의 장점
장점 | 설명 |
---|---|
유연성 | 클라이언트가 서버의 상태 흐름에 따라 행동할 수 있음 |
분리 | 클라이언트는 서버 로직을 몰라도, 링크를 따라가며 앱을 탐색할 수 있음 |
표준화 | 상태 전이(워크플로우)가 명시적으로 드러남 |
실제 적용 예
상태 | 가능 링크(HATEOAS) |
---|---|
CREATED | 결제, 취소 가능 |
PAID | 배송 요청 가능 |
SHIPPED | 반품 요청 가능 |
이 모든 상태 전이는 하이퍼미디어 링크로 제공되어야 하고, 클라이언트는 이 링크들을 따라 애플리케이션 상태를 전이한다.
결론
REST에서의 state(상태)는 단순한 데이터 스냅샷이 아닌, 현재 상태 + 가능한 전이 경로를 포함하는 개념이다. 그리고 이 전이 경로를 하이퍼미디어(HATEOAS)로 제공하는 것이 REST의 이상적인 방식이다.
4. HATEOAS의 절충안
REST에서 Stateless의 의미는 다음과 같다.
“각 요청은 독립적이며, 서버는 클라이언트의 상태(Session, Context)를 기억하지 않는다.” 즉, 클라이언트는 매 요청에 필요한 정보를 전부 포함해야 하며, 서버는 이전 요청에 대한 상태나 컨텍스트를 기억하지 않고도 요청을 처리해야 한다.
이 stateless 원칙은 서버 확장성, 안정성, 단순성을 제공한다.
HATEOAS와 Stateless의 관계
HATEOAS는 REST의 하위 원칙으로, 클라이언트가 서버로부터 받은 리소스 표현(state) 안에서 어떤 상태 전이(transition)가 가능한지를 링크로 알 수 있어야 한다는 규칙이다. 이는 REST의 “self-descriptive messages” 원칙을 강화하는 기능이지, Stateless 자체를 보장하는 요소는 아니다. 즉, HATEOAS를 따르지 않아도 stateless REST API는 구현 가능하다.
HATEOAS가 없는 경우의 한계
HATEOAS를 따르지 않으면 다음 문제가 생길 수 있다.
문제 | 설명 |
---|---|
클라이언트가 서버의 상태 흐름을 사전에 하드코딩해야 함 | 서버의 상태 전이 로직이 바뀌면 클라이언트도 코드 변경 필요 |
API 사용성이 떨어짐 | 클라이언트는 어떤 요청이 가능한지 모르고, 실수로 잘못된 호출 가능 |
분산 Hypermedia 흐름 불가 | 리소스를 탐색하고 상태를 따라가는 기능이 사라짐 |
즉, Stateless는 유지되지만 RESTful하지 않은 API가 되어버릴 수 있다.
그렇다면 실무의 절충안은?
대부분의 REST API는 HATEOAS를 완전하게 지키지 않는다. 대신 다음과 같은 절충 전략을 사용한다.
방법1. REST + API 문서 기반 (Swagger/OpenAPI)
- HATEOAS 대신 Swagger, Postman 등으로 상태 흐름을 문서화
- 클라이언트는 링크를 따르지 않고, API 명세를 하드코딩하여 구현
- 가장 현실적인 방식이며, 많은 회사가 이 모델을 사용
방법2. 상태 흐름은 클라이언트에 위임
- 예: 프론트엔드가 주문 상태
CREATED
이면"결제" 버튼
을 노출 - 서버는 단순하게 요청을 받고 처리만 함
- 서버는 Stateless하고, 상태 전이 흐름은 클라이언트가 판단
방법3. 부분적 HATEOAS 적용
- 중요한 리소스에만
_links
를 제공 - 예: 주문 상세 페이지에는
pay
,cancel
링크 제공 - 비즈니스 흐름이 복잡한 곳만 HATEOAS로 처리하고, 나머지는 일반 REST