라이프스타일

실전: 기존 프로젝트 유지보수

현황 기준을 만들고 한 가지 변경을 수행해 회귀 검사와 인계 기록을 남깁니다.

읽는 데 약 15분 · 실습 30 분

직접 제작한 흐름도이며 제품 화면이 아닙니다.
사진: Mokaair (© Mokaair)
전체 목차:Codex 학습 센터: 전체 튜토리얼 목차

고급 · Desktop / CLI / VS Code / JetBrains / cloud

이 글의 목차
  1. 목표와 시작점
  2. 1단계: 재작성 전에 기준 기록
  3. 2단계: 확인 가능한 변경 범위 정의
  4. 3단계: 먼저 실패하는 새 시험 추가
  5. 4단계: 구현하고 차이 확인
  6. 5단계: 화면·저장 데이터 회귀 확인
  7. 복원과 인계

목표와 시작점

이 단락의 학습 자료: 자료 · ·

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 계약을 따르며 임의 자료 정리기로 범위를 넓히지 않습니다.

maintenance.test.mjs · javascript
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);
});
모든 OS의 같은 회귀 명령 · sh
node --test core.test.mjs maintenance.test.mjs

4단계: 구현하고 차이 확인

범위를 제한한 리팩터링 요청 · text
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 연결 확인을 대신하지 않습니다.

core.mjs 참고 추가 함수 · javascript
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가 아닙니다.

app.js: 기존 core import 줄 교체 · javascript
import { countTasks, addTask, toggleTask, removeTask, visibleTasks, decodeTasks, encodeTasks } from "./core.mjs";
app.js: render 안의 기존 개수 대입 교체 · javascript
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 검증·복원 위치를 적고 미실행을 통과라 하지 않습니다. 다음 유지보수는 로 별도 범위를 정하며 저장 계층·프레임워크 교체를 끼워 넣지 않습니다. 확인 후 자신의 미리보기 터미널에서 Ctrl+C로 이번 서버를 중단하고 기준 JSON·검증 기록을 보존하세요.

직접 제작한 흐름도이며 제품 화면이 아닙니다.
직접 제작한 흐름도이며 제품 화면이 아닙니다. · 사진: Mokaair (© Mokaair)
자세한 설명 보기

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와 브라우저로 검증한 뒤 재시작·복원 인계 기록을 남깁니다.

  • 라이프스타일

    사용량과 효율: 재작업 줄이기

    조건, 모델 선택, 시간, 결과를 기록해 불필요한 재시도와 과도한 문맥을 줄입니다.

최신 여행 소식·가이드

출처

라이프스타일