[Connecti] 테스트 작성 순서 관련

CosmoNumb·2025년 1월 14일

현재 커넥티 테스트 진행 과정에서, 컨트롤러 테스트를 먼저 작성하고 서비스 테스트를 작성하는 이유

  1. 비즈니스 요구사항을 상위 레벨에서 검증하기 위함.
    컨트롤러 테스트는 애플리케이션의 외부 레이어(HTTP 요청/응답 처리)를 검증하는 역할을 하며, 사용자 요청(HTTP API 호출)이 어떻게 처리되고 어떤 결과를 반환해야 하는지를 상위 레벨에서 설계하고 확인할 수 있음.

    -> 이를 통해 비즈니스 요구사항을 상위 레벨에서 정의한 후, 하위 레이어(서비스, 리포지토리)를 구현하는 방식으로 개발할 수 있음.

  2. HTTP 인터페이스 설계를 명확히 하기 위함.
    컨트롤러 테스트를 먼저 작성하면 HTTP 인터페이스(API 설계)가 명확해짐.

    -> 어떤 URL로 어떤 HTTP 메서드(POST, GET, PUT, DELETE)를 사용하며, 요청 및 응답 데이터 형식이 어떻게 생겼는지를 컨트롤러 테스트 작성 단계에서 자연스럽게 정의할 수 있음. (외부와의 상호작용 방식을 먼저 확정)

  3. 현재 프로젝트에서 상위 레벨부터 하위 레벨로 내려가는 설계 방식을 따르고 있으므로
    컨트롤러 테스트를 먼저 작성하고, 이에 맞는 서비스 테스트 및 로직을 구현하는 방식은 상위 레벨부터 하위 레벨로 내려가는 설계 방식(Top-Down Approach)임.
    -> 이 방식은 요구사항 흐름을 따라가기 쉽고, 로직 누락이나 중복을 방지할 수 있다.

  4. 초기 단계에서 서비스 레이어가 복잡하지 않을 가능성이 있기 때문.
    초기에 서비스 레이어가 단순하거나 특정 규칙만 처리해야 한다면, 컨트롤러 테스트를 작성하면서 자연스럽게 서비스 레이어를 구현할 수 있다. -> 빠른 개발을 진행할 수 있게 됨.

(결론: 나는 TDD의 초보자이므로 사용자 요청/응답 관점에서 시작하는 것이 더 직관적임.)


최근 관점에서의 권장 방식 ~ 서비스 테스트를 먼저 작성하는 이유:

  1. 비즈니스 로직 중심 테스트
  • 서비스 계층은 핵심 비즈니스 로직을 포함하고 있어 가장 중요한 테스트 대상이먀, 컨트롤러는 단순히 요청을 받아 서비스로 전달하는 간단한 역할이 대부분이므로.
  1. 테스트 안정성
  • 컨트롤러 테스트는 HTTP 요청/응답, 시큐리티 설정 등 외부 요인에 영향을 받기 쉽다! 서비스 테스트는 이러한 외부 의존성이 적어 더 안정적이다.
  1. 개발 효율성
  • 서비스 테스트를 먼저 작성하면 비즈니스 요구사항에 집중할 수 있다. (핵심 로직이 검증된 후 컨트롤러 구현이 더 수월해짐)

즉, 서비스 테스트를 먼저 작성하면:
1. 진짜 중요한 규칙을 먼저 만들고
2. 나중에 API가 바뀌어도 핵심 기능은 안전하며
3. 사용자 입장에서 중요한 기능을 먼저 검증할 수 있다는 장점이 있다.

(이러한 접근 방식은 Martin Fowler의 글이나 Clean Architecture(Robert C. Martin)와 같은 현대적인 아키텍처 패턴에서도 강조되고 있음)


현재 진행중인 커넥티 SNS 어플리케이션에서 게시물 작성 기능을 예시로 들어 TDD 접근 방식의 차이를 알아본다.

1. 컨트롤러 테스트 먼저 작성하는 경우

@Test
void 게시물_작성_성공() {
    // given
    PostCreateRequest request = new PostCreateRequest("제목입니다", "내용입니다", List.of("image1.jpg"));
    
    // when
    ResponseEntity<PostResponse> response = postController.createPost(request);
    
    // then
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
    assertThat(response.getBody().getId()).isNotNull();
}

이 방식은 HTTP 응답이나 요청 형식에 먼저 집중하게 된다. 실제 중요한 비즈니스 로직은 아직 테스트되지 않은 상태다.

2. 서비스 테스트 먼저 작성하는 경우

@Test
void 게시물_작성시_이미지는_최대_5장까지_가능하다() {
    // given
    List<String> tooManyImages = List.of("1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg");
    
    // when & then
    assertThatThrownBy(() -> 
        postService.createPost("제목", "내용", tooManyImages))
        .isInstanceOf(TooManyImagesException.class);
}

@Test
void 게시물_내용은_최대_500자까지_가능하다() {
    // given
    String tooLongContent = "A".repeat(501);
    
    // when & then
    assertThatThrownBy(() -> 
        postService.createPost("제목", tooLongContent, List.of()))
        .isInstanceOf(ContentTooLongException.class);
}

@Test
void 게시물_작성_성공시_팔로워에게_알림이_발송된다() {
    // given
    String title = "제목";
    String content = "내용";
    List<String> images = List.of("image1.jpg");
    
    // when
    Post savedPost = postService.createPost(title, content, images);
    
    // then
    verify(notificationService).notifyFollowers(savedPost);
    assertThat(savedPost.getTitle()).isEqualTo(title);
    assertThat(savedPost.getContent()).isEqualTo(content);
}

서비스 테스트를 먼저 작성하면 다음과 같은 비즈니스 규칙들을 먼저 검증할 수 있다:
1. 이미지는 최대 5장까지만 첨부 가능하다
2. 게시물 내용은 500자를 넘을 수 없다
3. 게시물 작성 시 팔로워들에게 알림이 발송되어야 한다


이렇게 접근하면 경우의 장점:

  1. SNS 서비스에서 정말 중요한 도메인 규칙들을 먼저 검증할 수 있다
  2. 나중에 API 스펙이 바뀌더라도 (예: REST → GraphQL) 핵심 비즈니스 로직은 그대로 유지된다
  3. 실제 사용자 시나리오에 더 집중할 수 있다

(상위 항목 관련 예시 설명 추가)

1. 도메인 규칙 먼저 검증하기

  • 인스타그램에서 사진을 10장 올리려고 하면 "최대 5장까지만 가능합니다"라고 뜬다. -> 이것이 도메인 규칙임.
  • 컨트롤러 테스트만 작성하면 "응답 코드가 400이 와야 한다"는 것만 테스트하게 된다.
  • 서비스 테스트를 먼저 작성하면 "왜 5장이어야 하는지", "6장이 들어오면 어떻게 처리해야 하는지" 등 진짜 중요한 규칙을 먼저 테스트할 수 있다.

2. API 스펙이 바뀌어도 비즈니스 로직 유지

  • 음식점으로 비유하면:
    • 컨트롤러는 "주문을 받는 직원"이다 (배달앱으로 주문받을지, 전화로 받을지, 매장에서 받을지)
    • 서비스는 "요리사"다 (실제로 음식을 만드는 비즈니스 로직)
  • 주문 방식(API)이 바뀌어도 요리(비즈니스 로직)는 그대로다
  • 서비스 테스트를 먼저 하면 "음식이 제대로 만들어지는지"를 먼저 검증할 수 있다

3. 실제 사용자 시나리오에 집중

  • 컨트롤러 테스트만 하면: "API 호출했을 때 응답이 잘 오는가?"만 확인
  • 서비스 테스트를 먼저 하면:
    • "사용자가 게시물을 작성하면 팔로워에게 알림이 가야 한다"
    • "게시물에 욕설이 있으면 작성이 안 된다"
    • "해시태그는 최대 10개까지만 가능하다"
      실제 사용자가 경험하는 기능들을 먼저 테스트할 수 있다

->그렇지만 "반드시" 따라야 하는 규칙은 아님.
프로젝트의 특성이나 팀의 상황에 따라 컨트롤러 테스트를 먼저 작성하는 것이 더 효율적일 수도 있으며, 특히 API 스펙이 먼저 확정되어야 하는 경우라면 컨트롤러 테스트를 먼저 작성하는 것이 유리할 수 있음.

0개의 댓글