익숙하지 않은 프로젝트를 Claude Code에 맡기자 "기록은 브라우저에 저장되며, 최근 100개 항목을 보관하고 새로고침 후에도 복원됩니다"라는 답을 받았다고 해 보겠습니다. README에 옮겨 적기에도 충분히 구체적으로 들립니다. 그래도 먼저 답변의 근거가 된 자료를 열어 확인해야 합니다.
이런 결론 하나를 살펴보겠습니다. 요구 사항을 질문으로 바꾸고, 짧은 코드 조각을 읽은 다음 실행할 때 확인해야 할 동작을 짚어 봅니다. 마지막에는 무엇이 작동하고 무엇을 더 확인해야 하는지 보여 주는 간단한 보고서가 완성됩니다.
프로젝트 전체 개요 대신 요구 사항 하나 확인하기
Haiku 50은 키워드로 세 줄짜리 시를 생성하는 작은 애플리케이션입니다. 사용자는 언어를 선택하고 시를 받은 뒤 생성 기록을 확인합니다. 여기서는 요구 사항 하나만 살펴보면 됩니다. 최근 생성한 시 100개를 브라우저에 저장하고 페이지를 새로고침한 뒤에도 확인할 수 있어야 합니다.

여기서 Haiku 50은 학습용 예시입니다. 코드와 에이전트의 답변은 분석을 위해 구성했으며, 기대 동작은 코드에서 추론합니다. 실제 프로젝트의 원본 아카이브를 확인하는 것은 아닙니다. 필요한 내용은 모두 이 글에 있으므로 애플리케이션을 다운로드하거나 API 키를 발급받고 시 생성을 실행할 필요는 없습니다.
"여기서 모든 것이 어떻게 작동하는지 설명해 줘"라고 하기보다 질문 세 가지를 던져 보겠습니다. 새로 생성한 시가 저장소에 기록되나요? 애플리케이션이 다음에 열릴 때 저장된 내용을 읽나요? 항목이 100개를 넘으면 어떻게 되나요?
Claude Code에 처음 요청할 내용은 다음과 같을 수 있습니다.
생성 기록만 조사해. 코드는 아직 수정하지 마.
새 시를 받은 뒤 저장하는 경로를 찾고,
페이지를 연 뒤 기록을 표시하는 경로도 찾아.
저장 항목 수가 어디에서 제한되는지 확인해.
각 결론마다 파일, 줄 번호, 짧은 코드 조각을 제시해.
실행해서 확인해야 할 내용은 별도로 나열해.이렇게 요청하면 조사 범위가 명확해집니다. 기록이 다른 파일과 연결되어 있다는 사실을 에이전트가 발견하면, 그 파일을 읽어야 하는 이유도 설명할 수 있습니다. 여러분도 애플리케이션 전체 요약을 검토하는 것보다 몇 군데 근거만 확인하는 편이 더 쉽습니다.
파일 참조도 직접 읽어 봐야 합니다
학습용 파일 history.js를 예로 들어 보겠습니다. 생성이 성공하면 인터페이스가 addToHistory(item)를 호출하고, renderHistory는 전달받은 목록을 표시하기만 합니다. 이 예시에는 기록을 처리하는 다른 함수가 없습니다.
const STORAGE_KEY = "haiku-history";
let history = [];
function addToHistory(item) {
history.unshift(item);
localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
renderHistory(history.slice(0, 100));
}
function startHistory() {
renderHistory(history);
}
startHistory();
이 코드를 읽으려면 두 저장 위치를 구분하면 됩니다. history 배열은 열린 페이지의 메모리에 있습니다. localStorage는 사이트 데이터를 브라우저에 저장해 다음 방문 때도 유지합니다. 애플리케이션이 데이터를 따로 여기에 기록하고 다시 읽어 와야 합니다. 저장소는 프로토콜, 호스트, 포트에 연결되어 있으므로 확인할 때 같은 주소와 브라우저 프로필을 사용해야 합니다. 자세한 내용은 localStorage 문서를 참고하십시오.
에이전트가 다음과 같이 답했다고 해 보겠습니다.
기록은 최근 생성 100개를 저장하고 새로고침 후에도 복원됩니다.
근거: history.js:4-13,
localStorage와 slice(0, 100)을 사용합니다.경로와 줄 번호가 제시됐습니다. 이제 그것들이 문장 전체를 뒷받침하는지 확인해 보겠습니다. 학습용 파일은 const STORAGE_KEY로 시작하며, 빈 줄도 줄 번호에 포함됩니다.
- 5번째 줄의
history.unshift(item)은 새 항목을 배열 맨 앞에 추가합니다. - 6번째 줄의
localStorage.setItem호출은 배열 전체를 저장소에 기록합니다. JSON 변환은 배열을 문자열로 저장하기 위해 필요합니다. - 7번째 줄의
renderHistory(history.slice(0, 100))은 처음 100개 항목을 화면에 전달합니다.slice는 메서드 문서에 설명된 것처럼 새 배열을 만들며 원본 배열을 줄이지 않습니다. - 시작할 때 2번째 줄의
let history = []가 빈 배열을 만들고, 10-13번째 줄의startHistory함수와 그 호출이 이 배열을 화면에 전달합니다. 여기서는 저장소에서 데이터를 읽지 않습니다.
코드를 읽고 나면 답변을 수정해야 합니다. 기록을 저장하고 화면에 최대 100개를 표시하는 코드는 있습니다. 하지만 이 구현은 시작할 때 기록을 복원하지 않으며 저장되는 항목 수를 제한하는 코드도 찾을 수 없습니다.
실제 프로젝트라면 이 코드 조각만으로는 부족할 수 있습니다. 데이터를 불러오는 코드가 다른 모듈에 있을 수도 있으니까요. 따라서 에이전트에게 "이 키를 읽고 쓰는 모든 위치와 해당 함수를 호출하는 곳을 보여 줘"라고 확인해 보십시오. 여기서는 학습 예시의 범위가 정해져 있으니 다음 단계로 넘어가도 됩니다.
새로고침 후 동작 확인하기
코드를 읽고 어디에서 차이를 찾아야 할지 알게 되었습니다. 이제 관찰 조건을 정해 보겠습니다. 일반 브라우저 프로필에서 같은 주소로 페이지를 열고, 저장을 허용하며, 기록은 비어 있는 상태입니다. 학습 시나리오에서는 알아보기 쉬운 라벨 A가 붙은 생성 결과 하나를 받습니다. 각 단계 사이에 코드는 바꾸지 않습니다.
아래는 코드에서 예상할 수 있는 시나리오입니다. 한 단계를 더해 새로고침한 뒤 새 항목 B를 받아 보겠습니다.
| 단계 | 화면에서 예상되는 내용 | 저장소의 haiku-history 키에서 예상되는 내용 |
|---|---|---|
| 기록이 비어 있는 상태로 페이지 열기 | 빈 목록 | 항목 없음 |
| 생성 결과 A 추가 | A 항목 하나 | A 항목이 든 배열 |
| 같은 페이지 새로고침 | 빈 목록 | A 항목이 든 배열은 남아 있음 |
| 새로고침한 뒤 생성 결과 B 추가 | B 항목만 표시 | B만 든 배열; A 항목은 덮어써짐 |
실제 동작을 관찰하려면 브라우저 개발자 도구에서 사이트 데이터 저장소를 열어 보면 됩니다. 해당 키의 값을 확인하고 방금 추가한 항목과 대조하십시오. 화면에 빈 목록만 보아서는 충분하지 않습니다.
"새로고침하니 전부 삭제됐다"고 하면 정확하지 않습니다. 데이터는 저장소에 남아 있지만 애플리케이션이 읽지 않은 것입니다. 이 구현에서는 저장된 문자열과 화면에 전달되는 배열 사이에서 흐름이 끊깁니다.
다음 항목을 추가하면 이 오류의 결과가 드러납니다. 새로고침 후 메모리의 배열은 비어 있으므로 B만 들어갑니다. 그러면 localStorage.setItem이 저장된 기록을 항목 하나짜리 배열로 덮어씁니다. 요구 사항대로라면 B와 A가 남아야 하지만, 코드대로라면 B만 남습니다. 기록 표시와 보존 모두에 문제가 있습니다.
코드에 근거한 결론은 다음과 같이 기록할 수 있습니다. "startHistory에서 저장된 기록을 읽지 않으므로, 다음에 항목을 추가하면 이전 기록을 덮어씁니다." 실행 결과까지 확인하려면 네 단계를 모두 진행하고 매 단계마다 화면의 목록과 저장소 내용을 대조해야 합니다.
100개 제한 확인하기
기록 복원 여부는 확인했습니다. 요구 사항의 나머지 부분은 최근 생성 결과 100개를 저장하는 것입니다. 항목 하나만으로는 이 한계를 확인할 수 없습니다.
기록이 비어 있는 별도 시나리오를 준비해 보겠습니다. 새로고침 없이 같은 추가 함수에 1부터 101까지 라벨을 붙인 기록 101개를 차례로 전달합니다. 기록 자체를 확인하기 위해 생성기를 101번 호출할 필요는 없습니다. 준비된 결과를 받은 뒤의 동작이 궁금한 것이니까요.
새 항목은 배열 맨 앞에 들어갑니다. 따라서 마지막으로 추가한 뒤 화면에는 101부터 2까지, 총 100개가 표시됩니다. 하지만 저장 코드에는 전체 배열이 전달되므로 저장소에는 101부터 1까지 총 101개가 남습니다. 개수와 항목 구성을 모두 확인해야 합니다. 그렇지 않으면 최근 항목이 아니라 가장 오래된 항목을 남기는 문제를 놓칠 수 있습니다.
에이전트의 답변이 지나치게 일반화된 부분이 바로 여기입니다. 코드에 100이라는 숫자가 있기는 하지만 표시할 항목 수에 적용됩니다. 코드에서 내릴 수 있는 정확한 결론은 다음과 같습니다. "인터페이스에는 최근 항목 100개가 표시되지만, 예시 시나리오에서 저장소에는 101개가 있으므로 기록 저장 수 요구 사항은 충족되지 않습니다."
준비된 기록을 사용하면 기록 기능만 따로 확인할 수 있습니다. 생성 서비스의 가용성, 시의 품질, 선택한 언어의 전달 여부는 알 수 없습니다. 이런 요구 사항은 각각 별도의 시나리오로 확인해야 합니다.
간단한 보고서 작성하기
조사 결과를 프로젝트 폴더에 저장해 두면 다음 날 대화를 다시 읽지 않아도 됩니다. 예시 파일 이름은 HANDOFF_REVIEW.md로 하겠습니다. 이름은 임의로 정한 것이고, 확인 과정을 다시 따라갈 수 있게 기록하는 것이 더 중요합니다.
학습용 코드를 읽고 작성한 보고서입니다. 예상 동작 항목을 보면 실행할 때 무엇을 확인해야 하는지 알 수 있습니다.
범위: 생성 기록, 이 글의 학습용 history.js 버전.
조사 방법: 학습용 코드 조각 읽기.
브라우저에서 실행하지 않음.
요구 사항: 최근 생성 100개를 브라우저에 저장하고
새로고침 후에도 표시하기.
코드 확인 결과:
- history.js:6, localStorage.setItem은 배열 전체를 기록함.
- history.js:7, renderHistory(history.slice(0, 100))는
화면 표시만 제한함.
- history.js:10-13, startHistory와 호출부는
저장된 내용을 읽지 않고 표시를 시작함.
코드에서 예상되는 동작:
- 항목 A를 추가하면 화면과 저장소에 나타남.
- 새로고침 후 A는 저장소에 남지만 화면 목록은 비어 있음.
- 새로고침 후 B를 추가하면 저장된 기록을 덮어씀.
B와 A가 아니라 B만 남음.
- 빈 상태에서 101개를 추가하는 별도 시나리오에서는
화면에 100개(101..2), 저장소에 101개(101..1)가 남음.
코드에서 확인한 차이: 시작할 때 기록을 복원하지 않으므로
다음 항목을 추가하면 기존 기록을 덮어씀.
저장 기록은 최근 100개로 제한되지 않음.
확인하지 않음: 생성기 동작, 저장 오류,
여러 탭에서 동시에 사용할 때의 동작.
다음 단계: 두 시나리오를 재현하고 관찰 결과를 기록하기.
그다음 시작 시 기록을 읽고 저장 배열의 크기를 제한하도록
수정한 뒤 같은 시나리오를 다시 확인하기.자신의 보고서에는 "학습용 버전" 대신 확인한 프로젝트 버전을 적으십시오. 예를 들어 커밋과 커밋되지 않은 변경 사항이 있는지 기록할 수 있습니다. 실행을 마친 뒤에는 "실제 관찰 결과" 항목을 추가하고 결과나 수동 작업 기록을 첨부하십시오. 예상 동작과 비교하고, 실행하지 못했다면 해당 항목은 채우지 말고 실행하지 못했다고 표시해 두십시오. 여기서는 필요한 자료가 모두 글에 있지만, 큰 프로젝트에서는 줄 번호만으로 확인 과정을 재현하기 어렵습니다.
이런 보고서가 있으면 에이전트에게 다음 작업을 맡기기도 수월합니다. "기록을 더 안정적으로 만들어 줘"라고 막연하게 말하는 대신 구체적인 차이 두 가지를 제시할 수 있습니다. 아직 어떤 결론을 내리기 이른지도 알 수 있고요.
결론을 직접 확인하십시오
같은 학습용 구현에 기록 삭제 버튼을 추가했습니다. 버튼의 이벤트 처리 함수는 다음과 같습니다.
function clearHistory() {
history = [];
renderHistory(history);
}버튼을 누르기 전에는 목록과 저장소에 A가 있었습니다. 누른 뒤 목록은 비었습니다. 에이전트는 "버튼이 저장된 기록을 완전히 삭제합니다"라고 답했습니다.
어떤 결론이 확인되었습니까? 화면에서 기록이 사라졌다는 것, localStorage에서 항목이 삭제됐다는 것, 아니면 둘 다입니까? 다음으로 무엇을 확인해야 합니까? 해설을 읽기 전에 먼저 답해 보십시오.
해설
화면 목록이 사라진 것은 확인됐습니다. 코드에서도 메모리의 배열을 비운 것을 알 수 있습니다. 하지만 이벤트 처리 함수는 localStorage를 수정하지 않고, 조건상 renderHistory는 목록을 표시하기만 하므로 저장된 A는 그대로 남습니다.
다음으로 버튼을 누른 직후 haiku-history 키의 값을 확인해 보십시오. 기록 복원 기능을 구현한 뒤에는 페이지를 새로고침해 삭제한 항목이 다시 나타나지 않는지도 확인하면 좋습니다. 원래 구현에서는 새로고침만으로 판단할 수 없습니다. 삭제하지 않아도 시작할 때 빈 목록을 표시하기 때문입니다. 이런 점은 확인을 헷갈리게 할 수 있습니다.
Claude Code에 이런 작업 요청하기
실제 프로젝트에서는 다음 결정을 좌우하는 주장 하나부터 확인하십시오. 예를 들어 기록을 그대로 사용할 수 있는지, 아니면 먼저 복원 기능을 고쳐야 하는지처럼요. 근거를 열어 결론을 쉽게 확인할 수 있도록 에이전트에게 답변 형식을 지정해 주십시오.
다음 주장을 확인해 줘: [애플리케이션의 구체적인 동작].
먼저 관련 파일을 찾고 필요한 부분을 읽어.
코드는 아직 수정하지 마.
다음 내용을 답해 줘:
1. 코드로 확인되는 내용: 파일, 줄 번호, 짧은 코드 조각.
2. 실행 동작을 확인할 시나리오.
3. 실제로 실행한 내용과 관찰한 결과.
4. 정확한 결론과 아직 모르는 점.
실행할 수 없다면 그 사실을 명확히 적어.
제안한 시나리오를 이미 실행한 확인으로 기록하지 마.답변을 받은 뒤에는 핵심 결론의 근거를 열고 관찰 결과를 요구 사항과 대조하십시오. 그다음에야 메모나 문서에 옮기면 됩니다. 근거가 부족하다면 다음 요청도 분명합니다. 기록을 읽는 부분을 찾고, 키 값을 확인한 다음, 항목 101개 시나리오를 다시 실행하면 됩니다. 이렇게 확인 과정을 작고 검증 가능한 단계로 이어 갈 수 있습니다.
함수 이름을 묻는 간단한 질문이라면 코드 참조만으로 충분합니다. 답변에 데이터 저장, 복원, 크기 제한이 포함된다면 관련 동작을 끝까지 따라가 확인하는 편이 좋습니다. 확인 범위는 여러분이 어떤 주장을 하려는지에 따라 정하면 됩니다.
GO TO FULL VERSION