본문 바로가기
-- 오늘 있었던 개발 일기

RESTful Api란?

by code study 2026. 1. 4.

RESTful이란?

REST(Representational State Transfer)는 웹의 장점을 최대한 활용하는 API 설계 방식입니다. 2000년 Roy Fielding의 박사 논문에서 처음 소개되었으며, 현재 대부분의 웹 서비스에서 표준으로 사용됩니다.

 

REST가 필요한 이유

초기 웹 API들은 각자 다른 방식으로 설계되어 학습 비용이 높았습니다. 회원 조회를 위해 어떤 곳은 /getUserInfo를, 어떤 곳은 /member/get을 사용했죠. REST는 이런 혼란을 해결하기 위해 통일된 인터페이스를 제안했습니다.

📌 핵심 원칙

  1. 자원 중심: URL은 명사로 (동사 X)
  2. HTTP 메서드 활용: GET(조회), POST(생성), PUT(전체 수정), PATCH(부분 수정), DELETE(삭제)
  3. 무상태성: 각 요청은 독립적
  4. 일관된 인터페이스: 같은 패턴 반복

❌ 잘못된 설계 vs ✅ 올바른 설계

// ❌ 동사 중심의 잘못된 설계
POST /createMember
POST /getMemberInfo
POST /updateMemberInfo
POST /deleteMember

// ✅ RESTful 설계
POST   /api/members           // 생성
GET    /api/members/{id}      // 조회
PUT    /api/members/{id}      // 수정
DELETE /api/members/{id}      // 삭제

 

예를 들어 잘못된 설계는 POST createMember, POST getMemberInfo, POST deleteMember 이런 식으로 URL에 동사를 넣습니다.
반면 RESTful 설계는 POST /api/members로 생성하고, GET /api/members로 조회하고, DELETE /api/members로 삭제합니다. URL은 members로 통일하고, 행위는 HTTP 메서드로 구분
이런식으로 작성되면 URL만 봐도 회원에 관한 API구나 바로 알 수 있습니다. 또한 모든 리소스에 같은 패턴을 적용할 수 있어서 일관성이 생깁니다

 

왜 올바른 설계인가?

  • 직관적: URL만 봐도 무엇에 대한 것인지 파악 가능
  • 일관성: 모든 리소스에 같은 패턴 적용
  • 캐싱: GET 요청은 브라우저/CDN에서 자동 캐싱

실전 애매한 상황들 

상황 1: 로그인/로그아웃

문제: 로그인은 자원이 아닌 행위인데, 어떻게 표현할까?

// ❌ 동사 사용
POST /login
POST /logout

// ✅ 세션을 자원으로 간주
POST   /api/sessions          // 로그인 (세션 생성)
DELETE /api/sessions/current  // 로그아웃 (세션 삭제)

// ✅ 토큰을 자원으로
POST   /api/auth/tokens       // 토큰 발급
DELETE /api/auth/tokens       // 토큰 삭제

해결 포인트: "로그인"을 "세션 생성"으로 재해석하면 RESTful하게 표현 가능

상황 2: 비밀번호 변경

// ❌ 동사 사용
POST /changePassword

// ✅ 서브 리소스로
PUT  /api/members/{id}/password
POST /api/members/{id}/password/reset

상황 3: 복잡한 검색

문제: 검색 조건이 많아지면 URL이 너무 길어집니다.

// ✅ 간단한 검색 (조건 2-3개)
GET /api/members?name=홍길동&status=active

// ✅ 복잡한 검색 (조건 5개 이상)
POST /api/members/search
{
  "filters": {
    "name": "홍길동",
    "ageRange": { "min": 20, "max": 30 },
    "membershipTypes": ["premium", "vip"]
  },
  "page": 0,
  "size": 20
}

선택 기준: 조건이 적으면 GET, 많거나 복잡하면 POST /search

상황 4: 일괄 처리

// ❌ 반복 호출
PATCH /api/reservations/1
PATCH /api/reservations/2

// ✅ 배치 처리
PATCH /api/reservations/batch
{
  "ids": [1, 2, 3],
  "updates": { "status": "approved" }
}

상황 5: 중첩된 관계

// ❌ 너무 깊은 중첩 (3단계 이상)
GET /api/gyms/{gymId}/branches/{branchId}/trainers/{trainerId}/reservations

// ✅ 최대 2단계 또는 쿼리 파라미터
GET /api/trainers/{trainerId}/reservations
GET /api/reservations?trainerId={trainerId}

원칙: 중첩은 최대 2단계까지만!

상황 6: 상태 변경

// ✅ 간단한 경우 - PATCH
PATCH /api/reservations/{id}
{ "status": "approved" }

// ✅ 복잡한 경우 - POST
POST /api/reservations/{id}/approval
{
  "trainerId": "123",
  "note": "승인합니다"
}

선택 기준: 단순 상태만 바꾸면 PATCH, 추가 데이터나 로직 있으면 POST


HTTP 상태 코드

성공 (2xx)

200 OK          // 조회/수정 성공
201 Created     // 생성 성공 (Location 헤더 포함)
204 No Content  // 삭제 성공
202 Accepted    // 비동기 처리

클라이언트 오류 (4xx)

400 Bad Request    // 잘못된 요청
401 Unauthorized   // 인증 필요
403 Forbidden      // 권한 없음
404 Not Found      // 자원 없음
409 Conflict       // 중복
422 Unprocessable  // 처리 불가능

서버 오류 (5xx)

500 Internal Server Error
503 Service Unavailable

실무 팁: 400과 422 구분이 애매하면 400 사용. 중요한 건 팀 내 일관성!


실전 필수 팁

1. 페이지네이션

데이터를 여러 페이지로 나눠서 조금씩 가져오는 것

왜 필요? 10,000개 데이터를 한번에 조회하면 서버 터짐!

GET /api/members?page=0&size=20&sort=createdAt,desc

// 응답
{
  "content": [...],         // 실제 데이터 20개
  "totalElements": 500,     // 전체 개수
  "totalPages": 25,         // 전체 페이지 수
  "number": 0,              // 현재 페이지
  "first": true,            // 첫 페이지 여부
  "last": false             // 마지막 페이지 여부
}

2. API 버저닝

API를 여러 버전으로 관리하는 것

왜 필요? 기존 API 변경 시 배포된 앱이 작동하지 않음

GET /api/v1/members  // 기존 버전
GET /api/v2/members  // 새 버전

언제 버전업?

  • 응답 구조 변경
  • 필수 파라미터 추가
  • 기존 필드 삭제

3. 에러 응답 표준화

왜 필요? 프론트엔드가 에러를 화면에 표시하려면 일관된 형식 필요

{
  "timestamp": "2024-01-01T10:00:00",
  "status": 400,
  "error": "Bad Request",
  "message": "이메일 형식이 올바르지 않습니다",
  "path": "/api/members",
  "errors": [
    {
      "field": "email",
      "message": "유효한 이메일을 입력하세요"
    }
  ]
}

4. 자주 쓰는 쿼리 파라미터

?page=0&size=20              // 페이징
?sort=name,asc               // 정렬
?status=active               // 필터
?q=검색어                     // 검색
?startDate=2024-01-01        // 날짜 범위

핵심 요약

애매한 상황 해결 공식

  1. 동사 필요시 → 자원으로 재해석 (로그인 → 세션)
  2. 복잡한 검색 → POST /search
  3. 일괄 처리/batch
  4. 깊은 중첩 → 쿼리 파라미터
  5. 상태 변경 → 간단하면 PATCH, 복잡하면 POST

실무 핵심 4가지

  1. 페이지네이션: 데이터 많으면 필수
  2. HTTP 상태 코드: 프론트와의 약속
  3. 에러 응답 표준화: 일관된 형식 유지
  4. 일관성: 완벽함보다 중요

'-- 오늘 있었던 개발 일기' 카테고리의 다른 글

aws에 대해하여!  (0) 2026.01.06
2026년도 새해가 왔다  (0) 2026.01.05
MCP 연결에 대해!  (0) 2025.12.26
Spring 프레임워크가 무엇인가  (0) 2025.12.26
NoSql에서 트랜잭션이 가능한가?  (0) 2025.12.22