라이프스타일
실전: 기존 프로젝트 유지보수
현황 기준을 만들고 한 가지 변경을 수행해 회귀 검사와 인계 기록을 남깁니다.
읽는 데 약 15분 · 실습 30 분

이 글의 목차
Codex 학습 목차로 돌아가기Codex 학습 센터: 전체 튜토리얼 목차설치와 첫 작업부터 MD 지침과 고급 연동까지 60개 강의, 열 개 단원을 계획합니다. 수준, 환경, 목표, 명령으로 다음 글을 찾고 미게시 항목의 상태를 확인할 수 있습니다.전체 글 읽기
목표와 시작점
이 단락의 학습 자료: 자료 · 코드 지도기존 코드베이스 이해읽기 흐름으로 진입점, 데이터 흐름, 테스트를 찾아 파일 근거가 있는 프로젝트 지도를 만듭니다.전체 글 읽기 · Git 복원Git, 브랜치, diff와 복원Git은 파일 이력, 브랜치는 변경 묶음, diff는 차이를 관리합니다. 대화를 재개한다고 파일이 복원되지는 않습니다.전체 글 읽기
1단계: 재작성 전에 기준 기록
maintenance-lab의 index.html·style.css·app.js·core.mjs·core.test.mjs 다섯 파일을 확인하고 node --test core.test.mjs의 세 개 통과와 Node 버전·날짜·폴더를 기록합니다. 다르면 start·broken을 복사했는지 먼저 확인하며 기존 실패를 이번 리팩터링 탓으로 돌리지 않습니다. 로컬 Git 기준 커밋이나 전체 baseline 복사본을 저장한 뒤 변경해 복원 지점을 확보하세요.
수정 전 화면 기준도 만드세요. 이 폴더에서 아래 화면 회귀 절의 OS별 미리보기 명령을 사용하고 실습 전용 브라우저 프로필과 출처 URL을 유지합니다. Show에서 All tasks를 선택하고 기존 데이터가 없는지 확인하세요. 기존 데이터가 있다면 먼저 보존하고 지우는 대신 다른 새 실습 프로필에서 빈 상태로 시작합니다. Read·Build를 추가하고 Read를 완료해 1 active / 2 total을 확인합니다. 브라우저 개발자 도구의 Application/Storage → Local Storage에서 mokaair-codex-todo-v1의 가상 JSON을 저장해 두 ID와 완료 상태를 기록합니다. 수정 후 비교까지 두 항목·URL·프로필을 유지하세요. 데스크톱 앱에서 maintenance-lab을 열어 작업을 만들거나 이 폴더의 별도 터미널에서 codex를 실행한 뒤 다음 요청을 제출합니다.
Codex에 app.js의 #count 갱신을 읽기만 하게 하고 전체인지 필터 결과인지 설명하게 합니다. 기준은 Completed에서도 전체 active/total입니다. 저장 키 mokaair-codex-todo-v1·version 1·ID·completed 불리언도 확인하세요. 집계 책임만 옮기며 데이터 형식·마이그레이션은 바꾸지 않습니다. 먼저 읽으면 비슷한 코드를 합치다 세부 동작이 달라지는 문제를 막습니다.
2단계: 확인 가능한 변경 범위 정의
| 항목 | 요청 변경 | 불변 조건 |
|---|---|---|
| core.mjs | 순수 countTasks(tasks) 추가 | 입력 수정·DOM·저장 없음 |
| app.js | #count에 함수 사용 | 같은 문구·전체 개수 |
| maintenance.test.mjs | 집계·불변성 시험 | 원래 core.test.mjs 유지 |
| HTML/CSS | 변경 불필요 | 조작·배치·초점 유지 |
| 저장 자료 | 마이그레이션 없음 | key·version·ID·상태 유지 |
작은 범위도 검증이 필요하며 실패를 소수 변경과 연결하기 쉽게 합니다.
3단계: 먼저 실패하는 새 시험 추가
아래 maintenance.test.mjs를 기존 시험 옆에 저장하고 구현 전 둘 다 실행합니다. 함수가 없어 새 세 개는 실패하고 원래 세 개는 통과합니다. 누락을 감지하는 증거로 예상 실패를 보존하며 자료 불량으로 보거나 시험을 지워 초록색을 만들지 않습니다. 입력은 기존 Task 계약을 따르며 임의 자료 정리기로 범위를 넓히지 않습니다.
import test from 'node:test';
import assert from 'node:assert/strict';
import * as core from './core.mjs';
test('empty list counts are zero', () => {
assert.deepEqual(core.countTasks([]), { active: 0, total: 0 });
});
test('count all tasks without deduplicating equal titles', () => {
const tasks = [
{ id: 'a', title: 'Read', completed: false },
{ id: 'b', title: 'Read', completed: true },
{ id: 'c', title: 'Build', completed: false },
];
assert.deepEqual(core.countTasks(tasks), { active: 2, total: 3 });
});
test('counting preserves frozen task data and storage compatibility', () => {
const task = Object.freeze({ id: 'a', title: 'Read', completed: true });
const tasks = Object.freeze([task]);
const before = core.encodeTasks(tasks);
assert.deepEqual(core.countTasks(tasks), { active: 0, total: 1 });
assert.equal(core.encodeTasks(tasks), before);
assert.deepEqual(core.decodeTasks(before), tasks);
});
node --test core.test.mjs maintenance.test.mjs
4단계: 구현하고 차이 확인
Add countTasks(tasks) to core.mjs, returning {active, total} for the full list.
Use it in app.js when updating #count; keep the existing visible text.
Preserve storage format, key, IDs, task behavior and original tests.
Do not edit index.html, style.css or the new test expectations.
Run node --test core.test.mjs maintenance.test.mjs.
Report changed files, test results and remaining browser verification.
완료 후 여섯 시험이 통과해야 합니다. 아래 참고 함수를 app.js에서 import하고 render의 tasks를 집계해 기존 문구를 만듭니다. 필터 결과 shown을 넘기면 Completed의 전체 수가 틀리므로 확인하세요. git diff나 편집기 차이에서 원래 시험·HTML·CSS·저장 동작이 그대로인지 봅니다. 순수 함수 시험 통과는 UI 연결 확인을 대신하지 않습니다.
export function countTasks(tasks) {
return {
active: tasks.filter((task) => !task.completed).length,
total: tasks.length,
};
}
app.js의 기존 import에 countTasks를 추가하고 원래 여섯 함수는 남깁니다. render의 #count.textContent 대입 줄만 두 번째 부분으로 바꾸세요. 앞의 shown 필터를 포함한 다른 render 코드는 유지합니다. 특정 위치의 일부이며 전체 app.js가 아닙니다.
import { countTasks, addTask, toggleTask, removeTask, visibleTasks, decodeTasks, encodeTasks } from "./core.mjs";
const counts = countTasks(tasks);
document.querySelector("#count").textContent = `${counts.active} active / ${counts.total} total`;
인수가 tasks인지 확인하세요. Read 완료·Build 미완료일 때 Completed의 shown은 한 항목입니다. shown을 전달하면 올바른 1 active / 2 total 대신 0 active / 1 total이 나옵니다. 여섯 핵심 테스트는 함수 계약을 검사하므로 여전히 통과할 수 있어 별도의 연결·화면 확인이 필요합니다.
5단계: 화면·저장 데이터 회귀 확인
수정 전의 같은 실습 서버가 실행 중이면 두 번째 서버를 시작하지 말고 해당 URL을 새로고침하세요. 멈춘 경우에만 다음 명령을 사용합니다. 같은 폴더에서 Windows는 py -3 -m http.server 4173 --bind 127.0.0.1, macOS/Linux는 python3 -m http.server 4173 --bind 127.0.0.1을 쓰고 같은 http://127.0.0.1:4173을 엽니다. 사용 중이면 중단 전에 기존 서비스를 확인하세요. 전후에 같은 origin·가상 할 일을 써 포트 변경의 빈 localStorage를 데이터 손실로 오인하지 않습니다. 수정 전 Read·Build를 초기화하거나 다시 추가하지 말고 저장한 ID·완료 상태를 기준과 비교한 뒤 All tasks·Active·Completed 모두 1 active / 2 total인지 확인합니다.
새로고침으로 두 항목·ID·완료 상태 보존을 확인합니다. 같은 두 항목으로 먼저 390px와 데스크톱 폭 모두에서 필터·집계를 확인합니다. 그 뒤 All tasks를 선택해 Read를 한 번만 삭제하고 1 active / 1 total 및 Tab의 보이는 초점을 검증합니다. 회귀 확인이므로 새 디자인은 필요 없습니다. 필터에 따라 수가 바뀌면 app.js 인수, 함수가 틀리면 새 시험 실패로 조사하세요. 실제 관찰한 후에만 브라우저 통과를 기록하고 미조작 OS는 구분합니다.
복원과 인계
되돌릴 때 현재 차이를 저장하고 이번 core.mjs·app.js만 복원하며 새 maintenance.test.mjs는 별도 보관합니다. 원래 세 시험·집계 화면으로 기준 복귀를 확인하고 전체 강제 초기화로 다른 사람 수정을 지우지 않습니다. 인계에 기준·추출 책임·불변 계약·여섯 시험·실제 UI 검증·복원 위치를 적고 미실행을 통과라 하지 않습니다. 다음 유지보수는 맥락 인계맥락과 작업 인계긴 작업에는 결정과 증거를 남깁니다. README는 사용법, 설계 문서는 이유, 인계는 진행 상황, AGENTS.md는 지속할 규칙으로 구분합니다.전체 글 읽기로 별도 범위를 정하며 저장 계층·프레임워크 교체를 끼워 넣지 않습니다. 확인 후 자신의 미리보기 터미널에서 Ctrl+C로 이번 서버를 중단하고 기준 JSON·검증 기록을 보존하세요.
Codex 학습 목차로 돌아가기Codex 학습 센터: 전체 튜토리얼 목차설치와 첫 작업부터 MD 지침과 고급 연동까지 60개 강의, 열 개 단원을 계획합니다. 수준, 환경, 목표, 명령으로 다음 글을 찾고 미게시 항목의 상태를 확인할 수 있습니다.전체 글 읽기
자세한 설명 보기
Three numbered stages: identify the starting point, perform the exercise, and verify the result. Original illustration, not a product screenshot.
같은 주제의 글
라이프스타일
Codex 학습 센터: 전체 튜토리얼 목차
설치와 첫 작업부터 MD 지침과 고급 연동까지 60개 강의, 열 개 단원을 계획합니다. 수준, 환경, 목표, 명령으로 다음 글을 찾고 미게시 항목의 상태를 확인할 수 있습니다.
라이프스타일
Worktree와 작업 격리
Worktree는 하나의 Git 저장소에 다른 브랜치의 작업 폴더를 만듭니다. 파일이 분리되어도 DB, 포트와 외부 서비스는 공유될 수 있습니다.
라이프스타일
실습: 작은 웹사이트 만들기
brief.md에서 Small Steps 할 일 사이트를 계획하고 추가·완료·삭제·필터·로컬 저장을 구현합니다. HTML·CSS·데이터 함수·화면 이벤트·시험을 분리하고 Node와 브라우저로 검증한 뒤 재시작·복원 인계 기록을 남깁니다.
라이프스타일
사용량과 효율: 재작업 줄이기
조건, 모델 선택, 시간, 결과를 기록해 불필요한 재시도와 과도한 문맥을 줄입니다.
이 글을 인용한 글
최신 여행 소식·가이드

가이드도쿄
도쿄 어디에 묵을까? 신주쿠·우에노·도쿄역·시부야·아사쿠사·이케부쿠로·긴자 일곱 지역 비교: 공항 교통, 숙박세, 짐 배송까지
도쿄 어디에 묵을까? 신주쿠, 우에노, 도쿄역, 시부야, 아사쿠사, 이케부쿠로, 긴자 일곱 지역을 같은 기준으로 비교한다. 나리타·하네다 공항에서 오는 방법, 교통 노선, 주변의 볼거리, 동네 분위기, 적합한 여행자를 비교표와 야마노테선 안내도로 살펴보고, 2026년 9월에 확인한 도쿄도 숙박세(2027년 4월부터 3%)와 공항 택배로 짐을 보내는 규정도 정리했다.
- 예산
- 호텔

가이드도쿄
도쿄 교통패스 선택법: Suica/Welcome Suica, Tokyo Subway Ticket, JR Pass는 살 만할까?
도쿄를 처음 여행한다면 먼저 1인당 IC 카드 한 장으로 탈 때마다 결제한다(Welcome Suica는 보증금이 없고 28일간 유효). 하루에 지하철을 4번 이상 타면 2,000엔짜리 Tokyo Subway Ticket 72시간권을 추가하고, 간사이에 가지 않고 도쿄만 여행한다면 JR Pass는 반드시 손해다. TOURIST PASMO, iPhone의 Suica, 도쿄 Metro 하루권의 이용 가능·불가 범위를 결정도로 비교한다. 가격은 2026년 9월 확인.
- 교통
- 예산

가이드도쿄
도쿄 디즈니랜드·디즈니씨 가이드: 티켓 가격, 판타지 스프링스 Fantasy Springs, 디즈니 프리미어 액세스 DPA와 스탠바이 패스 이용법, 첫 방문에는 어느 파크가 좋을까
도쿄 디즈니 하루짜리 패스포트는 변동 가격제로, 2026년 9월에는 평일 대부분이 9,900엔, 주말이 10,900엔이다. 공식 홈페이지에서 매일 14:00에 두 달 뒤 같은 날짜의 티켓을 판매한다. 무료 프라이오리티 패스는 공식 서비스 목록에서 빠져 대기 시간을 줄이는 방법은 유료 디즈니 프리미어 액세스(한 사람당 한 번 1,000~3,500엔)뿐이다. 운영 시간, 25주년 행사, 스탠바이 패스, 엔트리 리퀘스트, 판타지 스프링스 이용법, 첫 방문 때 디즈니랜드와 디즈니씨 중 어디를 고를지도 담았다. 2026년 9월 공식 홈페이지에서 확인했다.
- 추천 일정
- 가족 여행
출처
- Codex prompting · 확인일:
- Git worktree guidance · 확인일: