부록 B. 셀프 체크 정답과 해설
1장
1-1. (나)에 완료 기준이 있습니다. 알림을 끈 다음 날 메일이 오는지, 새로고침 뒤 상태가 남는지를 누구나 확인할 수 있기 때문입니다. (가)의 '쓰기 편하게'는 확인 방법이 없습니다. 예를 들어 "알림 종류마다 켜기·끄기 스위치가 있고, 바꾸면 저장 버튼 없이 바로 반영되며, 새로고침해도 유지된다"처럼 관찰할 수 있는 결과로 바꿉니다.
1-2. 빈 상태(예약 내역이 없으면 안내 문구와 예약하러 가기 버튼이 보인다), 불러오는 중(로딩 표시가 나오고 버튼은 눌리지 않는다), 실패(다시 시도 버튼이 있는 오류 안내가 보인다), 권한 없음(로그인 화면으로 갔다가 로그인 뒤 내역 화면으로 돌아온다)입니다. 상태마다 관찰할 수 있는 결과가 적혀 있으면 정답입니다.
1-3. 예시: ① 손님이 문의 폼을 제출하면 "접수되었습니다"가 뜨고 관리자 목록에 한 건이 생긴다. ② 관리자가 문의를 열어 '확인함'으로 바꾸면 목록에 표시가 바뀐다. ③ 접수되면 손님에게 안내 메일이 한 통 나간다(테스트에서는 발송 기록으로 확인). 작업마다 사용자가 쓸 수 있는 결과가 나오면 됩니다. 표, API, 화면 순으로 나눴다면 층별로 자른 것이니 다시 나눕니다.
1-4. Ctrl+G로 계획을 텍스트 편집기에서 열어 직접 고친 뒤 진행시킵니다. 계획 없이 바로 맡겨도 되는 작업은 디버깅용 로그 한 줄 추가처럼 diff를 한 문장으로 요약할 수 있는 일입니다.
1-5. ③은 어느 요구와도 짝지어지지 않고 앱 전체를 건드리는 범위 밖 정리입니다(질문 1·2·5). 또 검증 단계가 없습니다(질문 4). "3단계는 빼라. 4단계 앞에 신청 저장을 확인하는 테스트 추가와 npm test 실행, 화면 캡처 단계를 넣어라"처럼 단계 번호와 이유를 들어 돌려줍니다.
1-6. Claude Code는 작업 폴더나 그 위에 CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md 중 하나라도 있으면 기본적으로 AGENTS.md 대신 그것을 읽습니다. CLAUDE.local.md도 여기에 들어가므로 그 팀원의 세션에서 팀 규칙이 빠졌습니다. 루트에 @AGENTS.md를 가져오는 CLAUDE.md를 두거나, 그 팀원이 개인 설정을 두 파일을 함께 읽는 값(claude-md-and-agents-md)으로 바꿉니다.
1-7. Codex는 ~/.codex/config.toml의 project_doc_fallback_filenames에 TEAM_GUIDE.md를 넣습니다. 폴더마다 AGENTS.override.md, AGENTS.md 다음으로 이 이름을 찾습니다. Gemini CLI는 settings.json의 context.fileName에 TEAM_GUIDE.md를 넣습니다(이름 하나나 목록).
2장
2-1. 5173번 포트를 이미 다른 프로세스가 쓰고 있다는 뜻입니다. 흔히 전에 띄운 개발 서버가 살아 있습니다. lsof -i :5173으로 PID를 확인해 kill <PID>로 그 프로세스만 끄거나 다른 포트로 띄웁니다. 이름 패턴으로 프로세스를 한꺼번에 끄는 방법은 관계없는 프로그램까지 끌 수 있어 피합니다. 의존성 재설치는 대개 소용이 없습니다.
2-2. 실행된 테스트가 하나도 없으니 아무것도 확인되지 않았습니다. '실패 없음'과 '검증됨'은 다릅니다. 테스트 파일의 위치나 이름 규칙, 테스트 설정이 깨졌거나 필터 때문에 선택된 테스트가 없을 가능성을 먼저 의심하고, 실행된 테스트 수를 확인합니다.
2-3. 콘솔에서는 클릭할 때 자바스크립트 오류가 나는지, 네트워크 탭에서는 요청이 나갔는지와 그 상태 코드를 봅니다. 콘솔에 오류가 있거나 요청이 아예 없으면 화면 코드, 400번대면 보낸 내용이나 권한, 500번대면 서버 쪽 문제이므로 서버 출력과 로그를 봅니다.
2-4. src/checkout/summary.ts의 47번째 줄입니다. 스택 트레이스에서 내 코드 중 가장 위에 있는 줄이 오류가 실제로 난 곳이고, OrderPanel은 그 함수를 부른 곳, node_modules는 라이브러리입니다. null인 대상의 price를 읽었으니 주문 항목이 null로 들어오는 경우를 살핍니다.
2-5. 종료 코드를 확인합니다. 명령 직후 echo $?가 0이면 성공입니다. 경고는 실패가 아니고, 오류 문구가 없다고 성공인 것도 아닙니다. CI도 종료 코드로 성공과 실패를 판단합니다.
2-6. 고친 코드를 잠시 되돌리거나 버그를 다시 넣은 뒤 그 테스트를 돌려 실패하는지 봅니다. 실패하면 테스트가 버그를 잡는 것이고, 통과하면 버그와 관계없는 테스트입니다. 확인 뒤에는 코드를 원래대로 돌립니다.
2-7. Linux는 파일 이름의 대소문자를 구분하고, macOS의 기본 APFS 형식은 구분하지 않습니다. 맥에서는 ./components/header가 Header.tsx를 찾았지만 Linux에서는 찾지 못합니다. import 경로를 실제 파일 이름대로 ./components/Header로 고칩니다.
3장
3-1. git diff는 작업 트리와 스테이징 영역을 비교해 아직 스테이징하지 않은 변경을, git diff --staged는 스테이징 영역과 마지막 커밋을 비교해 다음 커밋에 들어갈 변경을, git diff HEAD는 작업 트리와 마지막 커밋을 비교합니다. 두 가지를 한 번에 보려면 git diff HEAD를 씁니다. 추적하지 않는 새 파일은 어느 쪽에도 나오지 않습니다.
3-2. 새 파일은 Git이 아직 추적하지 않는 상태라 git diff에 나오지 않습니다. git status에서 ??로 표시되는지 확인하고, git add로 스테이징한 뒤 git diff --staged로 내용을 봅니다.
3-3. git diff -w로 공백 차이를 무시하면 진짜 변경만 남습니다. 커밋은 기능 변경과 서식 변경을 나눕니다. git add -p로 기능 헌크만 골라 먼저 커밋하고, 서식 변경은 따로 커밋하거나 되돌립니다.
3-4. -m으로 기준이 될 부모 번호(보통 main 쪽인 1)를 지정합니다. 머지 커밋은 부모가 둘 이상이라 어느 쪽 기준으로 되돌릴지 알려 줘야 하기 때문입니다. Git 문서는 머지를 되돌리면 그 병합으로 들어온 변경을 앞으로 원하지 않는다는 선언이 되어, 나중에 같은 브랜치를 다시 병합해도 이미 들어왔던 커밋의 변경은 다시 들어오지 않는다고 경고합니다.
3-5. git stash apply입니다. apply는 변경을 적용하고 stash 목록에 남겨 두므로 다른 브랜치에도 다시 적용할 수 있습니다. pop은 적용에 성공하면 목록에서 지웁니다. 다 쓴 뒤에는 git stash drop으로 정리합니다.
3-6. git reset --keep HEAD~2입니다. 커밋은 버리면서 커밋하지 않은 수정은 남깁니다. 지금 HEAD와 목표 지점 사이에서 내용이 다른 파일에 커밋하지 않은 수정이 있으면 덮어쓰지 않고 reset을 중단합니다.
3-7. 125입니다. Git 문서에 따르면 종료 코드 125는 현재 커밋을 테스트할 수 없다는 뜻이라 그 커밋을 건너뜁니다. 0은 정상, 125를 뺀 1~127은 비정상이고, 그 밖의 값은 bisect를 중단시킵니다.
4장
4-1. 실행되지 않습니다. Claude Code는 deny → ask → allow 순서로 규칙을 평가하고 처음 맞는 규칙이 결과를 정합니다. 맞는 deny 규칙이 있으면 더 넓은 allow 규칙이 있어도 막히며, allow로 deny의 예외를 만들 수 없습니다.
4-2. 아닙니다. 공식 문서는 .claudeignore가 아무 효과가 없다고 밝히고, 그 내용을 Read(./secrets/**) 같은 Read deny 규칙으로 옮기라고 안내합니다. 셸에서 도는 다른 프로그램까지 막아야 한다면 샌드박스의 읽기 금지도 함께 씁니다.
4-3. NEXT_PUBLIC_ 변수의 값은 next build 때 브라우저로 가는 코드에 박혀 고정됩니다. 또 Vercel에서 환경 변수 변경은 새 배포에만 반영됩니다. 다시 빌드해 새로 배포해야 새 값이 보입니다.
4-4. 맞지 않습니다. Claude Code 샌드박스의 기본값은 쓰기를 작업 폴더와 임시 폴더로, 네트워크를 허용 목록으로 제한하지만, 읽기는 ~/.ssh와 클라우드 자격 증명 파일을 포함해 컴퓨터 대부분을 허용합니다. 민감한 경로를 샌드박스 읽기 금지로 막고, 에이전트의 파일 도구는 Read deny 규칙으로 막습니다.
4-5. 사용자 계정의 푸시 보호는 기본으로 켜져 있고, 공개 저장소로 가는 푸시에 비밀값이 있으면 막습니다. 저장소 단위의 푸시 보호는 기본으로 꺼져 있어 관리자가 켜야 하며 GitHub Secret Protection이 필요합니다.
4-6. 거르지 않습니다. npm 문서에 따르면 --audit-level은 보고 내용을 걸러 내는 것이 아니라, 몇 단계 이상의 취약점이 있을 때 명령을 0이 아닌 종료 코드로 끝낼지 정하는 기준입니다. high 이상이 있으면 CI가 실패하게 됩니다.
4-7. 예시: (가) 오타 수정은 작업 폴더 안 문서 편집만 허용하고, 폴더 밖과 네트워크는 막으며, 편집 자동 승인은 괜찮습니다. (나) 조사는 읽기 전용(plan mode나 read-only)으로 하고, 네트워크는 패키지 레지스트리와 공식 문서만 열며, 설치는 금지합니다. (다) 버그 수정은 작업 폴더 쓰기와 테스트 명령을 허용하고, 폴더 밖과 불필요한 네트워크는 막으며, 의존성 추가와 푸시는 사람이 승인합니다. 작업마다 필요한 최소한만 열고 이유를 댈 수 있으면 정답입니다.
5장
5-1. 프로덕션입니다. Vercel은 새 프로젝트의 첫 배포를 어느 브랜치에서 하든, --prod가 없어도 항상 프로덕션 배포로 만듭니다. 그 뒤로는 프로덕션 브랜치의 커밋이나 vercel --prod가 프로덕션을, 다른 브랜치와 PR, --prod 없는 vercel이 미리보기를 만듭니다.
5-2. 브랜치 URL입니다. 그 브랜치의 최신 배포를 계속 가리킵니다. 커밋 URL은 특정 커밋의 배포에 고정되어 있으므로, 두 시점을 비교하거나 "이 버전에서 문제가 났다"고 기록할 때 씁니다.
5-3. 적용되지 않습니다. 롤백된 배포는 당시의 설정으로 돌고, 환경 변수 변경은 새 배포에만 반영됩니다. 새 배포를 만들어 승격하면 새 값이 반영되고 롤백 상태도 풀립니다.
5-4. Hobby 플랜은 바로 이전 배포로만 돌아갈 수 있습니다. Pro와 Enterprise는 프로덕션 도메인에 연결된 적 있는 배포 어디로든 롤백할 수 있습니다. 프로덕션에 연결된 적 없는 미리보기 배포는 어느 플랜에서도 대상이 아닙니다.
5-5. vercel logs는 기본적으로 최근 30분의 최신 100개 항목을 보여 줍니다. --since 3h처럼 범위를 넓힙니다. 그래도 없다면 플랜의 로그 보관 기간이 지났을 수 있습니다.
5-6. Production 환경의 Branch Tracking에서 Auto-assign Custom Production Domains를 끕니다. 프로덕션 브랜치에서 배포하면 도메인 연결 없이 승격을 기다리므로, 생성된 배포 URL에서 확인한 뒤 승격합니다. 승격은 다시 빌드하지 않고 도메인만 옮깁니다. 이 배포는 운영 환경 변수를 쓰므로 운영 데이터에 닿는다는 점에 주의합니다.
5-7. 예시(꽃꽂이 수업 예약 앱): ① 테스트, 타입 검사, 빌드 통과 ② 미리보기에서 수업 신청과 신청 취소 흐름 직접 확인 ③ 새로 쓰는 문자 발송 키가 Production에 있음 ④ 수강생 표 구조 변경 없음(있다면 이전 코드와 호환 확인) ⑤ 결제 웹훅이 운영 주소와 운영 키를 가리킴 ⑥ 직전 정상 배포와 롤백 방법 확인. 줄마다 실제 기능 이름이 있고 확인 여부를 참·거짓으로 가릴 수 있으면 정답입니다.