-
Notifications
You must be signed in to change notification settings - Fork 5
[Feature] - BE 테스트 개선 스프링 컨텍스트 캐싱 최적화 #625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Test Results 30 files 30 suites 53s ⏱️ Results for commit e2dc298. ♻️ This comment has been updated with latest results. |
eunjungL
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다 리비~
테스트에 추상화 계층이 하나 더 추가돼서 공통 로직이 잘 모이게 됐네용
덕분에 테스트 작성이 더 쉬워질 것 같슴다! 👍
| import org.springframework.boot.test.web.server.LocalServerPort; | ||
|
|
||
| @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | ||
| public abstract class AbstractControllerIntegrationTest extends AbstractIntegrationTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매번 불필요하게 반복되던 공통 로직이 잘 모였군요 👍
네이밍은 전 지금도 좋은 것 같습니다. 조금 긴 감이 있긴한데 오히려 명확한게 좋다고 생각해요~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 이름 좋다고 생각합니다! 실제로 스프링에서 제공해주는 클래스에도 Abstract로 시작하는 클래스들이 많아서 어색하지 않다고 생각되어요!
slimsha2dy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
공통 로직을 추상 클래스로 모아서 훨씬 깔끔해졌고 테스트 성능도 개선되었군요.
수고 많으셨네요 리비. 저도 네이밍은 지금이 명확해서 좋다고 생각합니다 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다 리비!!
연말이라고 약속이 많이 잡히다보니 리뷰가 많이 늦었네요 ㅠㅠ 죄송합니다
@MockBean 부분 까지 잘 처리한다면 스프링 컨텍스트를 극한으로 재활용할 수 있을 것 같아 의견 드려봤는데요!
해당 부분에 대해서만 결정 된다면 approve 드리도록 하겠습니다!
| @MockBean | ||
| private KakaoOauthProvider oauthProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MockBean 으로 인해 로그인 컨트롤러와 로그인 서비스 테스트는 각각 스프링 컨텍스트를 새로 띄우네요!
혹시 @MockBean 들도 추상 클래스에 protected 로 재정의하여 전체 컨텍스트를 2개로 줄이는 건 어떻게 생각하실까요??
다만 MemberRepository 가 전체 서비스 테스트에서 mock으로 사용시 문제가 발생하는데,
애초에 로그인 서비스 테스트에서 MemberRepository 를 목으로 사용하지 않는 것이 더 좋지 않을까 생각되네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
우선 운용하는 @MockBean은 KakaoOauthProvider 하나로 좁혀졌습니다.
MemberRepository, JwtTokenProvider 등, 필요없는 MockBean은 전부 제거하였어요
혹시 @MockBean 들도 추상 클래스에 protected 로 재정의하여 전체 컨텍스트를 2개로 줄이는 건 어떻게 생각하실까요??
그런데 @MockBean을 추상 클래스에 위치시키게 되면 MockBean이 관심사가 아닌 테스트들까지 참조가 열리게 됩니다.
- TravelogueService는 KakaoOauthProvider 목빈이 필요로 하지 않음에도 참조가 열림
그리고 MockBean을 XXXIntegrationTest에 위치시키는 것 자체가 통합 테스트를 부정하는 어폐가 있다고 생각도 드네요
MockBean을 추상클래스안에 위치시키면 스프링 애플리케이션 컨텍스트를 두개로 운용할 수 있음을 확인했는데요~ 선술한 이유를 근거로 추상클래스안에 위치시키지는 않았습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여담으로 통합테스트의 의미를 극한으로 살리기 위해서 MockBean stubbing이 아닌 MockServer를 운용하는 방식도 생각해보았어요. 이 경우 통합테스트의 의미를 살리면서 애플리케이션 컨텍스트도 캐싱하며 사용할 수 있는데요..! 이는 이번 PR의 관심사는 아닌 듯 하군요. 다음 이슈에서 작업되면 매우 좋을 것 같습니다.
MockServer 궁금하시면 다음 링크 한 번 살펴봐주세요
| import org.springframework.boot.test.web.server.LocalServerPort; | ||
|
|
||
| @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | ||
| public abstract class AbstractControllerIntegrationTest extends AbstractIntegrationTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 이름 좋다고 생각합니다! 실제로 스프링에서 제공해주는 클래스에도 Abstract로 시작하는 클래스들이 많아서 어색하지 않다고 생각되어요!
nak-honest
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제성함다 ㅎㅎ
approve를 이후에 드린다는걸 바로 드렸네요!
|
불필요한 MockBean 제거하는 개선만 수행되었습니다. |
nak-honest
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 잘 확인했습니다! 고생하셨습니다 리비!!
* [Feature] - graceful shutdown 설정 추가 #615 * [Feature] - BE 테스트 개선 1단계 Test Fixture 운용 방식 통일 (Enum Fixture) (#614) * test: OauthUserFixture - Enum 기반의 Fixture로 전환 * test: MemberFixture - EnumFixture 컨벤션 통일 개선 * test: MemberFixture 속성을 가지는 Member를 만드는 Request 객체 생성하는 기능 추가 * test: MemberFixture 속성을 기반으로 Request 객체를 만들도록 테스트 코드 수정 * test: OauthUserFixture의 팩토리 메서드 이름 수정 (createXXX -> getXXX) * test: MemberFixture의 팩토리 메서드 이름 수정 (createXXX -> getXXX) * test: 사용되지 않는 Fixture 클래스 제거 개선 * test: Travelogue관련 Enum Fixture 컨벤션 통일 개 * test: TravelogueCountry, TravelogueDay 도메인 테스트 중복 데이터 셋팅 제거 개선 * test: Request 객체 생성 도메인 Fixture 내부로 응집 * test: 도메인 구성 시 연관관계를 직접 주입하도록 테스트 코드 수정 * test: CountryCode 패키지 위치 수정 * test: TraveloguePhotoTest 연관관계 도메인 주입을 셋업 코드로 이동 개선 * test: Fixture를 통한 도메인 생성 시 연관관계를 주입하도록 로직 수정 * test: 사용하지 않는 상수 제거 개선 * test: 반복되는 메서드 모킹 setUp으로 이동 * test: 반복되는 메서드 모킹 setUp으로 이동 * test: 연관 관계를 가지는 Fixture를 주입받아 Request객체를 생성하는 기능 추가 * test: TravelogueRequestBuilder 구현 * test: TravelogueRequestBuilder에서 DayBuilder 체크로직 제거 * test: 실패하는 테스트 수정 * test: RequestBuilder 객체 패키지 이동 fixture -> helper * test: TravelPlan관련 fixture에 연관 도메인 관련 내용 제거 * test: TravelPlaceTodoFixture 구현 * test: Fixture를 통해서 Request 객체 만드는 기능 구현 * test: TravelPLanRequestBuilder 구현 * test: 과거 날짜 여행기 픽스쳐 추가 * test: Builder 클래스 개행 수정 * test: TravelPlanControllerTest에서 Request를 생성 시 RequestBuilder를 이용하도록 개선 * test: 사용하지 않는 테스트 상수 제거 개선 * test: TravelogueCountryTest 줄바꿈 컨벤션 적용 * test: TraveloguePlaceFixture 줄바꿈 컨벤션 적용 및 사용하지 않는 메서드 제거 개선 * test: TravelogueRequestBuilder와 TravelogueDayRequestBuilder 별도 클래스로 분리 * test: TravelPlanRequestBuilder와 PlanDayRequestBuilder 별도 클래스로 분리 * test: MemberFixture 이름 변경 DEFAULT_MEMBER -> TOUROOT_LOCAL_USER * [Feature] - 멤버 닉네임 중복을 허용 (#618) * feat: 멤버 닉네임 중복 검증 로직 제거 * test: 중복 닉네임 멤버 생성 테스트 제거 * [Feature] - 프로덕션 모니터링 구축 (#620) * chore: 프로덕션 loki 와 연결 * chore: 로그백 xml 파일에서 jasypt로 암호화 된 loki url을 복호화 하도록 스프링 부트의 초기화 동작 정의 * refactor: 컨벤션을 지키도록 개행 추가 Co-authored-by: eunjungL <[email protected]> * chore: dev loki url 암호화 --------- Co-authored-by: eunjungL <[email protected]> * [Feature] - BE 테스트 개선 2단계 Testcontainers 도입 (#623) * feat: testcontainers 의존성 추가 * feat: default profile logback CONSOLE appender 추가 * feat: 내장 H2 자동 활성화 제거 * feat: test datasource mysql testcontainers 도입 * fix: MySQL 문법 오류 수정 * feat: 테스트 컨테이너에 초기화 시 flyway가 실행되도록 설정 * feat: 테스트컨테이너 localstack 의존성 추가 * refactor: 내장 S3 Mocking 설정이 local 환경에만 적용되도록 수정 * feat: LocalStackContainer를 사용하는 S3TestConfig 작성 * feat: 테스트 관련 s3 클라우드 속성 값 수정 * test: 서비스 테스트가 테스트 컨테이너로 구성된 S3 설정을 바라보도록 수정 * feat: 테스트용 프로파일 이름 test로 설정 * feat: 기존 테스트에서 사용되는 프로파일 이름 수정 default -> test * feat: 각 테스트에서 test 프로파일로 테스트를 실행시키도록 수정 * refactor: s3 업로드 실패 시 stackTrace를 로깅하도록 핸들러 수정 * fix: 테스트 S3 버킷 images-base-uri 수정 * fix: 테스트에서 사용되는 Temporary 이미지 경로 영구저장소로 변경 * feat: S3 컨테이너 모킹 로직 제거 및 테스트컨테이너를 사용하도록 수정 * refactor: Testcontainers 설정 IntegrationTest로 통합 * refactor: S3 Bucket localStackContainer 실행 시 한 번만 생성하도록 변경 * feat: Controller, Service 계층 테스트에 IntegrationTest 상속 추가 * refactor: IntergrationTest S3 Bucket 이름 상수화 --------- Co-authored-by: eunjungL <[email protected]> * [Feature] - BE 테스트 개선 스프링 컨텍스트 캐싱 최적화 (#625) * refactor: 모든 서비스 테스트 스프링 부트 테스트 기반으로 통일 개 * refactor: IntegerationTest -> AbstractIntegrationTest 이름 변경 * refactor: 컨트롤러 테스트 구조 계층화 * refactor: 테스트 공통 로직 메서드명 변경 * refactor: 컨트롤러 테스트가 공통 로직을 사용하도록 추상화된 클래스 상속 * feat: 서비스 통합 테스트 추상 클래스 정의 * feat: 서비스 통합 테스트들이 추상화된 공통로직을 사용하도록 상속 * refactor: 사용하지 않는 애너테이션 제거 개선 * refactor: 불필요한 MockBean 제거 (MemberRepository, JwtTokenProvider) * refactor: MockBean 속성 접근 제어 수준 강화 (protected -> private) * [Feature] - Redis cache 도입 (#629) * feat: spring-data-redis 의존성 추가 * feat: CacheManager Redis로 변경 * refactor: EnableCaching 추가 * refactor: CacheConfig package global.config로 이동 * feat: redis 관련 설정 yml 추가 * style: 줄바꿈 컨벤션 준수 * feat: Testcontainers 레디스 모듈 의존성 추가 * feat: Testcontainers 기반 통합테스트 클래스에 레디스 컨테이너 추가 --------- Co-authored-by: libienz <[email protected]> * [Feature] - 모니터링/로깅 시스템 통합 (#633) * chore: dev 환경 톰캣에서 SSL 인증서 제거 * chore: prod loki url 변경 * chore: 깃허브 액션에서 ssl keystore 관련 부분 제거 * [Feature] - 좋아요 순 여행기 목록 조회 페이징 캐싱 (#631) * feat: 좋아요 순 여행기 목록 조회에 Cache 적용 * feat: PageImpl Deserializer 추가 * fix: PageDeserializer 제대로 동작되게 수정 * refactor: PageDeserializer 클래스 코드 정리 * fix: Sort 객체가 무조건 unsorted로 처리되던 현상 수정 * style: 필요 없는 로그 제거 * feat: 여행기 컨텐츠 페이지 캐싱 범위 설정 (PageNumber가 4이하인 것들만 캐싱) * refactor: CacheConfig 불필요한 애너테이션 제거 개선 * feat: Cache Default TTL 1시간에서 30분으로 변경 --------- Co-authored-by: libienz <[email protected]> * [Feature] - 레디스 관련 테스트 코드 작성 (#637) * test: 여행기 페이징 조회 기능 캐시 등록 테스트 작성 * test: 여행기 페이징 조회 기능 캐시 조건 테스트 작성 * test: 여행기 페이징 캐시 TTL 테스트 작성 * test: 테스트간 캐시 격리를 위한 캐시 tearDown 로직 작성 * test: ttl이 30분인지 테스트할 때 Expiration이 29-30분 사이인지 테스트 하도록 수정 * [Fix] - dev 환경 Redis host 수정 (#642) * [Feature] - 인기 여행기 페이징 응답 캐싱 무효화 전략 개선 (#644) * feat: 여행기 페이지 캐싱 시 좋아요 순 페이지 요청일 경우에만 캐싱하도록 수정 * refactor: 캐싱하는 최대 페이지 번호 상수화 * feat: Repository 통합 테스트 추상 클래스 작성 * feat: 좋아요 개수가 특정 등수만큼 많은 여행기의 좋아요 개수 조회 기능 구현 * test: 특정 등수 여행기의 좋아요 개수 조회 기능 테스트 작성 * fix: 좋아요 개수 반환 long 타입으로 수정 * feat: 여행기 좋아요가 특정 수치 이상인지 확인하는 기능 추가 * feat: 여행기 좋아요 변경 시 특정 수치 이상이면 페이징 캐싱을 무효화하는 로직 작성 * refactor: 캐시 이름 상수화 개선 * fix: Repository 테스트 롤백 기능 구현 * style: 캐시 무효화 로직 메서드 이름 변경 * style: 스태틱 임포트 제거 개선 * style: 테스트 코드 개행 개선 * [Feature] - default_batch_fetch_size 적용 (#647) * feat: default_batch_fetch_size - 100 설정 * feat: test 프로파일 default_batch_fetch_size - 100 설정 * [Feature] - TravelogueLike 조회를 fetch join으로 개선 (#649) * feat: 사용자가 좋아요한 데이터를 여행기와 여행기 작성자 정보와 함께 가져오는 기능 구현 * refactor: 사용자가 좋아요한 정보를 가져올 때 fetch join 쿼리를 사용하도록 메서드 변경 * refactor: 사용하지 않는 메서드 삭제 개선 * [Fix] - 서로 다른 테이블에 중복 저장되는 여행기 좋아요 정보 궁극적 일관성 확보 (#651) * fix: Repository 테스트에서 DataJpaTest로 인해 실 서비스와 다른 트랜잭션이 생성되지 않도록 수정 * feat: 실제 좋아요 정보와 여행기에 저장된 좋아요 개수를 동기화 하는 기능 추가 * feat: 매주 월요일 오전 3시 좋아요 개수를 동기화하는 배치 작업이 실행되도록 스케줄러 등록 * feat: ScheduleConfig에서 스케줄링 Enable * feat: redis 엔드포인트 수정 (#655) * feat: prod db 엔드포인트 수정 (#658) --------- Co-authored-by: 리비 <[email protected]> Co-authored-by: 이낙헌 <[email protected]> Co-authored-by: eunjungL <[email protected]> Co-authored-by: eunjungL <[email protected]>
✅ 작업 내용
🙈 참고 사항
추상 클래스 계층 구조를 통해 서비스 통합 테스트, 컨트롤러 통합 테스트 환경을 통일하도록 했습니다.
이전에는 10개의 애플리케이션 컨텍스트가 전체 테스트에 소모되었지만 최적화 후 4개로 줄어들었습니다.
테스트 수행시간은 5번씩 측정을 진행해보았을 때 약 39초에서 32초로 18프로 정도 개선되었습니다. (제 로컬 기준)
추상클래스 이름 추천받습니다 인스턴스화가 불가능한 추상클래스라는 점을 명세에 강조하기 위해서 Abstract을 붙여보았어요 다른 좋은 이름 생각나시면 말씀 부탁드리겠습니다.