Topic (오늘의 주제)
RESTful API 설계 원칙과 애매한 상황(Edge Case)의 현실적 해결 전략
Why (왜 사용하는가? 왜 중요한가?)
- 실무: 프론트엔드와 백엔드가 협업할 때, 명확한 **규약(Protocol)**이 없으면 API 명세서를 매번 확인해야 하는 비효율이 발생합니다. REST는 이를 표준화합니다.
- 구조적 의미: **자원(Resource)**과 **행위(Verb)**를 분리하여 시스템을 직관적으로 만들고, HTTP의 장점(캐싱, 무상태성)을 그대로 활용할 수 있습니다.
- 면접 의도: "REST가 무엇인가"를 넘어, "Login은 어떤 메서드를 써야 하는가?", "검색 조건이 너무 많으면 어떻게 하는가?" 같은 실무적인 딜레마를 어떻게 해결하는지 봅니다.
Core Concept (핵심 개념 정리)
| 요소 | 내용 |
| 개념 정의 | REST (Representational State Transfer): HTTP 프로토콜을 의도에 맞게 사용하여, 자원(Resource)의 상태를 주고받는 아키텍처 스타일. |
| 구성 요소 | 1. 자원 (URI): 명사(Noun)로 표현. (예: /members, /orders/1) 2. 행위 (Method): 동사(Verb)로 표현. (GET, POST, PUT, DELETE, PATCH) 3. 표현 (Representation): JSON, XML 등 데이터 형태. |
| 기본 원칙 | URI는 정보의 자원을 표현해야 하며, 자원에 대한 행위는 HTTP Method로 표현해야 한다. (BAD: POST /deleteMember/1 → URI에 동사가 있음) (GOOD: DELETE /members/1) |
Ambiguous Cases & Solutions (애매한 경우와 해결책)
REST 원칙을 완벽히 지키기 어려운 대표적인 상황과 실무적 합의(Best Practice)입니다.
Case 1: 단순 CRUD가 아닌 '동작' (예: 로그인, 메일 발송)
- 상황: 로그인은 '사용자 생성'도 아니고 '조회'도 아님. /login은 명사가 아닌 동사 느낌임.
- 애매함: REST는 URI에 동사를 쓰지 말라고 함.
- 해결책 1 (자원화): 행위 자체를 **명사(리소스)**로 만듭니다.
- POST /auth/token (토큰 발급 요청 = 로그인)
- POST /emails (이메일 전송 요청 = 이메일 리소스 생성)
- 해결책 2 (컨트롤러 리소스): 어쩔 수 없이 동사를 허용하되 명확히 구분합니다.
- POST /members/1/activate (상태 변경이 복잡할 때)
Case 2: 검색 조건이 너무 길거나 복잡할 때
- 상황: 필터링 조건이 20개가 넘어서 Query String(GET ?name=...&age=...)이 너무 길어짐. 혹은 보안상 URL에 정보 노출이 꺼려짐.
- 애매함: 조회(Read)니까 GET을 써야 하는데, URL 길이 제한에 걸림.
- 해결책 (POST 사용):
- POST /members/search (검색 요청을 Body에 담아 보냄)
- 엄밀한 REST 위반일 수 있으나, 실무에서는 검색 조건 자체를 리소스로 보거나 기술적 제약 때문에 허용합니다.
Case 3: 한 번에 여러 자원 수정 (Bulk Update)
- 상황: 회원 100명의 등급을 동시에 수정해야 함.
- 애매함: /members/1, /members/2를 100번 호출하는 것은 비효율적임.
- 해결책:
- PATCH /members (Body에 ID 목록과 변경 데이터 전송)
- 명확성을 위해 POST /members/bulk-update 같은 커스텀 URI를 사용하기도 합니다.
Interview Answer Version (면접 답변식 요약)
"RESTful 설계는 URI로 자원을 명시하고 HTTP Method로 행위를 정의하는 방식입니다.
하지만 실무에서는 로그인, 복잡한 검색, 일괄 처리 등 표준 CRUD로 정의하기 애매한 상황이 발생합니다.
이때는 도그마에 갇히기보다 **행위를 명사화(예: /tokens, /search)**하거나, 팀 내부 규약을 통해 예외적으로 POST를 활용하는 등 **실용주의(Pragmatism)**적인 접근을 하는 것이 중요하다고 생각합니다."
Practical Tip (사용시 주의할 점 or 활용 예)
1. HTTP 상태 코드(Status Code)의 올바른 사용
- 성공 시 무조건 200 OK만 내리는 경우가 있는데, 디테일이 중요합니다.
- 200 OK: 조회, 수정 성공.
- 201 Created: 생성 성공 (POST 응답).
- 204 No Content: 삭제 성공 후 반환할 본문이 없을 때.
- 400 Bad Request: 클라이언트 입력 실수 (Validation 실패).
- 401 Unauthorized: 인증 실패 (로그인 필요).
- 403 Forbidden: 인가 실패 (권한 없음).
2. URI 설계 규칙 (사소하지만 중요)
- 소문자 사용 (/Members (X) -> /members (O))
- 복수형 명사 권장 (/member/1 (△) -> /members/1 (O)) - 컬렉션의 의미.
- 구분자는 하이픈(-) 사용, 언더바(_) 지양.
- 마지막에 슬래시(/) 포함하지 않음.
3. 버전 관리 (Versioning)
- API는 한 번 배포하면 수정이 어렵습니다. 처음부터 버전을 명시하세요.
- URI 방식: /v1/members (가장 직관적, 추천)
- Header 방식: Accept: application/vnd.company.v1+json
예상 꼬리질문 정리
- Q: PUT과 PATCH의 정확한 차이점은 무엇인가요?
- 핵심 키워드: PUT은 자원 전체를 교체(없으면 생성), PATCH는 자원의 일부만 부분 수정. 멱등성(Idempotency)의 차이.
- Q: RESTful하지 않은 API(HTTP API)와 RESTful API의 차이는 무엇인가요?
- 핵심 키워드: HATEOAS(응답에 다음 상태로 갈 수 있는 링크 포함)까지 지켜야 진정한 REST(Richardson Maturity Model Lv.3)라고 하지만, 실무에선 Lv.2(리소스+동사) 정도를 RESTful이라 통칭함.
- Q: 리소스 간의 관계는 URI로 어떻게 표현하나요?
- 핵심 키워드: 하위 리소스로 표현. 예: GET /users/{id}/orders (특정 유저의 주문 목록).
'Archive > Daily Dev Q&A' 카테고리의 다른 글
| Daily Dev Q&A: Web Server vs WAS (Web Application Server) (1) | 2026.01.06 |
|---|---|
| Daily Dev Q&A: JPA (0) | 2026.01.05 |
| Daily Dev Q&A: session 로그인 방식과 token 로그인 방식 (0) | 2025.12.31 |
| Daily Dev Q&A: Spring Security의 인증과 인가 (0) | 2025.12.31 |
| Daily Dev Q&A: @SpringBootApplication은 필수인가? (1) | 2025.12.30 |