순서 변경과 롤백 확인
110분 안팎
학습 목표
실행 순서 의존과 트랜잭션 롤백을 재현합니다.
개념
순서 변화로 숨은 의존을 드러냅니다
가입, 중복 가입, 로그인 테스트를 늘 같은 순서로 실행하면 앞 사례의 준비에 의존한 검사가 계속 통과할 수 있습니다. 각각 독립 준비를 갖춘 뒤 정방향과 역방향, seed 17로 섞은 순서를 실행합니다. 순서 변화는 의존을 찾는 진단 방법이고 격리 자체를 대신하지 않습니다. 실패한 순서와 seed, 실행 이름 공간을 기록하여 같은 조건으로 재현할 수 있게 합니다.
제공 IsolationTest의 orderAndSeed는 실제 MemberApi를 MockMvc로 호출하고 SQL로 결과를 관찰합니다. signup 사례는 가입 성공, duplicate 사례는 자체 준비 뒤 중복 거절, login 사례는 자체 준비 뒤 인증 성공을 검사합니다. 각 사례가 끝나면 IsolationSupport.cleanup을 호출하고 원래 이메일 집합과 같아야 합니다. 정렬된 비교로 조회 순서 잡음을 없애지만 계정 내용 오류를 덮지는 않습니다.
롤백을 검증할 저장 경계입니다
이전 앱 members는 한 테이블의 저장으로 단순화되어 있습니다. 이번 롤백 실습은 같은 H2 연결 환경에 iso_users와 iso_profiles를 추가한 별도 저장 모델입니다. 사용자와 프로필이 함께 생겨야 하는 계약을 savePair로 표현합니다. 기존 가입 엔드포인트가 이 새 모델을 쓴다고 주장하지 않습니다. 미션은 API 데이터 격리와 다중 테이블 저장의 원자성 증거를 구분하여 보고합니다.
IsolationSupport.savePair는 JdbcTemplate과 TransactionTemplate을 받습니다. 사용자 INSERT 후 의도적으로 profile write failed를 던지거나 프로필 INSERT를 완료합니다. RuntimeException이 트랜잭션 콜백 밖으로 전파되면 두 저장을 함께 취소하는 조건을 검사합니다. 예외를 내부에서 잡아 정상 종료하면 커밋될 수 있으므로 오류 처리와 롤백 정책을 함께 읽습니다.
테스트 트랜잭션으로 가리지 않습니다
테스트 메서드 전체에 자동 롤백 트랜잭션을 두면 제품 저장 코드에 트랜잭션이 없어도 테스트 종료 뒤 DB가 비워져 원자성 결함이 숨을 수 있습니다. 제공 테스트는 메서드에 Transactional을 붙이지 않습니다. savePair 호출이 실패한 즉시 같은 JdbcTemplate으로 두 테이블을 조회합니다. 종료 시 정리 결과가 아니라 저장 함수 자체의 롤백 결과를 관찰하는 것이 핵심입니다.
정상 저장에서는 두 테이블 각각 한 행과 프로필 닉네임 합성회원을 확인합니다. 실패 저장에서는 먼저 다른 실행 계정을 정상 커밋하고 자기 계정의 두 번째 쓰기 전에 예외를 주입합니다. 자기 사용자가 남으면 사용자 INSERT가 취소되지 않은 것입니다. 모든 행이 없어지면 기존 커밋 데이터를 지운 것입니다. 자기 잔여 0과 다른 실행 두 행 보존을 각각 확인합니다.
starter 실패를 해석합니다
starter의 cleanup은 비어 있고 savePair는 트랜잭션 콜백이 빠져 있습니다. 따라서 순서 테스트에는 자기 이메일이 추가된 diff가 나오고 rollbackOutsideTestTransaction에는 예상 목록에 없는 mine 이메일이 보입니다. 둘은 데이터 잔여라는 증상은 같지만 원인이 다릅니다. 전자는 fixture 종료 정리 누락이고 후자는 부분 저장의 원자성 누락입니다. 증상만 보고 cleanup을 롤백 함수 안에 넣지 않습니다.
트랜잭션 실패를 보상 DELETE로 고치면 삭제 전에 앱이 종료되는 상황이나 연관 행이 추가되는 상황에서 원자성이 보장되지 않습니다. 이번 답안은 두 INSERT를 tx.executeWithoutResult 콜백 안에 둡니다. JDBC 작업이 같은 트랜잭션 관리자와 데이터 소스를 사용하는 제공 환경에서 실행됩니다. 다른 연결이나 외부 API까지 이 콜백으로 롤백된다고 일반화하지 않습니다.
실행 결과와 빌드 오류입니다
qa-transaction 압축을 푼 루트에서 ./mvnw test를 실행합니다. Java는 17, 부모 Spring Boot는 3.1.5입니다. 기존 API 검사도 보존되어 있으므로 IsolationTest만 통과하고 이전 계약 검사가 깨지면 완료가 아닙니다. surefire 보고서에서 Tests run과 Failures, Errors, Skipped를 확인합니다. 단언 실패는 기대·실제 차이를 읽고 환경 오류는 의존성과 런타임을 먼저 조사합니다.
오프라인 검증에서 의존성을 찾지 못하면 온라인 가능한 학습 환경에서 ./mvnw test로 캐시를 준비합니다. compilation failure는 TODO 편집 중 중괄호나 메서드 서명을 훼손했는지 확인합니다. 이 테스트는 웹 포트를 열지 않고 context를 AfterEach에서 닫습니다. 별도 서버를 백그라운드로 띄우지 않아 실행 후 남는 서버 프로세스가 없습니다. 운영 설정 파일도 읽지 않습니다.
독립성의 증거를 모읍니다
정방향과 역방향 결과가 같은 것은 그 두 순서의 관찰 증거입니다. seed 하나의 셔플 통과를 모든 가능한 순서 통과라고 보고하지 않습니다. 대상 테스트 수, 사례 이름, 실행 seed와 기준 SQL 집합을 적어 재검증을 지원합니다. 병렬 실행이나 실제 DB 격리 수준의 교착 상태는 이번 순차 검사와 다른 조건이므로 후속 회귀 항목으로 남깁니다.
사용자와 프로필 행 수만 검사하면 잘못된 이메일로 두 행을 저장한 결함을 놓칠 수 있습니다. 실패 검사는 정확한 다른 실행 이메일 목록의 보존을 비교하고 성공 검사는 자기 이메일의 nickname을 조회합니다. rollback 메시지의 users=1 profiles=1은 자기 실행 잔여가 아니라 먼저 커밋한 타 실행 데이터입니다. 숫자만 인용하지 않고 어떤 식별자 집합을 뜻하는지 함께 설명합니다.
미션 산출물을 이어 갑니다
qa-data-isolation-mission은 앞 미션의 모든 파일을 보존하고 isolation의 JavaScript fixture와 isolation-app의 Java 검사를 더합니다. 루트 check.sh는 앞 API 회귀 검사를 실행한 뒤 Node 정리와 Java 격리·롤백을 검증합니다. 학습자는 두 TODO 파일을 수정하며 테스트 조건을 완화하지 않습니다. 이미 존재하는 API 검증 함수와 원본 요구사항의 추적 관계도 유지합니다.
제출 설명에는 기존 members 대상 가입·중복·로그인의 순서별 결과와 새 iso 테이블의 커밋·롤백을 따로 적습니다. 준비 실패와 검증 실패 뒤 자기 잔여 0, 기준 계정 보존을 SQL 문장과 실제 단언으로 연결합니다. 웹 UI, 실제 TCP 전달, 파일 영속 DB의 장애 복구는 이 미션 결과만으로 확인할 수 없습니다. 격리 수준과 동시 실행의 이론 설명은 더 읽기의 트랜잭션 장에서 이어 갑니다.
따라하기
정순과 역순을 비교합니다
독립적으로 실행하여 결과를 비교합니다.
const ids=['signup','duplicate','login'];console.log(ids.join(' '));console.log([...ids].reverse().join(' '));실행 결과
signup duplicate login login duplicate signup
정리 범위를 구현합니다
IsolationSupport.cleanup의 TODO에 생성한 이메일별 매개변수 삭제를 넣습니다. 전체 삭제로 바꾸지 않습니다.
for (String email : owned) db.update("DELETE FROM members WHERE email=?", email);원자적 저장을 검증합니다
IsolationSupport.savePair의 두 INSERT를 tx.executeWithoutResult 콜백으로 묶습니다. qa-transaction 루트에서 실행하고 IsolationTest 4개의 실패·오류 0을 surefire 보고서에서 확인합니다. 기존 API 회귀 검사도 유지합니다.
./mvnw test확인 문제
실습
IsolationSupport.java의 cleanup과 savePair를 완성합니다. 소유 ID 삭제와 TransactionTemplate 콜백의 원자적 저장을 구현하고 기존 API 검사와 IsolationTest 4개를 유지합니다.
실행 명령
./mvnw test
기대 결과
IsolationTest 4개 및 기존 API 검사 실패·오류·skip 0
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 실행 순서에 따라 결과가 달라지는 테스트를 확인하는 방법을 설명해 주시면 됩니다.