노트

스프링 REST 컨트롤러

Spring REST Controller

백엔드#spring#http · 연결된 개념 9개

쉽게 말하면

REST 컨트롤러는 완성된 화면 대신 데이터를 JSON이라는 표준 상자에 담아 보내 주는 컨트롤러예요. 앱이든 웹이든 받는 쪽이 상자를 열어 원하는 모양으로 그려 쓰면 돼요.

비유가 깨지는 곳 상자 겉면의 송장도 중요해요. ResponseEntity로 201·204 같은 상태 코드와 헤더를 의미에 맞게 정하고, 엔티티를 그대로 담으면 민감 필드나 순환 참조가 새니 응답용 DTO를 따로 둬요.

@RestController는 메서드의 반환값을 뷰 이름이 아니라 HTTP 응답 본문(보통 JSON)으로 쓰는 컨트롤러다. @Controller에 @ResponseBody를 합친 것으로, 직렬화(serialization)는 Jackson이 맡는다.

@RestController
@RequestMapping("/api/orders")
public class OrderController {
 
    @GetMapping("/{id}")
    public OrderDto get(@PathVariable Long id) { return service.find(id); }
 
    @PostMapping
    public ResponseEntity<OrderDto> create(@Valid @RequestBody CreateOrder req) {
        OrderDto created = service.create(req);
        return ResponseEntity.created(URI.create("/api/orders/" + created.id())).body(created);
    }
}
  • @RequestBody: 요청 본문 JSON을 객체로 역직렬화(deserialization)한다. @RequestHeader로 헤더 하나를 받는다
  • ResponseEntity<T>: 상태 코드·헤더·본문을 직접 정한다. 생성은 201과 Location, 삭제는 204처럼 의미에 맞게
  • 반환 타입이 객체면 200과 그 JSON이 기본이다
  • 예외는 스프링 전역 예외 처리에서, 입력 검증은 Bean Validation에서 다룬다

Jackson 어노테이션

public record UserDto(
    @JsonProperty("user_id") Long id,   // JSON 필드 이름 바꾸기
    String name,
    @JsonIgnore String passwordHash     // 응답에서 빼기
) {}
  • 여러 필드를 빼려면 클래스에 @JsonIgnoreProperties({"a", "b"})
  • 엔티티를 그대로 반환하면 민감 필드 노출, 양방향 연관관계(bidirectional association) 무한 순환, 지연 로딩 예외가 생기기 쉽다. 응답 전용 DTO(Data Transfer Object)를 둔다

Spring Data REST

리포지터리 인터페이스를 REST 엔드포인트로 자동 노출하는 모듈이다. HAL(Hypertext Application Language) 형식으로 링크를 담아 응답하고, @RepositoryRestResource(path = "courses")로 경로를, exported = false로 노출 여부를 정한다. 빠른 프로토타입엔 편하지만 도메인 로직과 응답 형태를 통제하기 어렵다.

다른 출처의 프런트에서 부르려면 CORS 설정이 필요하고, 외부 API를 부르는 쪽은 스프링에서 외부 API 호출, 요청이 이 메서드까지 오는 과정은 Spring MVC 요청 흐름를 본다. 상태 코드와 메서드의 의미는 멱등성와 함께 맞춘다.

책: 5장. 제대로 된 REST API

출처: Spring Framework 문서: ResponseEntity

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • Spring Data 리포지터리와 쿼리 메서드

    Spring Data는 인터페이스만 선언하면 구현체를 런타임에 만들어 주는 영속성 추상화(persistence abstraction)다. JpaRepository<엔티티, ID타입>을 상속하면 저장·조회·삭제·페이징이 바로 생기고, 메서드 이름 규칙만으로 쿼리를 만들 수도 있다.

  • NestJS

    NestJS는 TypeScript를 전제로 모듈·의존성 주입(Dependency Injection, DI)·데코레이터(decorator) 구조를 제공하는 Node.js 서버 프레임워크다. 2017년 Kamil Myśliwiec가 만들었고, 구조를 강제하는 방식 때문에 흔히 "Node.js의 Spring"이라 불린다.

  • DRF 파서·렌더러와 콘텐츠 협상

    DRF에서 파서(Parser)는 요청 본문을 파이썬 자료형으로 바꾸고, 렌더러(Renderer)는 응답 데이터를 클라이언트가 받을 형식으로 바꾼다. 어떤 렌더러를 쓸지는 요청의 Accept 헤더를 보고 고르는데, 이를 콘텐츠 협상(content negotiation)이라 한다.

  • 스프링 빈과 IoC 컨테이너

    스프링 빈은 스프링 IoC(Inversion of Control, 제어의 역전) 컨테이너가 만들고, 의존성을 연결하고, 생명주기(lifecycle)를 관리하는 평범한 자바 객체(POJO, Plain Old Java Object)다. 컨테이너(ApplicationContext)는 이 빈들을 담는 공간이고, 내가 new로 만든 객체는 컨테이너가 모른다.

  • DRF 시리얼라이저

    DRF(Django REST Framework)의 시리얼라이저는 모델 인스턴스·QuerySet을 JSON으로 바꿀 수 있는 파이썬 기본 자료형으로 바꾸고(직렬화, serialization), 반대로 들어온 데이터를 검증해 모델로 만드는(역직렬화, deserialization) 틀이다. 장고의 Form과 비슷하게 필드와 검증 규칙을 선언한다.

보기 옵션