[Spring] @ResponseBody VS ResponseEntity<T>

2025. 1. 6. 10:51·BackEnd/Spring & JPA

1. @ResponseBody란?

@ResponseBody는 Spring MVC에서 컨트롤러 메서드가 반환하는 값을 HTTP 응답 본문으로 직렬화하여 클라이언트에게 전달할 때 사용됩니다. 반환되는 데이터는 Jackson 라이브러리를 사용하여 JSON 형식으로 변환됩니다. 기본적으로 HTTP 상태 코드는 200 OK로 설정되며, 데이터만 반환하는 단순한 API 응답 처리에 주로 사용됩니다.

1.1 @ResponseBody의 주요 특징

  • JSON, XML과 같은 포맷으로 데이터를 반환
  • HTTP 상태 코드는 기본적으로 200 OK
  • 주로 REST API 응답에서 사용
  • 뷰를 반환하지 않고 데이터를 직렬화하여 전달

2. ResponseEntity란?

ResponseEntity는 HTTP 응답의 상태 코드, 헤더, 본문을 모두 명시적으로 제어할 수 있는 클래스로, 더 복잡한 HTTP 응답 처리가 필요할 때 사용됩니다. 단순히 본문 데이터뿐만 아니라, HTTP 상태 코드나 추가적인 응답 헤더 등을 세밀하게 구성할 수 있습니다.

2.1 ResponseEntity의 주요 특징

  • 응답 본문, 헤더, 상태 코드 등을 직접 설정 가능
  • 클라이언트에게 상태 코드와 함께 명확한 응답을 보낼 수 있음
  • 오류 처리나 다양한 상태 코드가 필요한 API 설계에 유용

3. @ResponsBody와 ResponseEntity의 차이점

항목 @ResponseBody ResponseEntity
사용 목적 단순히 데이터를 반환하고 싶을 때 사용 상태 코드, 헤더 등 응답 전체를 제어하고 싶을 때 사용
HTTP 상태 코드 제어 200 OK로 고정 (명시적 제어 어려움) 상태 코드를 명시적으로 설정 가능
응답 헤더 제어 불가능 헤더를 직접 설정 가능
에러 처리 불편 에러 상태 코드와 메시지를 명확하게 제어 가능
주요 사용 사례 간단한 API 응답 복잡한 API 응답, 상태 코드와 헤더가 중요한 경우

4. @ResponseBody와 ResponseEntity를 이용한 회원 관련 예시 코드

아래의 예시는 회원 정보를 처리하는 간단한 API 컨트롤러를 @ResponseBody와 ResponseEntity를 사용하여 작성한 것입니다. 이 예시는 서비스 계층에서 회원 정보를 조회하거나 저장하는 방식으로 동작하며, 각각의 상황에 맞는 상태 코드와 헤더 등을 설정하는 방식입니다.

4.1 @ResponseBody를 사용한 컨트롤러 예시 코드

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

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user != null) {
            return user;
        } else {
            throw new UserNotFoundException("User not found");
        }
    }

    @PostMapping
    @ResponseBody
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }
}

위 @ResponseBody 사용 예시에서는 간단하게 회원 정보를 JSON 형식으로 반환합니다. HTTP 상태 코드는 자동으로 200 OK로 설정되며, 에러 처리를 위해서는 예외를 따로 처리해야 합니다. UserNotFoundException 같은 커스텀 예외는 별도로 처리해야 합니다.

서비스단 코드

@Service
public class UserService {

    public User getUserById(Long userId) {
        // DB에서 회원 정보 조회 (실제 로직은 생략)
        if (userId == 1L) {
            return new User(1L, "John", "Doe", "john@example.com");
        } else {
            return null; // 회원 정보가 없는 경우
        }
    }

    public User saveUser(User user) {
        // DB에 회원 정보 저장 (실제 로직은 생략)
        user.setId(2L); // ID가 생성된 경우로 가정
        return user;
    }
}

4.2 ResponseEntity를 사용한 컨트롤러 예시 코드

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

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<?> getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user != null) {
            // 성공적인 응답: 200 OK와 함께 사용자 정보를 반환
            return ResponseEntity.ok()
                    .header("Custom-Header", "User found")
                    .body(user);
        } else {
            // 회원을 찾을 수 없는 경우: 404 Not Found 응답
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .header("Custom-Header", "User not found")
                    .body("User not found with ID: " + id);
        }
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.saveUser(user);
        // 201 Created 응답과 함께 생성된 회원 정보 반환
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(createdUser);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) {
        // 예외 처리: 404 상태와 에러 메시지를 반환
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ex.getMessage());
    }
}

위 예시에서는 ResponseEntity를 사용하여 상태 코드, 헤더, 응답 본문을 명시적으로 제어하는 방식을 보여줍니다. 다음과 같은 추가적인 기능을 제공합니다.

  • 사용자 정보를 성공적으로 조회했을 때 200 OK와 함께 데이터를 반환
  • 사용자를 찾지 못했을 경우 404 Not Found와 함께 에러 메시지 반환
  • 사용자를 생성했을 때는 201 Created 상태 코드와 생성된 회원 정보를 반환

5. 참고사항 - @RestController에서 @ResponseBody 어노테이션을 안써도 JSON형태로 반환 잘 되지않나?

@ResponseBody는 원래 Spring MVC에서 컨트롤러 메서드의 반환 값을 HTTP 응답 본문으로 변환하는 역할을 하는 어노테이션입니다. 하지만, @RestController는 내부적으로 @Controller와 @ResponseBody가 결합된 형태이기 때문에, @RestController를 사용하는 경우에는 메서드 위에 @ResponseBody를 명시적으로 붙이지 않아도 자동으로 JSON 또는 XML 형태로 데이터를 반환합니다.

5.1 @RestController에서의 동작 방식

@RestController는 @Controller + @ResponseBody가 포함된 어노테이션이기 때문에, 모든 메서드의 반환 값이 자동으로 JSON 형식으로 직렬화됩니다. 따라서 @RestController가 적용된 클래스에서 메서드를 정의할 때는, @ResponseBody를 명시적으로 붙이지 않아도 데이터는 JSON 형식으로 반환됩니다.

@RestController 어노테이션만 사용한 컨트롤러 예시 코드

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

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user != null) {
            return user;
        } else {
            throw new UserNotFoundException("User not found");
        }
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }
}

위 코드에서 @ResponseBody를 제거했지만, 여전히 JSON 형식으로 반환됩니다. 이는 @RestController가 자동으로 @ResponseBody 역할을 수행하기 때문입니다.

5.2 @RestController가 없는 경우

만약 @RestController가 아닌 @Controller를 사용한다면, 메서드의 반환 값은 뷰 이름으로 해석되어 JSP나 HTML 같은 뷰를 렌더링하려고 시도합니다. 이때 데이터를 반환하고 싶다면, @ResponseBody를 명시적으로 추가해야 데이터가 JSON 형태로 반환됩니다

@Controller 예시 코드

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

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user != null) {
            return user;
        } else {
            throw new UserNotFoundException("User not found");
        }
    }

    @PostMapping
    @ResponseBody
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }
}

6. 정리

  • @RestController는 내부적으로 @ResponseBody를 포함하므로, 메서드에서 반환되는 객체는 자동으로 JSON 형식으로 직렬화되어 클라이언트에게 전달됩니다. 따라서 @ResponseBody를 명시적으로 붙일 필요가 없습니다.
  • @Controller를 사용하는 경우, 메서드에서 반환 값을 JSON으로 변환하여 응답하려면 @ResponseBody를 명시적으로 붙여야 합니다.

'BackEnd > Spring & JPA' 카테고리의 다른 글

[Spring Boot] MySQL Master/Slave 복제 설정과 Read/Write 자동 분기 처리 방법 정리  (0) 2025.03.24
[Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)  (0) 2025.02.13
[Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유  (0) 2025.01.21
[Spring] @Controller VS @RestController  (0) 2025.01.06
[Spring] 스프링 개념 및 동작 원리 정리  (0) 2025.01.05
'BackEnd/Spring & JPA' 카테고리의 다른 글
  • [Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)
  • [Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유
  • [Spring] @Controller VS @RestController
  • [Spring] 스프링 개념 및 동작 원리 정리
개발자 동긔
개발자 동긔
배우고 느낀점들을 기록합니다. 열정 넘치는 백엔드 개발자로 남고싶습니다.
  • 개발자 동긔
    Donker Dev
    개발자 동긔
  • 전체
    오늘
    어제
    • Category (39)
      • BackEnd (23)
        • JAVA (15)
        • Spring & JPA (7)
      • Database (4)
      • Computer Science (2)
        • Network (0)
        • Security (0)
        • Web (1)
      • DevOps (6)
        • Docker (1)
        • Jenkins (0)
        • Monitoring (2)
        • CICD (1)
      • 트러블 슈팅 (3)
      • 성능 개선 (1)
      • Project (0)
  • 인기 글

  • 태그

    spring boot
    @RequestBody
    interface
    mysql master/slave replication
    와일드카드
    restful api
    CICD
    인터페이스
    docker compose
    JPA
    spring cloud msa
    docker
    java
    nginx
    Spring
    restful api 설계
    master/slave db 이중화 처리
    Jenkins
    Database
    SSH
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
개발자 동긔
[Spring] @ResponseBody VS ResponseEntity<T>
상단으로

티스토리툴바