플러그인 없이 2회차 · 요청 1: 함수 두 개, 규칙을 다 정해 준 요청 · Claude Code · Opus 5.5 · 생각 깊이 중간 · 목록

플러그인 없이 2회차

요청 1: 함수 두 개, 규칙을 다 정해 준 요청

요청문: src/stock.mjs에 두 함수를 추가해 줘. expiringSoon(items, today)는 유통기한이 오늘부터 3일 뒤까지(오늘 포함)인 재료 이름 목록을, expired(items, today)는 유통기한이 이미 지난 재료 이름 목록을 돌려줘. today는 'YYYY-MM-DD' 문자열이야. 순서는 들어온 순서 그대로. test/stock.test.mjs에 테스트도 추가하고 돌려 봐.

클로드의 마지막 답변 (그대로)

`src/stock.mjs`에 `expiringSoon`과 `expired`를 추가했고, 테스트도 넣어서 돌려 보니 모두 통과했어요. ``` 기본 테스트 통과 유통기한 테스트 통과 ``` - **`expiringSoon(items, today)`**: 남은 일수가 0일 이상 3일 이하인 재료 이름을 돌려줘요. 오늘 끝나는 재료와 정확히 3일 뒤에 끝나는 재료도 들어가요. - **`expired(items, today)`**: 남은 일수가 0보다 작은 재료 이름을 돌려줘요. 그래서 유통기한이 오늘인 재료는 '임박'으로만 잡히고 '지남'에는 들어가지 않아요. - 남은 일수는 파일에 원래 있던 `daysBetween`으로 계산해요. 날짜를 UTC 기준으로 비교해서 실행하는 곳의 시간대에 따라 결과가 바뀌지 않아요. - 둘 다 `filter` → `map` 순서라 결과는 들어온 순서 그대로예요. `test/stock.test.mjs`에 추가한 테스트는 오늘을 2026-10-18로 두고 다음 경우를 확인해요. - 유통기한이 오늘인 것, 1일 뒤, 정확히 3일 뒤인 것(포함되는지) - 4일 뒤인 것(빠지는지) - 이미 지난 것 - 10월 30일에서 11월로 넘어가는 경우 - 빈 목록

바뀐 코드 (git diff)

diff --git a/src/stock.mjs b/src/stock.mjs
index f81b897..77aaa20 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 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);
+}
diff --git a/test/stock.test.mjs b/test/stock.test.mjs
index 71de632..a59e7f6 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,23 @@ 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('기본 테스트 통과');
+
+// 유통기한: 오늘=2026-10-18, 임박 범위는 10-18 ~ 10-21 (경계 포함)
+const fridge = [
+  { name: '생크림', qty: 1, unit: 'L', expires: '2026-10-21', minQty: 1 }, // +3일, 임박(경계)
+  { name: '버터', qty: 1, unit: 'kg', expires: '2026-10-17', minQty: 1 }, // -1일, 지남
+  { name: '우유', qty: 3, unit: 'L', expires: '2026-10-18', minQty: 5 }, // 오늘, 임박
+  { name: '시럽', qty: 2, unit: 'L', expires: '2026-10-22', minQty: 1 }, // +4일, 해당 없음
+  { name: '치즈', qty: 1, unit: 'kg', expires: '2026-09-30', minQty: 1 }, // 지남
+  { name: '딸기', qty: 1, unit: 'kg', expires: '2026-10-19', minQty: 1 }, // +1일, 임박
+];
+assert.deepEqual(expiringSoon(fridge, '2026-10-18'), ['생크림', '우유', '딸기']);
+assert.deepEqual(expired(fridge, '2026-10-18'), ['버터', '치즈']);
+// 월 경계를 넘는 경우
+assert.deepEqual(
+  expiringSoon([{ name: 'a', expires: '2026-11-02' }, { name: 'b', expires: '2026-11-03' }], '2026-10-30'),
+  ['a'],
+);
+assert.deepEqual(expiringSoon([], '2026-10-18'), []);
+assert.deepEqual(expired([], '2026-10-18'), []);
+console.log('유통기한 테스트 통과');