하나의 응답값에 두 개 이상의 다른 객체 반환하기

반영환·2023년 8월 28일
0

스프링 이모저모

목록 보기
12/12
post-thumbnail

Message Appender

프로젝트를 진행하면서 특정 API에서 토큰 만료기간이 긴박하면 토큰을 재발급 해주는 기능을 개발했다. 이때 만료기간이 다다른 토큰이면 ResponseEntity로 새로운 토큰을 포함한 Message를 반환해주고 다다르지 않은 토큰이면 토큰 자리에 null 값을 주어 응답값을 반환해주었다.

Message Constructor Overloading

@Getter
@NoArgsConstructor
public class Message<T> {
    public static final String DEFAULT_RESPONSE = "Request processed successfully";
    private int statusCode;
    private String message;
    private T data;
    private Token token;

    public Message(StatusCode statusCode) {
        this.statusCode = statusCode.getStatusCode();
        this.message = statusCode.getMessage();
        this.data = (T) DEFAULT_RESPONSE;
    }
    public Message(StatusCode statusCode, T data) {
        this.statusCode = statusCode.getStatusCode();
        this.message = statusCode.getMessage();
        this.data = data;
    }

    public Message(StatusCode statusCode, T data, Token token) {
        this.statusCode = statusCode.getStatusCode();
        this.message = statusCode.getMessage();
        this.data = data;
        this.token = token;
    }
}

이 경우의 문제점은 오버로딩을 진행해도 다른 컨트롤러에서 응답값을 반환할 때 token = null 이 포함돼 전송되는 것.

따라서 불필요한 데이터가 부적절한 컨트롤러에서 반환되는 것을 막고자 내부 클래스를 사용한 데이터 반환을 사용했다.

Inner Class Handling

Message Dto

@Getter
@NoArgsConstructor
public class Message<T> {
    public static final String DEFAULT_RESPONSE = "Request processed successfully";
    private int statusCode;
    private String message;
    private T data;

    public Message(StatusCode statusCode) {
        this.statusCode = statusCode.getStatusCode();
        this.message = statusCode.getMessage();
        this.data = (T) DEFAULT_RESPONSE;
    }
    public Message(StatusCode statusCode, T data) {
        this.statusCode = statusCode.getStatusCode();
        this.message = statusCode.getMessage();
        this.data = data;
    }


    public MessageAppender messageAppenderCaller( String key, Object value, StatusCode statusCode, T data) {

        MessageAppender messageAppender = new MessageAppender(key, value, statusCode, data);
        return messageAppender;
    }

    @NoArgsConstructor
    @Getter
    public static class MessageAppender<T> extends Message{
        private Map responseData = new HashMap();

        public MessageAppender(String key, Object value , StatusCode statusCode, T data) {
            super(statusCode, data);
            this.responseData.put(key,value);
        }

    }



}

controller

@GetMapping("/suiteroom")
    public ResponseEntity<Message> listUpSuiteRooms(@RequestHeader("Authorization") String authorizationHeader, AuthorizerDto authorizerDto) {
        // 토큰 재발급 부분 여기서 처리
        String token = authorizationHeader.substring("Bearer ".length());
        Token renewalToken = renewalTokenValidator(token, authorizerDto);

        List<ResSuiteRoomDto> getAllSuiteRooms = suiteRoomService.getAllSuiteRooms(getSuiteAuthorizer());

        Message.MessageAppender message = new Message.MessageAppender();
        return ResponseEntity.ok(message.messageAppenderCaller("token", renewalToken,StatusCode.OK,getAllSuiteRooms));
    }

Message 객체에서 MessageAppender 내부클래스를 선언한다.

추가적으로 받을 데이터들을 저장할 HashMap을 필드로 선언하고 생성자를 만들어준다.

중요한 것은 @Getter@NoArgConstructor인데 NoArgConstructor는 Message 객체 내부에 선언한 messageAppenderCaller를 호출하기 위한 객체를 만들기 위함이고, Getter는 JSON으로 직렬화 할 때 responseData 값을 가져오기 위함이다.

반환 객체를 하나의 엔티티가 아니라 추가적으로 더해서 응답을 보내고 싶으면 해당 내용으로 컨트롤러에서 반환해주면 불필요한 데이터를 다른 컨트롤러에서 노출시키지 않고 응답이 가능하다.

profile
최고의 오늘을 꿈꾸는 개발자

0개의 댓글