본문 바로가기
웹 개발/spring

[spring] dto클래스에 Getter가 필요한 이유

by dani0312 2024. 2. 29.

📌DTO 클래스에 Getter가 필요한 이유

◾DTO란

DTO(Data Transfer Object)란 데이터를 이동(Transfer)시키기 위한 객체이다.

Client가 Controller에 요청을 보낼 때 RequestDto의 형식으로 데이터를 객체로 받고, controller가 Client에게 응답을 보낼 때도 ResponseDto의 형태로 데이터를 보내게 된다. 

 

https://code-lab1.tistory.com/201

 

또 controller ↔ service repository 계층간에 데이터를 교환하는 것도 이 DTO의 형태로 이동하게 된다. 응답에 있어 본다면 앞서 말했든 controller가 요청을 받고, 응답을 하는 것이 DTO의 형태이므로  service에서 repository를 이용해 데이터베이스에 있는 데이터를 찾아 DTO형태로 만들어 반환하면 controller가 이것을 다시 반환하는 것이기 때문에 같은 맥락이다. 

 

DTO는 그저 계층간 데이터 교환이 이루어 질 수 있도록 하는 역할을 하는 것으로, 순수하게 데이터 전송을 위한 객체이다. DTO는 단순히 데이터를 옮기는 용도이므로 Setter을 이용해 값을 수정할 필요 없이 생성자만을 사용하여 값을 할당한다. 

count값을 응답하는 API의 ResponseDto

 

 

◾DTO에서 Getter가 필요한 이유

 앞 단락에서 말했듯이 controller ↔ service 계층 사이 데이터 전송을 위해 DTO를 사용한다. 

 

RequestDto: 클라이언트 → 서버

ResponseDto: 서버 → 클라이언트

 

requestDto
responseDto

 

위와 같이 요청 데이터를 받거나 응답 데이터를 전송할 때 DTO 객체를 다른 데이터 형식으로 반환시켜주어야 하는데, Srping은 Jackson라이브러리를 사용하여 Json데이터를 직렬화, 역직렬화 작업을 진행한다.

 

RequestDto의 경우 controller에서 service단에 데이터를 넘길 시 빈번히 호출되기 때문에(`request.getName()`) 이 때 getter가 선언되어 있지 않으면 컴파일 에러가 발생하므로 쉽게 getter가 선언되어 있지 않을 것을 확인할 수 있다.

 

반면 ResponseDto의 경우 미리 정의해두지 않으면 컴파일 상 에러가 발생하지 않고 서버도 정상적으로 동작하기 때문에 실제 API요청을 할 때 이때서야 에러가 발생된다. 

 

따라서 아래와 같이 ResponseDto에 getter를 붙여주지 않으면 아래와 같이 역직렬화를 할 수 없기 때문에 에러가 발생한다. 직렬화는 Json → RequestDto와 같이 반대 방향의 변환이다. 

 

역직렬화 
Spring이 ResponseDto → Json형태로 변환을 할 때 객체의 getter메서드를 통해 필드 값을 읽어오기 때문에, DTO에는 필요한 필드에 대한 getter메서드를 포함시켜야 한다. 이를 빠뜨리면 JSON으로 변환할 시 해당 필드 값을 읽어올 수 없으므로, 응답이 정상적으로 이루어지지 않는다. 

 

 

➡️한 줄 요약:

즉 DTO는 데이터 변환과정(직렬화,역직렬화)에서 Getter가 필요하므로 빠뜨리면 안된다.

 

 

◾마주친 문제와 해결 과정

GET API를 사용하여 결과로 count된 개수를 반환하는 API를 POSTMAN에서 요청하고 응답을 받는데 에러가 발생하였다. 

문제는 Response Dto에 Getter메서드를 빠뜨렸기 때문이다. 

 

결과를 응답해주지 못하며 다음과 같은 에러를 내뿜었다.

2024-02-29 14:36:59.625  WARN 15484 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver
 : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]

postman 에러

 406에러이다.  Could not find acceptable representation 에러 문구를 해석해보면 '허용 가능한 표현을 찾을 수 없다'라고 한다.

 

당시의 코드는 아래와 같았다. 

🔻controller

    @GetMapping("/fruit/count")
    public GetFruitCountResponse getFruitCount(@RequestParam String name) {
        return fruitServiceDay7.getFruitCount(name);
    }

 

🔻service

    public GetFruitCountResponse getFruitCount(String name) {
        Long fruitCount = fruitRepositoryDay7.countByName(name);
        return new GetFruitCountResponse(fruitCount); <--이 부분
    }

 

service에서 new GetFruitCountResponse(FruitCount);와 같이 데이터베이스에서 찾은 count값을 GetFruitCountResponse라는 응답 dto에 담아서 반환을 해주고 있다. dto를 살펴보니 Getter가 빠져있었다. 

 

🔻GetFruitCountResponse

public class GetFruitCountResponse {
    private Long count;
    public GetFruitCountResponse(Long count) {
        this.count = count;
    }
    // getter 추가!
    public Long getCount() {
    	return count;
    }
}

 

getter를 추가해주자 정상적으로 응답을 받을 수 있었다.

 

 

 

 


Reference

https://velog.io/@rara_kim/Spring-DTO%EC%97%90-Getter%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B4%EC%9C%A0

https://code-lab1.tistory.com/201


/* 내가 추가한 코드 */ /* 내가 추가한 코드 끝끝 */