본문 바로가기

개발/Java & Spring

[Spring] ResponseEntity는 왜 쓰는 것이며 어떻게 쓰는걸까?

기존 내 개인 프로젝트 코드의 RestController 반환값은 모두 Object 타입이었다. 하지만, 일반적인 API는 반환하는 리소스에 Value만 있지 않다는 것을 모두 알고 있을 것이다. 당장 생각나는 것으로는 상태코드, 응답 메시지 등이 포함될 수 있겠다.

그럴때 사용되는 것이 ResponseEntity Class 이다. 

 

ResponseEntity는 HttpEntity를 상속받음으로써 HttpHeader와 body를 가질 수 있다. 

 

 

 

Spring MVC 로 웹페이지 구축했을 때, 제가 작성한 API 반환 타입은 Object 뿐이었습니다 . Header 값을 통해 조금 더 견고한 API를 개발했더라면 더 좋았을걸 이라는 아쉬움이 남습니다.

 

간단한 예제를 통해 ResponseEntity의 사용법을 다뤄보려고 한다. Spring Boot 2.xx 기반으로 작성하였다.

참고로 ResponseEntity의 아주 단순한 사용법만 다루는 예제이기 때문에 Restful을 준수하여 작성하진 않았다는 핑계를 던져둔다 ,, 

 

package com.example.demo.controller;

import com.example.demo.message.Message;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ResponseEntityExController {

    @GetMapping("/success")
    public ResponseEntity successMessage(){
        return new ResponseEntity<>("success", HttpStatus.OK);
    }

    @GetMapping("/serverError", produces = "application/json")
    public ResponseEntity serverErrorMessage(){
        Message message = Message.builder()
                .message1("첫번째 메시지입니다")
                .message2("메시지 두개 전달해보고 싶어서")
                .build();
        return new ResponseEntity<>(message, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @GetMapping("/onlystatus")
    public ResponseEntity onlyStatus(){
        return new ResponseEntity(HttpStatus.OK);
    }

    @GetMapping("/header")
    public ResponseEntity header(){
        MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        header.add("AUTHCODE","xxxxxxx");
        header.add("TOKEN", "xxxxxx");
        return new ResponseEntity(header, HttpStatus.OK);
    }


}

 

ResponseEntity 는 status field를 가지기 때문에 상태코드는 필수적으로 리턴해줘야 한다. 

첫 번째 API 부터, (1) 단순한 메시지(String)과 상태코드(200)를 리턴하는 것, (2) 객체를 응답하고 상태코드를 오류로 반환하는 것, (3) 상태코드만을 리턴하는 것, (4) header 와 상태코드를 리턴하는 메서드를 작성했다. 

(2)에 쓰이는 Message 클래스는 단순하다.

package com.example.demo.message;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Message {
    private String message1;
    private String message2;

    @Builder
    public Message(String message1, String message2) {
        this.message1 = message1;
        this.message2 = message2;
    }
}

 

API는 준비가 되었고 하나하나 테스트코드를 작성해보며 확인해보겠다. 

 

 

정상적으로 OK 상태코드와, "success" 메시지를 응답받는 것을 확인할 수 있다. 실제로 서버를 기동시키고 웹 페이지에서 /success 경로에 진입해본 뒤 관리자 모드(f12) > 네트워크 > 모두 보기를 들어가면 아래와 같이 메시지와 상태코드를 확인할 수 있다.

 

 

 

다음은 응답데이터로 객체와 500에러를 반환하는 API 테스트이다.

 

 

 

이 API는 JSON 객체를 응답하기 때문에 검증 시 jsonPath를 이용하였다. "$.message1"은 message1 필드를 뜻한다. 

 

해당 url을 웹페이지에서 직접 들어가보면 성공 응답을 내렸던 것과는 다른 화면이 보인다. Json 형식이기 때문에고, 네트워크 탭을 보면 역시 500 에러를 확인할 수 있다.

 

 

 

status만 반환하는 케이스는 생략하고, 마지막으로 MultiValueMap 타입의 헤더를 반환하는 API를 테스트 해본다. 

인증값과 토큰을 응답하는 API라 가정해보았다. 

 

 

 

header() 정적 메서드를 통해 값을 검증할 수 있다.

 

 

Headers 응답을 확인해보자. 예시가 딱히 적절한거같진 않지만 ^^ ; ; 

 

결과적으로 ResponseEntity는 Client의 요청에 대한 응답을 한번 더 감싸는 역할을 한다.

이러한 응답을 받은 Client 개발자는 요청 후 응답의 상태코드에 따라 다른 화면을 노출시킬 수도있고, Header값에 따라 다른 동작을 할 수도 있다. MVC의 ModelAndView 리턴에 익숙해 있다면 @RestController 의 응답도 그와 마찬가지로 데이터만 리턴해줄 수 있는데(사실 내가 그랬다) API의 목적을 잘 생각해야할 것 같다.