재현 입력과 실행 조건
70분 안팎
학습 목표
실패 fixture로 JDK·명령·입력·기대 및 실제 결과를 모은 재현 기록을 작성합니다.
개념
재현 자료가 수정의 기준입니다
신입이 AI에게 오류를 고쳐 달라고만 요청하면 모델은 자신이 상상한 경로를 수정할 수 있습니다. 이번 할 일 앱은 요청이 성공했는데 목록 순서가 달라지는 문제입니다. 서버가 중단되지 않아도 명세를 어기면 실패입니다. 시니어는 먼저 같은 문제를 다른 사람이 다시 볼 수 있는 자료를 요구합니다. 사례 ID ORDER-01을 붙이고 환경·입력·기대·실제를 나누면 수정 전후를 같은 약속으로 비교할 수 있습니다. 이번 목표는 원인을 단정하는 일이 아니라 재실행 가능한 실패 보고를 만드는 일입니다.
한 번만 준비하는 모듈 환경
브라우저 실습은 Python 표준 입력으로 JSON 배열 하나를 받습니다. 로컬 실습은 JDK 17·Spring Boot 3.1.5와 제공 Maven Wrapper를 사용합니다. starter와 solution을 별도 폴더에 풀고 pom.xml 위치에서 ./mvnw test를 실행합니다. 의존성 캐시를 준비한 환경에서는 ./mvnw -o -q test로 확인합니다. 관찰용 코드는 solution에서 읽고 수정 과제는 starter에서 수행합니다. AI 계정 없이 제공 결함 fixture로 수행할 수 있으며 운영 서버나 개인 데이터는 필요하지 않습니다.
출발점과 결함을 구별합니다
이전 모듈은 생성·조회·완료 API와 상태 전이 테스트를 갖췄습니다. 이번 starter는 그 solution을 이어받고 TaskRepository.list에 제목순 정렬을 넣은 교육용 결함입니다. 원래 명세는 생성 순서, 이 앱에서는 증가하는 ID 순서로 조회합니다. Z를 먼저 만들고 A를 나중에 만들면 기대 ID는 [1, 2]입니다. 실제 [2, 1]은 제목 정렬과 일치하는 관찰이지만 이 시점에는 가설로만 적습니다. 제목을 사전순으로 보여 달라는 새 요구로 해석하지 않습니다.
환경은 실행 조건으로 적습니다
환경 칸에는 JDK의 실제 버전과 Maven Wrapper 사용 여부, Spring Boot 버전, 작업 폴더, 테스트 명령을 적습니다. Java 17이라는 주요 버전 외에 실제 패치 버전은 java -version으로 확인해 개인 실행 기록에 남깁니다. 제공 자료는 jdkMajor를 17로 검사하며 각자의 패치 문자열을 정답으로 강제하지 않습니다. 운영 경로나 사용자 홈의 실명은 합성 경로로 대체합니다. 실행 파일을 찾지 못한 상황과 테스트가 실행되어 결과가 다른 상황을 구분할 수 있을 정도의 조건을 남깁니다.
입력은 순서와 초기 상태까지 포함합니다
재현 절차는 빈 TaskService를 만들고 Z, A를 차례로 add한 다음 list를 호출하는 것입니다. 이미 항목이 있는 서비스에서 시작하면 ID와 기대값이 달라집니다. 입력을 두 제목이라고만 적으면 A를 먼저 넣어 우연히 통과할 수 있습니다. 초기 상태는 빈 저장소이고 완료 호출은 없다는 점도 적습니다. API 장애 보고라면 HTTP 경로와 메서드를 추가하지만 이번 최소 관찰은 서비스 호출로 제한합니다. 토큰을 붙인 실제 요청을 그대로 AI에게 전달할 필요가 없습니다.
기대값의 출처를 적습니다
expected에는 [1, 2]를 쓰고 생성 순서 보존이라는 spec.md의 약속을 근거로 연결합니다. before에는 직접 관찰한 [2, 1]을 씁니다. 두 배열을 같은 칸에 적거나 둘 다 결과라고 부르면 검토자가 어느 쪽이 요구인지 알기 어렵습니다. 실패 메시지에서 expected는 테스트가 정한 답이며 but was는 코드가 반환한 값입니다. 테스트 기대도 잘못될 수 있으므로 명세와 대조한 이유를 함께 적습니다. 실제 결과를 기대 칸에 복사해 테스트를 통과시키는 방식은 사용하지 않습니다.
AssertionError를 읽는 순서
JUnit 실패는 테스트 이름과 비교 메시지, 호출 위치를 함께 읽습니다. ORDER01_sameInput은 사례 ID와 같은 문제를 가리킵니다. expected [1, 2]와 but was [2, 1]에서 개수는 같고 순서만 다르다는 점을 먼저 찾습니다. IllegalArgumentException이나 컴파일 오류가 나오면 이 순서 assertion까지 도달했는지 확인합니다. 업무 예외와 테스트 비교 실패를 혼동하면 재현이 확인되지 않은 채 원인을 조사하게 됩니다. target/surefire-reports의 XML은 tests·failures·errors를 별도로 남깁니다.
실행 실패도 유형이 있습니다
./mvnw의 실행 권한 오류는 테스트 결과가 아닙니다. ZIP을 푼 뒤 실행 권한이 없다면 chmod +x mvnw로 복구합니다. 오프라인 의존성 오류는 캐시 준비 문제이며 Java 소스를 고쳐 해결할 일이 아닙니다. package를 찾지 못한다는 컴파일 오류는 assertion 실패와 다릅니다. 로컬 Maven 실행에서 테스트 보고서가 생겼는지 확인한 뒤 기능 결함으로 분류합니다. 오류 원문을 자연스러운 문장으로 바꾸기보다 필요한 부분을 보존하고 어떤 값만 가렸는지 기록합니다.
공유할 자료를 줄입니다
AI에게 제공할 묶음은 사례 ID, 합성 입력, 명세 한 문장, 관련 메서드, 테스트 이름, 오류 원문, 실행 조건입니다. Authorization 헤더와 개인 제목은 제외합니다. 실제 제목의 문자 순서가 원인에 필요하다면 Z와 A처럼 관계를 보존하는 합성 데이터로 다시 실행합니다. 값을 가린 결과가 여전히 재현되는지 확인해야 합니다. 마스킹했으니 안전하다는 선언 대신 수집하지 않은 항목과 바꾼 항목을 redaction에 씁니다. 전체 저장소나 운영 설정을 붙이지 않습니다.
요청은 조사와 수정을 나눕니다
첫 요청에는 관찰 자료를 주고 제목순 정렬 가설을 확인할 위치와 반증 입력을 설명해 달라고 적습니다. 아직 파일을 바꾸는 단계가 아니므로 변경 범위도 분명히 합니다. 실제 AI를 사용했다면 답변의 주장과 직접 확인한 사항을 따로 기록하고, fixture만 사용했다면 그렇게 적습니다. AI가 원인이 확실하다고 말해도 테스트나 코드 관찰이 추가되기 전에는 가설입니다. 조사 결과를 받은 뒤 허용 경로와 보호 테스트를 제시하여 한 변경만 요청할 수 있습니다.
실습 제출물의 의미
failures.json의 TODO 상태를 관찰한 사실로 채우고 해당 테스트를 다시 실행합니다. 제공 JUnit 검사는 사례 ID와 테스트 연결, 기대·수정 전 배열, 환경 주요 버전, 필요한 문자열을 검사합니다. 문장에 무엇이든 채우면 구조는 통과할 수 있으므로 사람이 근거를 읽는 검토도 필요합니다. starter는 제공 결함 때문에 일부 assertion이 실패합니다. 재현 자료를 적었다고 앱이 수정된 것은 아니며 이번에는 자료 수집을 먼저 끝내고 후속 레슨에서 최소화와 가설 검증을 이어갑니다.
미확인 항목을 보존합니다
이 실습의 서비스 호출과 기존 standalone MockMvc 테스트는 실제 HTTP 소켓이나 운영 설정을 검사하지 않습니다. failures.json의 unverified에 그 범위를 적습니다. 보고서의 verified는 실행한 교육 사례와 구조 검사의 상태이며 운영 승인 의미가 아닙니다. 전부 정상이라는 문장보다 어떤 입력을 어느 명령으로 비교했는지 설명하는 기록이 다음 담당자에게 유용합니다. 더 읽기의 디버깅 장에서는 다른 도메인의 재현과 중단 기준을 살펴보고 여기서는 할 일 조회 사례의 자료만 완성합니다.
따라하기
기대와 관찰을 분리합니다
아래 코드를 그대로 실행해 관찰 값을 비교합니다.
expected = [1, 2]
actual = [2, 1]
print("expected:", expected)
print("actual:", actual)
print("same:", expected == actual)실행 결과
expected: [1, 2] actual: [2, 1] same: False
공유 자료를 제한합니다
아래 코드를 그대로 실행해 관찰 값을 비교합니다.
packet = {"caseId": "ORDER-01", "input": ["Z", "A"]}
print(sorted(packet))
print("Authorization" in packet)실행 결과
['caseId', 'input'] False
실제 재현 테스트를 실행합니다
starter의 pom.xml 폴더에서 실행합니다. assertion의 expected와 but was를 failures.json에 옮깁니다. Java 버전은 java -version으로 확인합니다. 환경마다 달라지는 전체 로그 대신 직접 관찰한 값을 기록합니다.
./mvnw test -Dtest=ReproductionTest#ORDER01_sameInput확인 문제
실습
README의 재현 절차로 환경·입력·기대·실제를 관찰하고 failures.json을 채웁니다. 이번 제출은 기록이며 앱 수정은 후속 레슨에서 이어갑니다.
실행 명령
./mvnw test
기대 결과
starter는 조회 순서 assertion과 미완성 기록 검사 일부 실패, solution은 전체 테스트 실패·오류·건너뜀 0.
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 생성 코드의 오류를 AI에 다시 전달하는 방법을 설명해 주시면 됩니다.