cleanup 전략별 통합 테스트 수행 시간 — 4가지 케이스 비교

통합 테스트 cleanup 방식 전환으로 누적 수행 시간 개선

테스트 코드를 실무에 적용하면서 겪는 문제들 복잡했던 도메인 로직들이 리팩토링되고, 필요한 Fixture를 만들어두니 테스트 코드 작성 속도가 빨라지고 있다. 요즘은 매 스프린트마다 테스트 개수가 크게 증가하며, 하나 둘씩 관련 문제가 생기고 있다. 지난 포스트에서는 Application Context(이하 컨텍스트)의 증가1로 인해 MySQL로 연결되는 커넥션 수가 max_connections에 도달해서 발생하는 Too Many Connections을 다뤘다. 클래스마다 MockBean 조합이 다르면 Spring 컨텍스트의 캐시미스가 발생하여 Spring이 컨텍스트를 새로 만들기 때문에, MockBean을 통합하는 방식으로 해결할 수 있었다. 현재는 어드민 권한 테스트용 하나와 일반 유저 테스트용 하나의 컨텍스트로 총 2개만 유지되도록 매 스프린트마다 유지보수하는 중이다. ...

April 20, 2026 · 5 min · 1034 words · Gukin Han
Last updated April 28, 2026
6개의 ApplicationContext가 MySQL max_connections를 초과하는 다이어그램

Spring 통합 테스트의 다중 ApplicationContext로 인한 Too many connections

개별 테스트는 통과, 전체 실행시 Too many connections 발생 여러 기능 브랜치가 개발 브랜치로 머지된 후, 그동안 기능 개발하면서 놓친 실패 테스트들을 점검하기 위해 전체 테스트를 실행했다. Too many connections 에러로그가 발생하면서 통합테스트들 일부가 실패하였다. 로그의 일부는 아래와 같다: Error creating bean with name 'liquibase': Too many connections → Error creating bean with name 'databaseCleanupUtil' → Failed to load ApplicationContext 하지만, 각각 테스트 클래스들을 개별로 실행했을때는 모두 통과했다. 도대체 왜 동일한 코드에서 실행 범위만 다를 뿐인데 결과가 다를까? ...

April 1, 2026 · 7 min · 1411 words · Gukin Han
jdbc.resultset ON/OFF에 따른 TPS 비교 그래프

시간당 34GB Spring Boot 로깅이 TPS에 미치는 영향과 병목점 분석

시간당 34GB의 로그 발생 사내 인프라 담당자가 우리가 담당하고 있는 서버의 로깅 설정 관련된 내용을 공유해주었다. 간단하게 정리하면 다음과 같다: Cloudwatch는 로그 GB마다 과금되는 형태 불필요한 로그로 인해 비용이 발생하는것으로 확인됨 현재 서비스에서 발생하는 로그(특히 info)를 점검할 필요가 있음 도메인 개발자라서 인프라 업무를 직접 수행할 기회와 권한이 없었다. 이번에 인프라팀이 공유해준 걸 계기로 개인적으로 살펴보았다. 먼저 Cloudwatch에 들어가 직접 눈으로 로그 발생량을 확인했다. 우리 서비스는 HR 서비스이기 때문에 대부분의 트래픽은 9시부터 18시 사이에 발생한다. 시간당 대략 34GB(2.7억건)의 로그가 발생하며 그 중에 44% 정도가 jdbc.resultset=INFO 에서 발생함을 확인했다. 여기서 몇 가지 의문이 들었다. ...

March 1, 2026 · 7 min · 1460 words · Gukin Han
REDIS_SCHED 모드 아키텍처

트랜잭션에서 이벤트로 - Sync / Async / Redis 성능 비교와 TTV 분석

문제 @Transactional public void like(String loginId, Long productId) { // 1. 유저 조회 User user = userService.getByLoginId(loginId); // 2. 상품-좋아요 Insert boolean isInserted = productLikeRepository .insertIgnoreDuplicateKey(user.getUserId(), productId); if (!isInserted) return; // 3. 좋아요 수 집계 Update productRepository.incrementLikeCount(productId); } 좋아요 기능에서 처음엔 모든 로직을 하나의 트랜잭션 안에서 동기적(Sync)으로 처리 안정적이지만 트랜잭션 크기가 커지고, 상품 핫키에 경합으로 인한 병목이 발생 그래서, 이벤트 기반 설계를 통해 결합도를 낮추고(loosely coupled), 책임을 분리하려는 시도 Github PR : https://github.com/gukin-han/commercial-service/pull/7 ...

August 29, 2025 · 4 min · 743 words · Gukin Han

좋은 테스트는 무엇인가? 레거시 시스템에 테스트 환경 구축

요약 반복적인 수동테스트로 불편함을 느껴서 테스트 환경을 구축하였습니다 구축하고 테스트를 작성하는 과정에서 구성 방식, 데이터 클린업 등에 대한 고민을 하였습니다 결과적으로 어떻게 설계하고 테스트를 작성할지 자신만의 기준을 정할 수 있게 되었습니다 수동 테스트의 반복 비용 마이클 페더는 “레거시 코드 활용 전략”에서 레거시 코드를 다음과 같이 정의했다: “테스트가 없는 코드는 곧 레거시 코드다” 테스트 코드가 없는 조직은 신기능 개발이나 이슈로 인한 코드 수정이 발생하면 일부 기능에 대한 수동 테스트를 진행하게 된다. 예를 들어, 연차를 생성하는 옵션에 요구사항이 바뀌면 연차 생성을 위한 옵션 설정을 하고 여러 직원, 근무형태 케이스에 대해 모두 테스트를 진행하게 된다. 아무래도 다양한 경우의 수를 확인하기 어렵기 때문에 숨어있는 모든 버그를 찾아내기란 쉽지 않았다. ...

July 18, 2025 · 6 min · 1251 words · Gukin Han