리소스 URL과 HTTP 메서드의 관계를 단순한 다이어그램으로 표현한 REST API 디자인 기본 패턴 이미지입니다.
REST API 4일차 : 초보자를 위한 REST API 디자인 기본 패턴
한눈에 보는 요약
REST API를 잘 디자인하려면 “URL은 명사(리소스 이름)”, “HTTP 메서드는 동작(읽기, 만들기 등)”이라는 기본 원칙만 먼저 기억하시면 됩니다.
URL 패턴은 일관되게 만들고, 컬렉션과 개별 리소스를 구분해 설계하면 API가 훨씬 읽기 쉽고 유지 보수도 쉬워집니다.
GET·POST·PUT·PATCH·DELETE와 같은 HTTP 메서드를 적절한 상태 코드(200, 201, 204, 400, 404 등)와 함께 사용하면, 클라이언트와 서버가 서로의 의도를 오해하지 않게 됩니다.
이 글에서는 복잡한 이론을 최소화하고, 실무에서 바로 쓸 수 있는 REST API 디자인 기본 패턴을 쉬운 예시와 함께 정리합니다.
목차
- 1. REST API 디자인이 중요한 이유
- 2. 리소스와 URL 패턴 기본
- 3. HTTP 메서드와 상태 코드 조합
- 4. 자주 쓰는 디자인 기본 패턴
- 5. 코드 예시 (간단한 사용자 API)
- 6. 실무 적용 단계
핵심 포인트
- REST API 디자인의 목표는 “사람이 읽어도 이해하기 쉬운 URL과 규칙”을 만드는 것입니다.
- 리소스는 명사(예:
/users,/orders)로 표현하고, 동사는 HTTP 메서드로 표현합니다. - 컬렉션(
/users)과 개별 리소스(/users/{id})를 구분해 설계하면 패턴이 단순해집니다. - 상태 코드(200, 201, 204, 400, 404, 409 등)를 상황에 맞게 사용하면 디버깅과 오류 처리가 쉬워집니다.
- 필터링, 페이징, 정렬, 에러 응답 형식 같은 “자주 반복되는 패턴”을 팀 규칙으로 미리 정해두면 좋습니다.
상세 설명
1. REST API 디자인이 중요한 이유
REST API는 화면(UI)과 서버를 연결하는 통신 언어입니다. 대부분의 웹·모바일 서비스는 이 API를 통해 데이터(유저, 주문, 게시글 등)를 주고받습니다. 이때 API가 직관적으로 설계되어 있으면, 새로운 개발자가 와도 구조를 빠르게 이해하고 기능을 안전하게 추가할 수 있습니다.
반대로, 규칙 없이 제각각 만들어진 API는 작은 수정에도 많은 부분을 동시에 고쳐야 하고, 버그가 숨어들기 쉬워집니다. 따라서 초반에 약간의 시간을 들여 “기본 패턴”을 정리해 두는 것이 장기적인 개발 비용을 크게 줄이는 방법입니다.
2. 리소스와 URL 패턴 기본
REST에서 가장 중요한 단어는 “리소스”입니다. 리소스는 시스템에서 다루는 대상, 예를 들어 사용자, 상품, 주문 등입니다. URL은 이 리소스를 가리키는 주소 역할을 합니다.
- 컬렉션(목록) URL: 리소스 전체를 가리키는 복수형 명사 사용 – 예:
/users,/products - 개별 리소스 URL: 특정 한 개를 가리키기 위해 ID 추가 – 예:
/users/123,/products/10 - 중첩 리소스 URL: 특정 유저의 주문처럼 “소속 관계”를 표현 – 예:
/users/123/orders
URL에는 동사를 넣지 않는 것이 일반적인 규칙입니다. 예를 들어 /createUser보다는 /users에 POST 메서드를 보내 “생성” 의미를 표현하는 식입니다. 또한 소문자와 하이픈(-)을 사용해 통일하면 가독성이 좋아집니다. 예: /user-groups
3. HTTP 메서드와 상태 코드 조합
HTTP 메서드는 리소스에 대해 “무엇을 할지”를 나타내는 동사 역할을 합니다. 핵심 메서드와 보통 함께 쓰는 상태 코드는 다음과 같습니다.
- GET: 조회 – 성공 시 보통
200 OK, 리소스가 없으면404 Not Found - POST: 생성 – 성공 시 신규 리소스에는
201 Created, 특별한 응답이 없으면204 No Content - PUT: 전체 수정 – 지정한 리소스를 통째로 교체하는 의미로, 성공 시
200또는204 - PATCH: 부분 수정 – 일부 필드만 변경할 때 사용
- DELETE: 삭제 – 성공 시 주로
204 No Content사용
요청이 잘못되었을 때는 400 Bad Request, 권한이 없을 때는 401 Unauthorized 또는 403 Forbidden, 중복 데이터 등으로 요청을 처리할 수 없을 때는 409 Conflict를 사용하는 것이 일반적입니다. 이렇게 공통 규칙을 정해두면 클라이언트 코드도 조건 분기를 예측 가능하게 짤 수 있습니다.
4. 자주 쓰는 디자인 기본 패턴
실제 서비스에서 자주 등장하는 REST API 디자인 패턴을 몇 가지로 정리해 보겠습니다.
- 컬렉션 / 개별 리소스 패턴
GET /users– 사용자 목록 조회,POST /users– 사용자 생성,GET /users/{id}– 사용자 상세 조회,PATCH /users/{id}– 일부 정보 수정,DELETE /users/{id}– 삭제. - 필터링·검색 패턴
쿼리스트링을 사용해 조건을 표현합니다. 예:GET /users?role=admin&active=true,GET /orders?from=2024-01-01&to=2024-01-31 - 페이징 패턴
page,size또는limit,offset같은 파라미터를 사용합니다. 예:GET /users?page=1&size=20 - 정렬 패턴
sort파라미터에 정렬 기준과 방향을 함께 표현합니다. 예:GET /users?sort=createdAt,desc - 표준화된 에러 응답
에러 발생 시{ "code": "USER_NOT_FOUND", "message": "사용자를 찾을 수 없습니다." }처럼 코드와 메시지 구조를 통일해 두면, 프런트엔드에서 처리하기 편리합니다.
REST API 디자인 기본 패턴 요약 표
아래 표는 방금 설명한 REST API 디자인 기본 패턴을 한눈에 정리한 것입니다.
| 패턴 | URL / 예시 | 의미 | 주의할 점 |
|---|---|---|---|
| 컬렉션 / 리소스 | /users, /users/{id} | 목록과 개별 대상을 구분해 표현 | URL에 동사를 넣지 않고 명사형으로 유지 |
| 중첩 리소스 | /users/{id}/orders | 소속 관계(유저의 주문 등)를 표현 | 중첩 단계가 너무 깊어지지 않도록 설계 |
| 필터링 / 검색 | /users?role=admin | 조건을 쿼리스트링으로 전달 | 필터 파라미터 이름을 일관되게 사용 |
| 페이징 | /users?page=1&size=20 | 응답 크기를 제한해 성능과 트래픽 관리 | 총 건수, 총 페이지 정보도 함께 제공하면 좋음 |
| 정렬 | /users?sort=createdAt,desc | 정렬 기준과 방향을 지정 | 여러 필드를 지원할지 정책을 사전에 합의 |
코드 예시 (간단한 사용자 API)
// Node.js Express를 이용한 간단한 REST API 예시 const express = require('express'); const app = express(); app.use(express.json());
// 1) 사용자 컬렉션 조회 및 생성
app.get('/users', (req, res) => {
// 사용자 목록 조회 (예: DB 조회)
const users = [{ id: 1, name: 'Alice' }];
res.status(200).json(users);
});
app.post('/users', (req, res) => {
// 사용자 생성 (예: DB 저장)
const newUser = { id: 2, name: req.body.name };
res.status(201).json(newUser);
});
// 2) 개별 사용자 조회, 수정, 삭제
app.get('/users/:id', (req, res) => {
const id = Number(req.params.id);
if (id === 1) {
return res.status(200).json({ id: 1, name: 'Alice' });
}
return res.status(404).json({ code: 'USER_NOT_FOUND', message: '사용자를 찾을 수 없습니다.' });
});
app.patch('/users/:id', (req, res) => {
// 일부 필드만 수정한다고 가정
const updated = { id: Number(req.params.id), name: req.body.name };
res.status(200).json(updated);
});
app.delete('/users/:id', (req, res) => {
// 삭제 성공 시 보통 내용 없이 204 응답
res.status(204).send();
});
app.listen(3000, () => {
console.log('REST API server running on port 3000');
});
위 예시는 사용자 리소스를 기준으로 컬렉션(/users)과 개별 리소스(/users/:id)를 나누고, GET·POST·PATCH·DELETE 메서드를 조합하여 기본 CRUD 기능을 구현한 코드입니다. 성공·실패에 따라 200, 201, 204, 404 등의 상태 코드를 다르게 반환하도록 구성해 두면, 클라이언트가 결과를 쉽게 판별할 수 있습니다.
실행 단계
- 현재 API 목록 정리
먼저 시스템에 존재하는 모든 엔드포인트 URL, 사용 중인 HTTP 메서드, 응답 형식을 표로 정리합니다. 이 단계에서 “규칙이 제각각인 부분”을 찾는 것이 목표입니다. - 리소스 중심으로 다시 묶기
화면이나 기능 단위가 아니라 “사용자, 주문, 상품” 같은 리소스 기준으로 그룹을 재구성합니다. 각 리소스에 대해 컬렉션 URL과 개별 URL을 정의해 봅니다. - HTTP 메서드와 상태 코드 규칙 합의
팀 차원에서 “조회는 GET, 생성은 POST, 삭제는 DELETE” 등 기본 규칙을 문서로 정리하고, 어떤 상황에 어떤 상태 코드를 쓸지 표로 만들어 공유합니다. - 필터·페이징·정렬 공통 규칙 정의
목록 조회 API들의 쿼리 파라미터 이름과 의미를 통일합니다. 예를 들어 모든 목록에서page,size,sort를 동일하게 사용하는 식입니다. - 에러 응답 포맷과 버전 전략 정리
에러 응답 JSON 구조를 통일하고, 나중에 큰 변경을 위해/v1,/v2같은 버전 전략을 미리 논의해 둡니다.
추가로 생각해볼 점
- API 버전 관리는 URL에 버전을 붙이는 방식(
/v1/users)과 헤더로 구분하는 방식이 있습니다. 팀 규모와 시스템 복잡도에 맞게 선택하는 것이 좋습니다. - Swagger/OpenAPI 같은 도구를 이용해 설계 단계에서부터 문서를 자동으로 생성하면, 클라이언트·백엔드 간 의사소통 비용을 크게 줄일 수 있습니다.
- 요청·응답 로그와 모니터링을 함께 설계해 두면, 나중에 장애가 발생했을 때 원인 분석이 훨씬 쉬워집니다.

0 댓글