Post

스프링 부트 REST API 개발 시 자주 하는 실수 TOP 10

스프링 부트로 REST API를 개발할 때 개발자들이 자주 저지르는 10가지 실수를 정리하고, 이를 해결하기 위한 모범 사례와 코드 예제를 제공한다.

스프링 부트 REST API 개발 시 자주 하는 실수 TOP 10

REST API는 현대 웹 애플리케이션 개발에서 핵심적인 부분이다. 스프링 부트는 강력한 REST API 개발 도구를 제공하지만, 개발자들이 흔히 범하는 실수들이 있다. 아래에서 스프링 부트 REST API 개발 시 가장 흔히 발생하는 10가지 실수와 그 해결책을 알아보자.


1. 적절한 HTTP 상태 코드 사용하지 않기

문제점: 많은 개발자들이 모든 응답에 대해 200 OK 상태 코드만 사용하고, 응답 본문에 성공/실패 메시지를 포함시킨다.

해결책: HTTP 프로토콜은 다양한 상태 코드를 제공한다. 이를 적절히 활용하자:

  • 200 OK: 요청 성공
  • 201 Created: 리소스 생성 성공
  • 204 No Content: 성공했지만 반환할 내용 없음
  • 400 Bad Request: 잘못된 요청
  • 401 Unauthorized: 인증 필요
  • 403 Forbidden: 권한 없음
  • 404 Not Found: 리소스 없음
  • 500 Internal Server Error: 서버 오류
1
2
3
4
5
6
7
8
9
10
11
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
    User savedUser = userService.save(user);
    return new ResponseEntity<>(savedUser, HttpStatus.CREATED);
}

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

2. URL에 동사 사용하기

문제점: REST API URL에 동사를 사용하는 것은 REST 원칙에 맞지 않는다.

잘못된 예:

1
2
3
/getAllUsers
/createUser
/deleteUser/{id}

올바른 예:

1
2
3
GET /users - 모든 사용자 조회
POST /users - 새 사용자 생성
DELETE /users/{id} - 특정 사용자 삭제

3. 예외 처리 미흡

문제점: 많은 API가 적절한 예외 처리 없이 기본 오류 응답을 반환한다.

해결책: 전역 예외 처리기를 사용하여 일관된 오류 응답 형식을 제공하자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("NOT_FOUND", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
        ErrorResponse error = new ErrorResponse("INTERNAL_ERROR", "예상치 못한 오류가 발생했다");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

4. 버전 관리 부재

문제점: API 버전 관리가 없으면 기존 클라이언트에 영향을 주지 않고 API 변경이 어렵다.

해결책: URL, 헤더, 매개변수 등을 통해 API 버전을 관리하자:

1
2
3
4
5
6
7
8
9
10
// URL 기반 버전 관리
@RequestMapping("/api/v1/users")
public class UserControllerV1 { ... }

@RequestMapping("/api/v2/users")
public class UserControllerV2 { ... }

// 헤더 기반 버전 관리
@RequestMapping(value = "/api/users", headers = "X-API-VERSION=1")
public class UserControllerV1 { ... }

5. 페이지네이션 구현 미흡

문제점: 대량의 데이터를 반환할 때 페이지네이션이 없으면 성능 문제가 발생한다.

해결책: 스프링 데이터의 페이지네이션 지원을 활용하자:

1
2
3
4
5
6
7
8
9
@GetMapping
public ResponseEntity<Page<User>> getAllUsers(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size) {
    
    Pageable pageable = PageRequest.of(page, size);
    Page<User> users = userService.findAll(pageable);
    return ResponseEntity.ok(users);
}

6. 적절한 응답 형식 사용하지 않기

문제점: 일관되지 않은 응답 형식은 클라이언트 측 처리를 복잡하게 만든다.

해결책: 표준화된 응답 형식을 사용하자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ApiResponse<T> {
    private boolean success;
    private String message;
    private T data;
    
    // 생성자, getter, setter 생략
}

@GetMapping("/{id}")
public ResponseEntity<ApiResponse<User>> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    ApiResponse<User> response = new ApiResponse<>(true, "사용자를 성공적으로 조회했다", user);
    return ResponseEntity.ok(response);
}

7. API 문서화 부족

문제점: 문서화되지 않은 API는 사용하기 어렵고 유지보수가 힘들다.

해결책: Swagger/OpenAPI와 같은 도구를 사용하여 API를 문서화하자:

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("사용자 관리 API")
                        .version("1.0")
                        .description("사용자 관리를 위한 REST API 문서"));
    }
}

8. 입력 유효성 검사 부족

문제점: 유효성 검사가 없으면 잘못된 데이터가 시스템에 저장될 수 있다.

해결책: Bean Validation을 사용하여 입력 데이터를 검증하자:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserRequest {
    @NotBlank(message = "이름은 필수다")
    private String name;
    
    @Email(message = "유효한 이메일 주소를 입력해야 한다")
    private String email;
    
    @Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 한다")
    private String password;
    
    // getter, setter 생략
}

@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody UserRequest userRequest) {
    // 유효성 검사를 통과한 요청 처리
}

9. 하이퍼미디어 링크(HATEOAS) 부재

문제점: REST API의 중요한 원칙 중 하나는 하이퍼미디어를 통한 자기 설명적 특성이다.

해결책: 스프링 HATEOAS를 사용하여 관련 리소스에 대한 링크를 제공하자:

1
2
3
4
5
6
7
8
9
10
11
@GetMapping("/{id}")
public ResponseEntity<EntityModel<User>> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    
    EntityModel<User> resource = EntityModel.of(user);
    resource.add(linkTo(methodOn(UserController.class).getUser(id)).withSelfRel());
    resource.add(linkTo(methodOn(UserController.class).getAllUsers(0, 10)).withRel("users"));
    resource.add(linkTo(methodOn(OrderController.class).getOrdersByUser(id)).withRel("orders"));
    
    return ResponseEntity.ok(resource);
}

10. 보안 고려 부족

문제점: REST API에서 보안을 간과하면 심각한 취약점이 발생할 수 있다.

해결책:

  • HTTPS 사용
  • JWT 또는 OAuth2와 같은 안전한 인증 방식 구현
  • 입력 데이터 검증
  • CORS 구성
  • 속도 제한 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()  // REST API에서는 CSRF 보호가 필요 없을 수 있음
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer().jwt();  // JWT 토큰 사용
        
        return http.build();
    }
}

결론

스프링 부트로 REST API를 개발할 때 이러한 일반적인 실수를 피하면 더 나은 품질의 API를 제공할 수 있다. REST 원칙을 준수하고, 적절한 상태 코드를 사용하며, 예외를 적절히 처리하고, API를 문서화하는 것이 중요하다. 또한 페이지네이션, 버전 관리, 유효성 검사, 보안을 고려하면 더 강력하고 확장 가능한 API를 구축할 수 있다.

REST API 개발은 단순히 기능만 구현하는 것이 아니라, 좋은 설계 원칙과 실천 방법을 따르는 것이 중요하다. 이 글에서 제시한 실수와 해결책을 참고하여 더 나은 REST API를 개발하길 바란다.

출처

이 글은 Java Guides의 Top 10 Spring Boot REST API Mistakes 포스팅을 번역 및 재구성한 것이다. 원문에서 제시된 REST API 개발 시 흔한 실수와 해결책을 바탕으로 스프링 부트 환경에 적합하게 정리했다.

This post is licensed under CC BY 4.0 by the author.