Spring Boot - 정적 멤버 클래스를 이용하여 DTO 관리하기

UkJJang·2021년 12월 7일
2

https://johngrib.github.io/wiki/java-inner-class-may-be-static/ 종립님의 글을 참고하였습니다.

DTO관리

  • 취업을 준비하면서 사이드 프로젝트로 API를 개발을 하고있는데 하나의 도메인에서 DTO가 여러개 나오게 되면서 클래스 파일도 많아지고 이걸 좀 더 효율적으로 소스코드를 줄일 수 있는 방법은 없을까? 고민을 하게 되었다. 그러던 도중 내부클래스에 대한 글을 읽게되고 이미 다른 분들이 정적멤버 클래스를 이용해서 DTO를 관리하고 계신 분들이 있었다.

이거다!!!

중첩클래스

public class MainCless{

	class SubClass {
    
    }

}
  • 클래스 안에 정의된 클래스를 중첩 클래스라고 부른다!
  • 하지만 중첩 클래스를 선언하면 static을 붙이라는 경고를 해준다.

static을 붙여야 하는 이유

  • static 내부 클래스로 선언하게 된다면 메모리 누수의 원인을 예방할 수 있고, 클래스의 각 인스턴스당 더 적은 메모리를 사용하게 된다.
  • 또한 static이 아닌 멤버 클래스는 바깥 인스턴스와 암묵적으로 연결이 되기 때문에 바깥 인스턴스 없이는 생성할 수 없다. 두 클래스 관계는 멤버 클래스의 인스턴스 안에 만들어지며 메모리를 차지하게 되고 생성도 느리다.
  • 즉 멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여 정적 멤버 클래스로 만들어주자!

결과

public class UserResponse {

    /**
     * 회원 정적 멤버 클래스
     */
    @Getter
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    public static class UserDetailResponse {
        private String email;
        private String name;
        private String phone;
        private String birth;
        private String roadAddress;
        private String detailAddress;
        private String bankName;
        private String account;

        @Builder
        public UserDetailResponse(String email, String name, String phone, 
        			String birth, String roadAddress, String detailAddress, 
                    		String bankName, String account) {
            this.email = email;
            this.name = name;
            this.phone = phone;
            this.birth = birth;
            this.roadAddress = roadAddress;
            this.detailAddress = detailAddress;
            this.bankName = bankName;
            this.account = account;
        }

    }

    /**
     * 회원 정적 멤버 클래스로 변환하여 리턴합니다.
     * @param user 유저 엔티티
     * @return 변환된 유저 상세조회 DTO
     */
    public static UserDetailResponse toDetailUser(User user) {
        return UserDetailResponse.builder()
                .email(user.getEmail())
                .name(user.getName())
                .phone(user.getPhone())
                .birth(user.getBirth())
                .bankName(user.getBankName())
                .account(user.getAccount())
                .roadAddress(user.getUserAddress().getRoadAddress())
                .detailAddress(user.getUserAddress().getDetailAddress())
                .build();
    }

}

------------------ 컨트롤러 --------------------

    @GetMapping("/{userEmail}")
    public UserResponse.UserDetailResponse getUser(@PathVariable("userEmail") String userEmail) {

        User findUser = userService.getUser(userEmail);
        return UserResponse.toDetailUser(findUser);

    }

결론

  • 마지막 정적 멤버클래스를 반환하는 메서드를 만들어서 컨트롤러에서 사용했는데 이 부분에 대해서는 잘 한건지는 아직 잘 모르겠지만 컨트롤러 단에서는 깔끔해서 확실히 보기가 좋아졌다.
  • 정적 멤버클래스를 앞으로 더 잘 사용해 봐야겠다.

혹시 잘못된 부분이 있다면 댓글로 알려주시면 감사하겠습니다!

profile
꾸준하게 성실하게

0개의 댓글