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

플러그인 없이 2회차

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

`src/stock.mjs`에 두 함수를 추가했고, `node test/stock.test.mjs`로 돌린 기존 테스트와 새 테스트가 모두 통과했습니다. **추가한 함수** - `expiringSoon(items, today)`: 오늘부터 남은 날짜가 0~3일인 재료 이름을 들어온 순서대로 돌려줍니다. 오늘이 기한인 재료와 정확히 3일 뒤가 기한인 재료도 들어갑니다. - `expired(items, today)`: 남은 날짜가 0보다 작은, 즉 기한이 지난 재료 이름을 돌려줍니다. - 날짜 계산은 파일에 원래 있던 `daysBetween`을 그대로 썼습니다. UTC 기준으로 계산하기 때문에 시간대나 서머타임에 따라 결과가 하루씩 밀리지 않습니다. **추가한 테스트** (`test/stock.test.mjs`, 기준일 2026-10-18) - 어제, 오늘, 내일, 3일 뒤, 4일 뒤, 지난달이 기한인 재료를 섞어 넣고 결과와 순서를 확인했습니다. 결과는 `['생크림', '우유', '케이크']`와 `['딸기', '버터']`입니다. - 빈 배열을 넣는 경우를 확인했습니다. - 연말에서 연초로 넘어가는 경우(12/30→1/2, 12/31→1/1)를 확인했습니다. `data.json`에 오늘(2026-10-18) 날짜로 넣어 보면 임박 재료는 `우유, 생크림, 바닐라 시럽, 치즈케이크`이고, 기한이 지난 재료는 `딸기`입니다.

바뀐 코드 (git diff)

diff --git a/src/stock.mjs b/src/stock.mjs
index f81b897..0d1b19f 100644
--- a/src/stock.mjs
+++ b/src/stock.mjs
@@ -19,3 +19,16 @@ export function orderList(items) {
     .filter((it) => it.qty < it.minQty)
     .map((it) => ({ name: it.name, need: it.minQty * 2 - it.qty, unit: it.unit }));
 }
+
+export function expiringSoon(items, today) {
+  return items
+    .filter((it) => {
+      const left = daysBetween(today, it.expires);
+      return left >= 0 && left <= 3;
+    })
+    .map((it) => it.name);
+}
+
+export function expired(items, today) {
+  return items.filter((it) => daysBetween(today, it.expires) < 0).map((it) => it.name);
+}
diff --git a/test/stock.test.mjs b/test/stock.test.mjs
index 71de632..69700a0 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 },
@@ -8,3 +8,21 @@ assert.deepEqual(lowStock(items), ['우유']);
 assert.deepEqual(orderList(items), [{ name: '우유', need: 7, unit: 'L' }]);
 assert.equal(daysBetween('2026-10-18', '2026-10-20'), 2);
 console.log('기본 테스트 통과');
+
+const today = '2026-10-18';
+const dated = [
+  { name: '딸기', qty: 1, unit: 'kg', expires: '2026-10-17', minQty: 1 }, // 어제 (지남)
+  { name: '생크림', qty: 2, unit: '팩', expires: '2026-10-18', minQty: 2 }, // 오늘
+  { name: '우유', qty: 3, unit: 'L', expires: '2026-10-21', minQty: 5 }, // 3일 뒤 (경계)
+  { name: '시럽', qty: 1, unit: '병', expires: '2026-10-22', minQty: 1 }, // 4일 뒤
+  { name: '케이크', qty: 0, unit: '판', expires: '2026-10-19', minQty: 1 }, // 내일
+  { name: '버터', qty: 1, unit: '개', expires: '2026-09-30', minQty: 1 }, // 월 넘어 지남
+];
+assert.deepEqual(expiringSoon(dated, today), ['생크림', '우유', '케이크']);
+assert.deepEqual(expired(dated, today), ['딸기', '버터']);
+assert.deepEqual(expiringSoon([], today), []);
+assert.deepEqual(expired([], today), []);
+// 월·연 경계
+assert.deepEqual(expiringSoon([{ name: 'A', expires: '2027-01-02' }], '2026-12-30'), ['A']);
+assert.deepEqual(expired([{ name: 'B', expires: '2026-12-31' }], '2027-01-01'), ['B']);
+console.log('유통기한 테스트 통과');