[JAVA] RESTful API 설계 원칙과 적용 방법 – 실전 사례 기반 가이드

요즘 대부분의 백엔드 시스템은 RESTful API 형식으로 설계됩니다. 하지만 REST를 표방한다고 해서 모두가 RESTful한 것은 아닙니다. 실무에서 자주 마주치는 RESTful API의 설계 원칙과 적용법을 실제 예제와 함께 설명합니다.

 

1. REST란 무엇인가?

REST(Representational State Transfer)는 2000년 Roy Fielding의 박사 논문에서 소개된 분산 시스템 아키텍처의 스타일입니다. HTTP를 기반으로 리소스를 식별하고 상태를 전이시키는 구조로, 다음과 같은 특징이 있습니다:

  • 클라이언트-서버 구조
  • 무상태성(Stateless)
  • 캐시 가능
  • 계층화 구조
  • Uniform Interface (URI, HTTP Method 등)

 

2. RESTful API 설계 원칙

RESTful API는 위의 REST 개념을 잘 따르도록 만든 API를 의미합니다. 주요 설계 원칙은 다음과 같습니다:

 

 

2.1 리소스 중심

URI는 동작이 아닌 리소스를 표현해야 합니다.

Good:  GET /users/123
Bad:   GET /getUserById?id=123

 

2.2 HTTP 메서드의 의미를 명확히

REST는 HTTP 메서드를 CRUD 동작에 맞게 사용하는 것이 핵심입니다.

  • GET: 리소스 조회
  • POST: 리소스 생성
  • PUT: 리소스 전체 수정
  • PATCH: 리소스 부분 수정
  • DELETE: 리소스 삭제

 

2.3 URI는 복수 명사 사용

Good:  /users, /orders
Bad:   /getUser, /createOrder

 

2.4 계층적 구조 표현

GET /users/123/orders/456

 

2.5 상태 코드를 일관되게 사용

적절한 HTTP Status Code를 리턴해야 클라이언트가 상황을 명확히 인지할 수 있습니다.

상태 코드 의미
200 OK 성공적인 요청
201 Created 리소스 생성 성공
204 No Content 응답 본문 없음 (삭제 등)
400 Bad Request 잘못된 요청 파라미터
401 Unauthorized 인증 실패
403 Forbidden 권한 없음
404 Not Found 리소스 없음
500 Internal Server Error 서버 내부 오류

 

3. RESTful API 실전 설계 예시

3.1 유저 리소스 예시

GET    /users              // 전체 유저 목록 조회
POST   /users              // 유저 생성
GET    /users/{id}         // 특정 유저 조회
PUT    /users/{id}         // 유저 전체 수정
PATCH  /users/{id}         // 유저 일부 수정
DELETE /users/{id}         // 유저 삭제

3.2 유저의 주문 리소스 예시

GET    /users/{id}/orders           // 해당 유저의 주문 목록
POST   /users/{id}/orders           // 주문 생성
GET    /users/{id}/orders/{orderId} // 특정 주문 조회

 

4. RESTful하게 만들기 위한 실전 팁

  • 쿼리스트링은 검색/필터링에만 사용
    예: /users?role=admin&status=active
  • HATEOAS는 선택적 – 실무에서는 오히려 단순한 구조가 더 유지보수에 유리할 때도 많음
  • 버전 관리는 URI 또는 헤더로
    예: /v1/users 또는 Accept: application/vnd.myapp.v1+json

 

5. Spring Boot에서 REST API 구현 예시

@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    public List<UserDto> getAllUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public UserDto getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    public ResponseEntity<UserDto> createUser(@RequestBody @Valid UserDto dto) {
        UserDto created = userService.create(dto);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

 

결론

RESTful API는 단지 HTTP를 사용하는 것 이상의 개념입니다. 리소스를 어떻게 명확하게 표현하고, 클라이언트와의 커뮤니케이션을 일관되게 유지할 수 있을지가 핵심입니다.

Spring Boot와 같은 프레임워크는 RESTful 설계를 돕는 많은 도구를 제공합니다. 하지만 결국 중요한 것은 명확하고 일관된 API를 제공하는 개발자의 설계 역량입니다.