[Day 34 | Spring] REST API - @RestController

y♡ding·2024년 11월 28일

데브코스 TIL - Spring

목록 보기
42/46

1. @RestController란?

@RestController는 Spring MVC에서 RESTful 웹 서비스를 개발하기 위해 사용하는 어노테이션입니다.

기존의 @Controller@ResponseBody의 조합을 대체하여, 더 간결하게 RESTful API를 개발할 수 있습니다.


2. @RestController 특징

  1. RESTful 응답 처리:
    • 메서드의 반환 값이 뷰(view) 이름이 아닌 HTTP 응답 본문(body)에 직렬화되어 클라이언트로 전달.
    • JSON, XML, 텍스트 등 다양한 포맷으로 응답 가능.
  2. 자동 직렬화 지원:
    • 반환 객체를 JSON, XML로 변환하여 HTTP 응답 본문에 포함.
    • Spring Boot에서는 기본적으로 Jackson 라이브러리를 사용하여 JSON으로 직렬화.
  3. 간결한 코드:
    • @Controller + @ResponseBody를 결합한 형태로 코드 간결화.

3. 주요 차이: @Controller vs @RestController

특징@Controller@RestController
뷰 반환 여부뷰 템플릿(JSP, Thymeleaf 등)을 반환.데이터(JSON/XML 등)를 반환.
응답 본문 처리@ResponseBody와 함께 사용해야 응답 본문에 데이터 포함.메서드 반환 값이 기본적으로 HTTP 응답 본문에 포함.
주요 사용 사례웹 애플리케이션, 뷰 렌더링이 필요한 서비스.RESTful API, 데이터 전송이 주 목적.

4. @RestController 예제

4.1 기본 사용

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController // RESTful API를 위한 컨트롤러
@RequestMapping("/api")
public class HelloController {

    // 단순 문자열 응답
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, World!";
    }

    // JSON 객체 응답
    @GetMapping("/user")
    public User getUser() {
        return new User(1, "홍길동", "hong@example.com");
    }
}

결과

  1. GET /api/hello

    Hello, World!
    
  2. GET /api/user

    {
        "id": 1,
        "name": "홍길동",
        "email": "hong@example.com"
    }
    

4.2 Content Negotiation (콘텐츠 협상)

Spring Boot는 클라이언트의 Accept 헤더를 기반으로 JSON, XML, 텍스트 등 다양한 응답 포맷을 자동으로 결정합니다.

코드

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ContentNegotiationController {

    // 텍스트 응답
    @GetMapping(value = "/text", produces = MediaType.TEXT_PLAIN_VALUE)
    public String getText() {
        return "This is plain text!";
    }

    // JSON 응답
    @GetMapping(value = "/json", produces = MediaType.APPLICATION_JSON_VALUE)
    public User getJson() {
        return new User(1, "홍길동", "hong@example.com");
    }

    // XML 응답
    @GetMapping(value = "/xml", produces = MediaType.APPLICATION_XML_VALUE)
    public User getXml() {
        return new User(2, "이몽룡", "lee@example.com");
    }
}

결과

  • GET /text
    This is plain text!
    
  • GET /json
    {
        "id": 1,
        "name": "홍길동",
        "email": "hong@example.com"
    }
    
  • GET /xml
    <user>
        <id>2</id>
        <name>이몽룡</name>
        <email>lee@example.com</email>
    </user>
    

5. @RestController와 상태 코드 설정

RESTful API에서는 적절한 HTTP 상태 코드를 설정하는 것이 중요합니다.

예제: HTTP 상태 코드 설정

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
public class StatusCodeController {

    // 사용자 데이터 예시
    private final List<User> users = List.of(
            new User(1, "홍길동", "hong@example.com"),
            new User(2, "이몽룡", "lee@example.com")
    );

    // 사용자 조회 API
    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUserById(@PathVariable int id) {
        Optional<User> user = users.stream()
                                   .filter(u -> u.getId() == id)
                                   .findFirst();

        return user.map(ResponseEntity::ok) // HTTP 200
                   .orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).build()); // HTTP 404
    }
}

결과

  1. GET /users/1 (성공):
    • 상태 코드: 200 OK
    • 응답:
      {
          "id": 1,
          "name": "홍길동",
          "email": "hong@example.com"
      }
      
  2. GET /users/3 (실패):
    • 상태 코드: 404 Not Found
    • 응답: 없음.

6. @RestController의 고급 사용

6.1 예외 처리

예외 처리 컨트롤러

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                             .body("오류 발생: " + ex.getMessage());
    }
}

6.2 POST 요청 처리

예제 코드

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

    private final List<User> users = new ArrayList<>();

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        users.add(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(user); // HTTP 201
    }
}

POST 요청 JSON 예시

{
    "id": 3,
    "name": "성춘향",
    "email": "sung@example.com"
}

응답

  • 상태 코드: 201 Created
  • 응답:
    {
        "id": 3,
        "name": "성춘향",
        "email": "sung@example.com"
    }
    

0개의 댓글