[Web] REST API 정리: 리소스 중심 설계와 실무 기준
REST API는 “REST(Representational State Transfer)”라는 아키텍처 스타일을 따르는 API를 의미한다.
다만 실무에서 REST API는 엄밀한 이론을 완벽히 구현한 형태라기보다,
HTTP의 특성을 잘 활용하여 읽기 쉽고 일관된 규칙으로 설계한 API를 가리키는 경우가 많다.
이 글에서는 웹 개발 관점에서 REST API를 이해하기 위해 필요한 핵심 개념과, 설계 시 자주 사용하는 규칙을 정리한다.
1. REST API의 핵심: 리소스(Resource) 중심
REST에서 가장 중요한 관점은 행위(동작)보다 리소스(대상)이다.
즉, API가 다루는 대상을 URL로 표현하고, 어떤 작업을 할지는 HTTP 메서드로 표현한다.
- 리소스: 사용자, 게시글, 댓글, 주문 등
- URL: 리소스를 식별하는 주소
- 메서드: 리소스에 대한 행위를 표현
예를 들어 게시글을 다룬다면 다음처럼 설계한다.
/posts: 게시글 컬렉션(목록)/posts/{id}: 특정 게시글(단건)
2. HTTP 메서드로 의도를 표현한다
REST API에서는 URL에 create, delete 같은 동사를 넣기보다, HTTP 메서드로 의도를 드러내는 방식을 선호한다.
대표 메서드와 의미
- GET: 조회
- POST: 생성
- PUT: 전체 교체(전체 수정)
- PATCH: 일부 수정
- DELETE: 삭제
예시(CRUD)
GET /posts: 게시글 목록 조회GET /posts/1: 게시글 상세 조회POST /posts: 게시글 생성PATCH /posts/1: 게시글 일부 수정DELETE /posts/1: 게시글 삭제
3. 상태(Stateless): 요청은 독립적으로 이해되어야 한다
REST는 기본적으로 무상태(Stateless)를 지향한다.
이는 서버가 “이전 요청의 문맥”에 의존하지 않도록, 각 요청이 독립적으로 처리되어야 한다는 의미이다.
예를 들어 인증이 필요한 요청이라면, 매 요청에 인증 정보가 포함되어야 한다.
- 쿠키 기반 세션(브라우저가 쿠키를 자동 전송)
- 토큰 기반 인증(Authorization 헤더)
무상태 특성은 확장성과 단순성 측면에서 장점이 있지만, 실무에서는 인증/인가, 캐시, 세션 전략과 함께 균형 있게 설계한다.
4. 표현(Representation): 리소스는 “형태”로 전달된다
REST의 “Representational”은 리소스를 직접 전달한다기보다, 리소스의 표현(Representation)을 전달한다는 의미이다.
웹 API에서는 보통 JSON이 대표적인 표현 형식이다.
예:
1
2
3
4
5
{
"id": 1,
"title": "REST API",
"authorId": 10
}
또한 표현은 상황에 따라 달라질 수 있다.
- 목록 응답: 요약 필드 중심
- 상세 응답: 본문/연관 데이터 포함
- 권한에 따라 일부 필드 제외
5. URL 설계 규칙: 실무에서 많이 쓰는 기준
명사 중심으로 작성한다
- 권장: /users, /posts, /orders
- 비권장: /getUsers, /createPost
복수형(컬렉션)과 단건을 구분한다
- 컬렉션: /posts
- 단건: /posts/{id}
계층 관계를 과도하게 깊게 만들지 않는다
관계가 있는 리소스를 표현할 때 중첩 경로가 자연스러울 수 있으나, 너무 깊어지면 관리가 어려워진다.
예:
- /posts/1/comments (가능)
- /users/3/posts/1/comments/9 (지나치게 깊어질 수 있음)
실무에서는 “조회 목적”과 “모델 관계”를 분리해서 고민하는 편이 좋다.
6. 상태 코드와 에러 응답 설계
REST API는 응답의 의미를 상태 코드로 표현하는 것을 중요하게 본다.
자주 사용하는 상태 코드
- 200 OK: 성공(조회/수정 등)
- 201 Created: 생성 성공
- 204 No Content: 성공했으나 응답 바디 없음(삭제 등)
- 400 Bad Request: 요청 값/형식 오류
- 401 Unauthorized: 인증 필요
- 403 Forbidden: 권한 없음
- 404 Not Found: 리소스 없음
- 409 Conflict: 충돌(중복, 상태 충돌 등)
- 500 Internal Server Error: 서버 오류
에러 응답은 일관된 형태로 제공한다
실무에서는 프론트엔드가 예외 처리를 쉽게 할 수 있도록, 에러 응답 구조를 통일하는 편이 좋다.
예:
1
2
3
4
5
6
7
8
9
{
"error": {
"code": "VALIDATION_ERROR",
"message": "입력 값이 올바르지 않습니다.",
"details": [
{ "field": "title", "reason": "필수 값입니다." }
]
}
}
7. 페이징, 정렬, 필터링은 쿼리 스트링을 사용한다
목록 API에서는 페이징/정렬/필터링을 URL Path가 아니라 Query로 표현하는 경우가 많다.
예:
GET /posts?page=1&size=20
GET /posts?sort=createdAt&order=desc
GET /posts?status=published
8. 버전 관리(Versioning)
API 변경이 누적되면 클라이언트 호환 문제가 생길 수 있다. 이를 관리하기 위해 다음과 같은 방식이 활용된다.
- 경로 버전: /api/v1/posts
- 헤더 버전: Accept: application/vnd…
실무에서 가장 흔한 것은 경로 버전 방식이며, 문서화와 운영 측면에서 단순한 편이다.
9. REST API라고 다 같은 것은 아니다
실무에서 “REST API”는 대체로 다음 의미로 사용된다.
- URL이 리소스 중심으로 설계되어 있고
- 메서드/상태 코드가 일관되며
- 요청/응답 구조가 예측 가능하고
- 문서화 및 클라이언트 개발이 수월한 API
즉, 완전한 이론적 REST 준수 여부보다 일관성과 사용성이 더 중요한 경우가 많다.
마무리
REST API는 “리소스를 URL로 표현하고, 행위를 메서드로 표현한다”는 원칙을 중심으로, HTTP의 장점을 설계에 녹여낸 방식이다. 웹 개발 관점에서는 다음 항목을 지키는 것만으로도 API 품질이 크게 개선된다.
- URL은 리소스(명사) 중심으로 설계한다.
- 메서드(GET/POST/PATCH/DELETE)로 의도를 표현한다.
- 상태 코드와 에러 응답 형식을 일관되게 유지한다.
- 목록의 조건(페이징/정렬/필터)은 쿼리 스트링을 사용한다.