explanatory-output-style 플러그인 2회차 · Claude Code · Opus 5.5 · 생각 깊이 중간 · 가상 카페 재고 코드 · 목록

explanatory-output-style 플러그인 2회차

클로드의 마지막 답변 (claude -p 화면에 찍히는 부분, 그대로)

`src/stock.mjs`에 `expiringSoon`과 `expired` 두 함수를 추가했고, `node test/stock.test.mjs`를 돌려서 기존 테스트와 새 테스트가 모두 통과했습니다. - **`expiringSoon(items, today)`**: 남은 일수가 0~3일인 재료, 즉 오늘부터 3일 뒤까지의 재료 이름을 돌려줍니다. - **`expired(items, today)`**: 남은 일수가 0보다 작은 재료, 즉 유통기한이 이미 지난 재료 이름을 돌려줍니다. - 두 함수 모두 기존 `daysBetween(today, it.expires)`로 남은 일수를 계산하고, 들어온 순서를 그대로 유지합니다. **추가한 테스트** (`test/stock.test.mjs`, 오늘을 2026-10-18로 가정): - 경계값: 오늘(10-18)과 3일 뒤(10-21)는 임박 목록에 들어가고, 4일 뒤(10-22)는 빠지는지 확인합니다. - 지난 재료: 어제(10-17)와 지난달(09-30) 날짜가 지난 목록에 들어가는지 확인합니다. - 순서: 결과가 들어온 순서대로 나오는지 확인합니다 (`['우유', '시럽']`, `['생크림', '버터']`). - 빈 배열: 입력이 비어 있으면 빈 배열을 돌려주는지 확인합니다. `★ Insight ─────────────────────────────────────` - 이런 날짜 범위 조건에서 버그가 가장 잘 나는 곳은 범위의 양 끝입니다. 그래서 3일째와 4일째 날짜를 둘 다 넣어 `<= 3`이 맞게 동작하는지 고정해 뒀습니다. 누가 나중에 `< 3`으로 바꾸면 테스트가 바로 실패합니다. - 월이 바뀌는 날짜(09-30)도 넣었습니다. `daysBetween`이 날짜를 숫자로 바꿔 빼기 때문에 월말 처리를 따로 할 필요가 없다는 것도 함께 확인됩니다. - 이 프로젝트에는 `package.json`이나 테스트 러너가 없습니다. `node:assert/strict`만 쓰는 스크립트라서 실패하면 예외가 나고 종료 코드가 0이 아니게 됩니다. 그래서 CI에 붙이더라도 `node test/stock.test.mjs` 한 줄이면 됩니다. `─────────────────────────────────────────────────`

바뀐 코드 (git diff)

diff --git a/src/stock.mjs b/src/stock.mjs
index f81b897..539f8a2 100644
--- a/src/stock.mjs
+++ b/src/stock.mjs
@@ -14,6 +14,19 @@ export function lowStock(items) {
   return items.filter((it) => it.qty < it.minQty).map((it) => it.name);
 }
 
+export function expiringSoon(items, today) {
+  return items
+    .filter((it) => {
+      const d = daysBetween(today, it.expires);
+      return d >= 0 && d <= 3;
+    })
+    .map((it) => it.name);
+}
+
+export function expired(items, today) {
+  return items.filter((it) => daysBetween(today, it.expires) < 0).map((it) => it.name);
+}
+
 export function orderList(items) {
   return items
     .filter((it) => it.qty < it.minQty)
diff --git a/test/stock.test.mjs b/test/stock.test.mjs
index 71de632..b61d6a6 100644
--- a/test/stock.test.mjs
+++ b/test/stock.test.mjs
@@ -1,5 +1,5 @@
 import assert from 'node:assert/strict';
-import { lowStock, orderList, daysBetween } from '../src/stock.mjs';
+import { lowStock, orderList, daysBetween, expiringSoon, expired } from '../src/stock.mjs';
 const items = [
   { name: '우유', qty: 3, unit: 'L', expires: '2026-10-20', minQty: 5 },
   { name: '원두', qty: 4, unit: 'kg', expires: '2027-01-10', minQty: 2 },
@@ -7,4 +7,17 @@ const items = [
 assert.deepEqual(lowStock(items), ['우유']);
 assert.deepEqual(orderList(items), [{ name: '우유', need: 7, unit: 'L' }]);
 assert.equal(daysBetween('2026-10-18', '2026-10-20'), 2);
+
+const dated = [
+  { name: '생크림', qty: 1, unit: 'L', expires: '2026-10-17', minQty: 1 }, // 어제 → 지남
+  { name: '우유', qty: 3, unit: 'L', expires: '2026-10-18', minQty: 5 }, // 오늘 → 임박
+  { name: '원두', qty: 4, unit: 'kg', expires: '2027-01-10', minQty: 2 }, // 한참 남음
+  { name: '시럽', qty: 2, unit: '병', expires: '2026-10-21', minQty: 1 }, // 3일 뒤 → 임박(경계)
+  { name: '치즈', qty: 1, unit: 'kg', expires: '2026-10-22', minQty: 1 }, // 4일 뒤 → 제외(경계)
+  { name: '버터', qty: 1, unit: 'kg', expires: '2026-09-30', minQty: 1 }, // 월 넘어 지남
+];
+assert.deepEqual(expiringSoon(dated, '2026-10-18'), ['우유', '시럽']);
+assert.deepEqual(expired(dated, '2026-10-18'), ['생크림', '버터']);
+assert.deepEqual(expiringSoon([], '2026-10-18'), []);
+assert.deepEqual(expired([], '2026-10-18'), []);
 console.log('기본 테스트 통과');