[Spring]그림으로 배우는 스프링 6 - 12장 스프링 MVC의 REST 기능

Gaeng·2024년 11월 23일

[Spring] 공부

목록 보기
13/21
post-thumbnail

스프링 MVC에서 RESTful 웹 서비스를 만들 때 편리한 기능?


1. HTTP와 메서드별로 핸들러 메서드 전환

HTTP 메서드와 @XxxMapping의 역할 정리

REST(Representational State Transfer)에서는 리소스(Resource)에 대한 다양한 작업을 HTTP 메서드로 표현합니다.
Spring Framework에서는 이 HTTP 메서드에 대응하는 어노테이션을 제공하여 직관적이고 간결하게 처리할 수 있도록 돕습니다.

어노테이션HTTP 메서드주요 역할특징
@GetMappingGET리소스 조회서버 상태를 변경하지 않음, 안전함, idempotent
@PostMappingPOST리소스 생성데이터 전송(body), 생성 작업
@PutMappingPUT리소스 전체 수정/생성전체 대체, 누락된 필드 초기화 가능성 있음
@PatchMappingPATCH리소스 일부 수정부분 수정, 효율적
@DeleteMappingDELETE리소스 삭제idempotent, 삭제 작업

1. @GetMapping

  • HTTP 메서드: GET
  • 설명: 데이터를 조회할 때 사용합니다.
  • 특징:
    • 요청의 데이터는 URL 경로나 쿼리 파라미터로 전달됩니다.
    • 서버 상태를 변경하지 않으며, 안전하고, idempotent(항상 같은 요청 결과 반환)합니다.
  • 예시:
    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return ResponseEntity.ok(userService.findById(id));
    }

2. @PostMapping

  • HTTP 메서드: POST
  • 설명: 서버에 새로운 데이터를 생성하거나 리소스를 추가할 때 사용합니다.
  • 특징:
    • 서버에 데이터를 담아 요청 본문(body)으로 전송합니다.
    • 주로 생성(create) 작업에 사용됩니다.
  • 예시:
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        return ResponseEntity.status(HttpStatus.CREATED).body(userService.save(user));
    }

3. @PutMapping

  • HTTP 메서드: PUT
  • 설명: 기존 리소스를 전체적으로 수정(대체)하거나 새로 생성합니다.
  • 특징:
    • idempotent(항상 같은 요청 결과 반환)합니다.
    • 모든 필드가 전달되지 않으면 누락된 필드가 기본값으로 초기화될 수 있으므로 주의가 필요합니다.
  • 예시:
    @PutMapping("/users/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        return ResponseEntity.ok(userService.update(id, user));
    }

4. @PatchMapping

  • HTTP 메서드: PATCH
  • 설명: 기존 리소스의 일부 필드를 수정할 때 사용합니다.
  • 특징:
    • 데이터의 부분적인 수정(partial update)에 적합합니다.
    • idempotent하며 필요한 필드만 보낼 수 있어 효율적입니다.
  • 예시:
    @PatchMapping("/users/{id}")
    public ResponseEntity<User> partiallyUpdateUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
        return ResponseEntity.ok(userService.partialUpdate(id, updates));
    }

5. @DeleteMapping

  • HTTP 메서드: DELETE
  • 설명: 서버에서 리소스를 삭제할 때 사용합니다.
  • 특징:
    • 리소스를 삭제하는 작업에 사용되며 idempotent합니다.
  • 예시:
    @DeleteMapping("/users/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }

2. 송수신하는 데이터를 적절한 형식으로 자동 변환

HttpMessageConverter로 요청/응답 데이터 변환

HttpMessageConverter란?

  • REST에서는 요청 바디와 응답 바디의 데이터를 형식을 클라이언트가 결정할 수 있음.
  • HttpMessageConverter는 Spring Framework에서 클라이언트와 서버 간의 HTTP 요청과 응답 데이터를 변환하는 데 사용되는 인터페이스
  • Spring MVC는 컨트롤러가 반환하거나 요청받는 데이터(객체와 HTTP 메시지)를 JSON, XML, String, Binary 등으로 변환하여 클라이언트와 통신할 수 있도록 합니다.
  • 이 과정에서 HttpMessageConverter가 동작합니다.
RequestResponse

요청 처리 과정 (클라이언트 → 서버)

  1. 클라이언트 요청:
    • 클라이언트가 JSON, XML 등의 데이터 형식으로 요청을 보냅니다.
    • 요청 헤더(Content-Type)와 요청 본문(body)에 데이터를 포함합니다.
  2. DispatcherServlet:
    • Spring MVC의 진입점인 DispatcherServlet이 요청을 수신합니다.
    • 요청 데이터의 Content-Type을 확인하고, 적절한 HttpMessageConverter를 선택합니다.
  3. HttpMessageConverter:
    • 요청 본문(JSON 등)을 Java 객체로 변환합니다.
    • 변환된 객체는 컨트롤러의 매개변수로 전달됩니다.
  4. Controller:
    • 컨트롤러는 변환된 객체를 사용하여 비즈니스 로직을 처리합니다.

응답 처리 과정 (서버 → 클라이언트)

  1. Controller 반환값:
    • 컨트롤러에서 처리 결과로 Java 객체를 반환합니다.
  2. DispatcherServlet:
    • 컨트롤러에서 반환된 데이터를 확인합니다.
    • 클라이언트가 요청한 데이터 형식(Accept 헤더)을 기준으로, 응답 데이터 변환을 위해 적절한 HttpMessageConverter를 호출합니다.
  3. HttpMessageConverter:
    • Java 객체를 JSON, XML 등으로 변환합니다.
  4. 클라이언트 응답:
    • 변환된 데이터를 HTTP 응답 본문에 포함해 클라이언트로 반환합니다.
  • 요청 단계: 클라이언트가 보낸 데이터를 Java 객체로 변환 (HttpMessageConverter 사용).
  • 응답 단계: 컨트롤러의 반환값(Java 객체)을 클라이언트가 요구하는 형식(JSON 등)으로 변환 (HttpMessageConverter 사용).
  • 결국, 요청이 들어왔을 때부터 응답을 반환하기까지 HttpMessageConverter가 요청 데이터와 응답 데이터를 변환하는 핵심 역할을 합니다.

3. 상태 코드 지정

@ResponseStatus

@ResponseStatus는 Spring Framework에서 HTTP 응답 상태 코드를 설정하기 위해 사용되는 어노테이션입니다. 주로 컨트롤러 메서드나 예외 클래스에 적용하여, 특정 조건에서 클라이언트에 반환할 HTTP 상태 코드를 명시적으로 설정합니다.

주요 특징

  1. HTTP 상태 코드 설정:
    • 컨트롤러 메서드 또는 예외가 처리된 후 반환할 HTTP 상태 코드를 지정합니다.
    • 예: 200 OK, 404 NOT FOUND, 500 INTERNAL SERVER ERROR.
  2. 명확한 응답 상태 관리:
    • 응답 상태 코드를 명시적으로 정의함으로써, REST API의 응답 일관성을 유지하고 클라이언트가 응답 상태를 이해하기 쉽게 만듭니다.
  3. 예외 처리에 사용:
    • 사용자 정의 예외와 함께 사용하여 특정 예외 발생 시 자동으로 HTTP 상태 코드를 반환할 수 있습니다.
@ResponseStatus(value = HttpStatus.STATUS_CODE, reason = "Reason Message")
  • value: 반환할 HTTP 상태 코드를 설정 (필수). / reason: 상태 코드에 대한 간단한 메시지(선택).

4. 요청 헤더 참조 및 응답 헤더 지정

  • @RequestHeader: 클라이언트의 요청 헤더를 읽어와 컨트롤러 메서드에서 처리.
  • @ResponseEntity: 응답 상태 코드, 헤더, 본문을 세부적으로 제어하여 클라이언트로 반환.
특징@RequestHeader@ResponseEntity
주요 역할요청의 헤더를 읽어서 컨트롤러 메서드에서 사용응답 상태 코드, 헤더, 본문을 명시적으로 설정
위치컨트롤러 메서드 매개변수에 사용컨트롤러 메서드의 반환값으로 사용
헤더 처리요청 헤더를 읽음응답 헤더를 설정함
본문(body)없음응답 본문 데이터를 포함
사용 시기클라이언트 요청 헤더를 읽어야 할 때응답 데이터와 상태를 세부적으로 제어할 때

@RequestHeader

@RequestHeader는 클라이언트가 HTTP 요청 헤더에 포함한 값을 서버의 컨트롤러에서 읽어오기 위해 사용하는 어노테이션입니다.

주요 특징

  • 요청 헤더의 값을 매개변수로 전달받아 사용할 수 있습니다.
  • 헤더 이름과 매개변수 이름이 다를 경우, 명시적으로 지정해야 합니다.
  • 기본값을 설정할 수 있어, 헤더가 없더라도 처리 가능합니다.
@RequestHeader(value = "헤더이름", required = true/false, defaultValue = "기본값")
@RestController
public class AuthController {

    @GetMapping("/secure-data")
    public ResponseEntity<String> getSecureData(@RequestHeader("Authorization") String authorizationHeader) {
        // "Bearer <JWT>"에서 JWT만 추출
        String token = authorizationHeader.replace("Bearer ", "");

        // JWT 검증 로직 (예: 서명 확인)
        if (isValidToken(token)) {
            return ResponseEntity.ok("You have access to secure data");
        } else {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid token");
        }
    }

    private boolean isValidToken(String token) {
        // 여기서 JWT를 검증 (서명 확인, 만료 여부 등)
        return true; // 실제 검증 로직으로 대체
    }
}

@ResponseEntity

@ResponseEntity는 HTTP 응답의 상태 코드, 헤더, 본문(body)을 명시적으로 설정하여 반환할 때 사용하는 클래스입니다.

주요 특징

  • 응답 상태 코드와 HTTP 헤더를 세부적으로 제어할 수 있습니다.
  • JSON, XML, 텍스트 등 다양한 응답 본문을 포함할 수 있습니다.
  • 컨트롤러의 반환값으로 사용됩니다.

구문

ResponseEntity<T>
  • T: 응답 본문의 데이터 타입.
@GetMapping("/response")
public ResponseEntity<String> getResponse() {
    return new ResponseEntity<>("Hello World!", HttpStatus.OK);
}

그림출처 : 그림으로 배우는 스프링 6

profile
문제를 해결하면서 나온 문제를 기록하는 노트

0개의 댓글