API 설계 표준
27.1. RESTful API 규칙
27.1.1. URL 네이밍
- 소문자와 하이픈(
-)만 사용합니다. 언더스코어(_)와 camelCase는 사용하지 않습니다. - 리소스명은 복수형을 사용합니다.
- URL 끝에 슬래시(
/)를 포함하지 않습니다.
| 구분 | 올바른 예 | 잘못된 예 |
|---|---|---|
| 복수형 | /api/users | /api/user |
| 하이픈 | /api/user-profiles | /api/user_profiles |
| 소문자 | /api/users | /api/Users |
27.1.2. HTTP 메서드
| 메서드 | 용도 | 예시 | 응답 코드 |
|---|---|---|---|
GET | 리소스 조회 | GET /api/users | 200 |
POST | 리소스 생성 | POST /api/users | 201 |
PUT | 리소스 전체 수정 | PUT /api/users/1 | 200 |
PATCH | 리소스 부분 수정 | PATCH /api/users/1 | 200 |
DELETE | 리소스 삭제 | DELETE /api/users/1 | 204 |
27.1.3. URL 계층 구조
리소스 간 관계는 URL 경로로 표현합니다.
GET /api/users/{userId}/orders # 특정 사용자의 주문 목록
GET /api/users/{userId}/orders/{orderId} # 특정 사용자의 특정 주문- 중첩은 2단계까지만 허용합니다.
- 3단계 이상의 중첩이 필요한 경우, 쿼리 파라미터를 사용합니다.
27.2. 요청/응답 형식
27.2.1. 표준 응답 구조
단일 리소스 응답:
json
{
"id": 1,
"name": "홍길동",
"email": "user@tienipia.com",
"createdAt": "2026-02-28T10:30:00"
}27.2.2. 목록 응답 (페이지네이션)
json
{
"content": [
{
"id": 1,
"name": "홍길동",
"email": "user@tienipia.com"
}
],
"page": 0,
"size": 20,
"totalElements": 150,
"totalPages": 8
}27.2.3. 페이지네이션 파라미터
| 파라미터 | 설명 | 기본값 |
|---|---|---|
page | 페이지 번호 (0부터 시작) | 0 |
size | 페이지 크기 | 20 |
sort | 정렬 기준 | 미지정 시 기본 정렬 |
GET /api/users?page=0&size=20&sort=createdAt,desc27.2.4. 날짜/시간 형식
- ISO 8601 형식을 사용합니다:
2026-02-28T10:30:00 - 타임존이 필요한 경우:
2026-02-28T10:30:00+09:00
27.3. 에러 코드 체계
27.3.1. HTTP 상태 코드
| 코드 | 의미 | 사용 기준 |
|---|---|---|
200 | OK | 조회, 수정 성공 |
201 | Created | 리소스 생성 성공 |
204 | No Content | 삭제 성공 |
400 | Bad Request | 입력값 검증 실패 |
401 | Unauthorized | 인증 필요 |
403 | Forbidden | 권한 부족 |
404 | Not Found | 리소스 없음 |
409 | Conflict | 리소스 충돌 (중복 등) |
500 | Internal Server Error | 서버 내부 오류 |
27.3.2. 커스텀 에러 코드
HTTP 상태 코드와 별도로 커스텀 에러 코드를 사용하여 세부적인 에러를 구분합니다.
{접두사}{순번}| 접두사 | 도메인 | 예시 |
|---|---|---|
C | 공통 | C001 (잘못된 입력) |
U | 사용자 | U001 (사용자 없음) |
A | 인증 | A001 (토큰 만료) |
O | 주문 | O001 (주문 없음) |
27.3.3. 표준 에러 응답 형식
json
{
"code": "U001",
"message": "사용자를 찾을 수 없습니다.",
"timestamp": "2026-02-28T10:30:00"
}입력 검증 오류 시 필드별 상세 정보를 포함합니다.
json
{
"code": "C001",
"message": "잘못된 입력값입니다.",
"timestamp": "2026-02-28T10:30:00",
"errors": [
{
"field": "email",
"value": "invalid-email",
"reason": "올바른 이메일 형식이 아닙니다."
}
]
}27.4. API 문서화
27.4.1. SpringDoc 적용
모든 API 프로젝트는 SpringDoc (OpenAPI 3.0)을 적용하여 Swagger UI를 제공합니다.
xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.4</version>
</dependency>yaml
# application.yml
springdoc:
swagger-ui:
path: /swagger-ui.html
api-docs:
path: /v3/api-docs27.4.2. API 어노테이션
Controller와 DTO에 OpenAPI 어노테이션을 적용합니다.
java
@RestController
@RequestMapping("/api/users")
@Tag(name = "사용자", description = "사용자 관리 API")
public class UserController {
@Operation(summary = "사용자 조회", description = "ID로 사용자를 조회합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "404", description = "사용자 없음")
})
@GetMapping("/{id}")
public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
}27.4.3. 문서화 원칙
- 모든 공개 API에
@Operation어노테이션을 포함합니다. - 요청/응답 DTO에 필드 설명을 포함합니다.
- Swagger UI는 개발/스테이징 환경에서만 활성화하고, 프로덕션에서는 비활성화합니다.