[Java] 운영 환경과 동일한 형태의 DTO Class를 테스트 환경에서 사용한 이유 - Nested Class와 프로젝트 변경점 관리 및 유지보수성을 중심으로 살펴보며

Hyo Kyun Lee·2025년 9월 26일
0

Java

목록 보기
101/106

1. 개요

개인 프로젝트를 진행하면서 중첩 클래스(Nested Class)를 테스트 환경에서 사용하는 경우를 보게 되었다.

운영 main src에 멤버 등의 모든 형태가 동일한 DTO Class가 있음에도, 테스트 환경에서 별도의 중첩 DTO Class를 선언한다는 상황이 어색해보였다.

단순히 테스트 환경이 운영환경과 분리되었다는 이유로 DTO Class를 또다시 재사용하기엔 변경점 관리나 유지보수성 측면에서 그리 좋지 못한 선택인 것 같은데, Nested Class의 개념과 함께 이러한 구성 이유를 살펴보게 되었다.

2. DTO Class를 테스트 환경에서 중첩사용한 상황

아래와 같이 API 통합테스트를 진행하기 위해 Test 구성환경을 살펴보던 중에 CommentApiTest 최하단에 static class로 CommentCreateRequest가 정의되어있는 것을 확인하였다.

public class CommentApiTest {
    RestClient restClient = RestClient.create("http://localhost:9001");

    @Test
    void create() {
        CommentResponse response1 = createComment(new CommentCreateRequest(1L, "my comment1", null, 1L));
        CommentResponse response2 = createComment(new CommentCreateRequest(1L, "my comment2", response1.getCommentId(), 1L));
        CommentResponse response3 = createComment(new CommentCreateRequest(1L, "my comment3", response1.getCommentId(), 1L));

        System.out.println("commentId=%s".formatted(response1.getCommentId()));
        System.out.println("\tcommentId=%s".formatted(response2.getCommentId()));
        System.out.println("\tcommentId=%s".formatted(response3.getCommentId()));

//        commentId=123694721668214784
//          commentId=123694721986981888
//          commentId=123694722045702144
    }

    CommentResponse createComment(CommentCreateRequest request) {
        return restClient.post()
                .uri("/v1/comments")
                .body(request)
                .retrieve()
                .body(CommentResponse.class);
    }
    
    @Getter
    @AllArgsConstructor
    public static class CommentCreateRequest {
        private Long articleId;
        private String content;
        private Long parentCommentId;
        private Long writerId;
    }
}

이 정적 클래스로 선언된 CommentCreateRequest는 운영환경에서도 이 형태 그대로 사용하고 있는 요청 객체인데, 변경점 관리나 유지보수성 측면(중복 등)에서 이득일 수 없는 이러한 상황이 왜 발생하였을까?

2. Nested Class

일단 먼저 중첩 클래스(Nested Class)가 무엇이며, 언제 사용하는지에 대해 먼저 살펴보는 것이 좋겠다.

Nested Class로 사용할 수 있는 형태는 아래와 같이 총 4가지가 있는데, 각각의 정의나 사용목적이 아예 다르기 때문에 그 특성을 잘 구분할 필요가 있겠다.

정적 중첩 클래스(Static Nested Class)

  • 특정 환경과 분리된 환경에서 자체적/독립적인 클래스 운용이 필요할 경우
  • 자체적으로 정적 클래스를 정의하여 사용하며, 현재의 경우와 같이 필드멤버로의 목적을 명시하기 위해 static으로 선언하여 사용한다.

내부 클래스(Inner Non-static Class)

  • 특정 환경 Class에 종속하여 사용하기 위해 사용하는 클래스로, 외부 클래스 멤버에 접근가능하다.
  • 종속하여 사용하므로 결합도가 매우 높고, 환경적으로 동일하거나 변경점 관리가 거의 없을때 활용하는 것이 좋다.

지역 클래스(local Class)

  • 메서드 내부에서 선언되어 메서드 내부에서만 사용하는 클래스.

익명 클래스(Anonymous Class)

  • 1회성 구현체, 이름없이 바로 선언하여 활용하는 클래스
  • 주로 람다 함수의 매개변수에 활용한다.

3. 테스트 환경에서 중첩 DTO 클래스를 활용하는 이유

이러한 Nested Class의 정의와 함께 살펴보면, 더더욱 테스트 환경에서 동일한 형태의 DTO Class를 정적으로 선언하여 사용할 필요가 없어진다.

기본적으로 운영과 형태가 동일하다면, 운영의 DTO 클래스를 그대로 사용하여 변경점이 발생하여도 별도 관리가 필요없기에 유지관리에 유리하기 때문이다.

이 경우는 테스트 로직을 작성하면서 자체적으로 필요한 중첩 DTO 클래스를 선언하면서 시작된 이유로, 시간차로 인해 발생한 잔존으로 보면 되겠다.

테스트 환경에서 테스트를 위한 중첩 클래스를 활용하는 이유보다는, 중첩 클래스가 왜 잔존하는지에 대한 이유를 살펴보았는데, 어떠한 형태의 클래스 혹은 환경 구성을 어떠한 상황에서 활용하는지 더 살펴볼 수 있었던 계기가 되었다.

0개의 댓글