Skip to content

Commit c7fa485

Browse files
author
jammy
committed
Revamp Java lesson explanations and AI literacy file-set snapshot workflow
1 parent c71e31b commit c7fa485

179 files changed

Lines changed: 4993 additions & 732 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/backend/prisma/content/ai-literacy/curriculum.json

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,278 @@
2222
"description": "오래된 AI 예제 코드의 응답 필드 접근 오류를 재현하고 수정합니다.",
2323
"difficulty": "basic",
2424
"estimatedTime": 12
25+
},
26+
{
27+
"id": "ai-1-2",
28+
"order": 2,
29+
"title": "null/undefined 처리 누락 잡기",
30+
"description": "AI가 생략한 null 체크 때문에 발생하는 런타임 오류를 수정합니다.",
31+
"difficulty": "basic",
32+
"estimatedTime": 12
33+
},
34+
{
35+
"id": "ai-1-3",
36+
"order": 3,
37+
"title": "타입 착각으로 인한 비교 버그 잡기",
38+
"description": "문자열/숫자 타입 혼동으로 생긴 조건 분기 오류를 디버깅합니다.",
39+
"difficulty": "basic",
40+
"estimatedTime": 12
41+
},
42+
{
43+
"id": "ai-1-4",
44+
"order": 4,
45+
"title": "경계값(off-by-one) 오류 잡기",
46+
"description": "배열 인덱스 경계 조건 실수로 생긴 버그를 수정합니다.",
47+
"difficulty": "basic",
48+
"estimatedTime": 12
49+
},
50+
{
51+
"id": "ai-1-5",
52+
"order": 5,
53+
"title": "await 누락으로 인한 비동기 오류 잡기",
54+
"description": "Promise 처리 순서 문제를 재현하고 올바른 비동기 흐름으로 수정합니다.",
55+
"difficulty": "basic",
56+
"estimatedTime": 12
57+
},
58+
{
59+
"id": "ai-1-6",
60+
"order": 6,
61+
"title": "에러 메시지 오독 디버깅",
62+
"description": "로그 한 줄을 근거로 잘못된 원인 가정을 교정하는 훈련을 합니다.",
63+
"difficulty": "basic",
64+
"estimatedTime": 12
65+
}
66+
]
67+
},
68+
{
69+
"id": "ai-ch2",
70+
"order": 2,
71+
"title": "API Client Debug Lab",
72+
"description": "같은 파일셋에서 API 매핑/예외/재시도 버그를 연속적으로 추적합니다.",
73+
"part": "debugging",
74+
"partLabel": "디버깅 랩",
75+
"lessons": [
76+
{
77+
"id": "ai-2-1",
78+
"order": 1,
79+
"title": "증상 재현과 실패 로그 읽기",
80+
"description": "공통 코드셋의 첫 실패 케이스를 재현하고 핵심 로그를 추출합니다.",
81+
"difficulty": "intermediate",
82+
"estimatedTime": 15
83+
},
84+
{
85+
"id": "ai-2-2",
86+
"order": 2,
87+
"title": "매핑 로직 불일치 잡기",
88+
"description": "응답 변환 함수의 필드 매핑 오류를 추적하고 수정합니다.",
89+
"difficulty": "intermediate",
90+
"estimatedTime": 15
91+
},
92+
{
93+
"id": "ai-2-3",
94+
"order": 3,
95+
"title": "예외 누락으로 인한 연쇄 실패 차단",
96+
"description": "누락된 예외 처리 지점을 찾아 실패 전파를 막습니다.",
97+
"difficulty": "intermediate",
98+
"estimatedTime": 15
99+
},
100+
{
101+
"id": "ai-2-4",
102+
"order": 4,
103+
"title": "재시도 로직 버그 수정",
104+
"description": "잘못된 재시도 조건으로 발생한 중복 호출 문제를 고칩니다.",
105+
"difficulty": "intermediate",
106+
"estimatedTime": 15
107+
},
108+
{
109+
"id": "ai-2-5",
110+
"order": 5,
111+
"title": "패치 영향 범위 점검",
112+
"description": "수정이 다른 모듈에 미치는 부작용을 점검하고 보완합니다.",
113+
"difficulty": "intermediate",
114+
"estimatedTime": 15
115+
},
116+
{
117+
"id": "ai-2-6",
118+
"order": 6,
119+
"title": "회귀 테스트로 마무리",
120+
"description": "재발 방지를 위한 테스트를 추가해 디버깅 루프를 닫습니다.",
121+
"difficulty": "intermediate",
122+
"estimatedTime": 15
123+
}
124+
]
125+
},
126+
{
127+
"id": "ai-ch3",
128+
"order": 3,
129+
"title": "Async Workflow Debug Lab",
130+
"description": "같은 비동기 파일셋에서 상태 꼬임과 타이밍 이슈를 단계적으로 해결합니다.",
131+
"part": "debugging",
132+
"partLabel": "비동기 디버깅",
133+
"lessons": [
134+
{
135+
"id": "ai-3-1",
136+
"order": 1,
137+
"title": "비동기 상태 꼬임 재현",
138+
"description": "공통 워크플로우 코드에서 상태 불일치 증상을 재현합니다.",
139+
"difficulty": "intermediate",
140+
"estimatedTime": 16
141+
},
142+
{
143+
"id": "ai-3-2",
144+
"order": 2,
145+
"title": "중복 처리 버그 추적",
146+
"description": "중복 실행이 발생하는 분기 조건을 찾아 수정합니다.",
147+
"difficulty": "intermediate",
148+
"estimatedTime": 16
149+
},
150+
{
151+
"id": "ai-3-3",
152+
"order": 3,
153+
"title": "타임아웃 경계값 디버깅",
154+
"description": "경계 타이밍에서만 발생하는 실패를 관찰하고 패치합니다.",
155+
"difficulty": "intermediate",
156+
"estimatedTime": 16
157+
},
158+
{
159+
"id": "ai-3-4",
160+
"order": 4,
161+
"title": "idempotency 보장하기",
162+
"description": "재시도 상황에서도 동일 결과를 보장하도록 흐름을 고칩니다.",
163+
"difficulty": "intermediate",
164+
"estimatedTime": 16
165+
},
166+
{
167+
"id": "ai-3-5",
168+
"order": 5,
169+
"title": "관측 로그 개선",
170+
"description": "원인 분석 속도를 높이도록 로그 포인트와 메시지를 개선합니다.",
171+
"difficulty": "intermediate",
172+
"estimatedTime": 16
173+
},
174+
{
175+
"id": "ai-3-6",
176+
"order": 6,
177+
"title": "비동기 회귀 테스트 작성",
178+
"description": "패치 이후 동일 결함이 재발하지 않도록 검증 테스트를 추가합니다.",
179+
"difficulty": "intermediate",
180+
"estimatedTime": 16
181+
}
182+
]
183+
},
184+
{
185+
"id": "ai-ch4",
186+
"order": 4,
187+
"title": "Production Incident Lab",
188+
"description": "운영 장애 시나리오에서 복합 원인을 분리해 패치 우선순위를 세웁니다.",
189+
"part": "debugging",
190+
"partLabel": "운영 장애 대응",
191+
"lessons": [
192+
{
193+
"id": "ai-4-1",
194+
"order": 1,
195+
"title": "장애 타임라인 복원",
196+
"description": "로그/증상 데이터를 기준으로 장애 발생 순서를 복원합니다.",
197+
"difficulty": "advanced",
198+
"estimatedTime": 18
199+
},
200+
{
201+
"id": "ai-4-2",
202+
"order": 2,
203+
"title": "재시도 폭주 차단",
204+
"description": "AI가 제안한 재시도 로직의 폭주 조건을 찾아 안전장치를 넣습니다.",
205+
"difficulty": "advanced",
206+
"estimatedTime": 18
207+
},
208+
{
209+
"id": "ai-4-3",
210+
"order": 3,
211+
"title": "캐시 불일치 디버깅",
212+
"description": "캐시/원본 데이터 불일치로 인한 오류 경로를 추적합니다.",
213+
"difficulty": "advanced",
214+
"estimatedTime": 18
215+
},
216+
{
217+
"id": "ai-4-4",
218+
"order": 4,
219+
"title": "부분 실패 복구 설계",
220+
"description": "전체 실패를 피하도록 부분 실패 복구 경로를 도입합니다.",
221+
"difficulty": "advanced",
222+
"estimatedTime": 18
223+
},
224+
{
225+
"id": "ai-4-5",
226+
"order": 5,
227+
"title": "패치 롤백 기준 수립",
228+
"description": "배포 후 이상 징후에 대응할 롤백 기준과 지표를 정의합니다.",
229+
"difficulty": "advanced",
230+
"estimatedTime": 18
231+
},
232+
{
233+
"id": "ai-4-6",
234+
"order": 6,
235+
"title": "사후 분석 문서화",
236+
"description": "원인/대응/재발방지를 사후 분석 형식으로 정리합니다.",
237+
"difficulty": "advanced",
238+
"estimatedTime": 18
239+
}
240+
]
241+
},
242+
{
243+
"id": "ai-ch5",
244+
"order": 5,
245+
"title": "AI Patch Review Lab",
246+
"description": "AI 패치를 비판적으로 검토하고 반례/회귀 테스트로 품질을 보장합니다.",
247+
"part": "debugging",
248+
"partLabel": "패치 리뷰",
249+
"lessons": [
250+
{
251+
"id": "ai-5-1",
252+
"order": 1,
253+
"title": "패치 의도 파악",
254+
"description": "AI가 제안한 패치의 의도와 전제를 추출합니다.",
255+
"difficulty": "advanced",
256+
"estimatedTime": 18
257+
},
258+
{
259+
"id": "ai-5-2",
260+
"order": 2,
261+
"title": "반례 설계",
262+
"description": "패치가 깨질 수 있는 입력/조건 반례를 설계합니다.",
263+
"difficulty": "advanced",
264+
"estimatedTime": 18
265+
},
266+
{
267+
"id": "ai-5-3",
268+
"order": 3,
269+
"title": "누락 케이스 보완",
270+
"description": "패치가 놓친 경계 조건을 추가 수정으로 보완합니다.",
271+
"difficulty": "advanced",
272+
"estimatedTime": 18
273+
},
274+
{
275+
"id": "ai-5-4",
276+
"order": 4,
277+
"title": "회귀 테스트 강화",
278+
"description": "핵심 동작과 반례를 모두 커버하는 테스트 세트를 작성합니다.",
279+
"difficulty": "advanced",
280+
"estimatedTime": 18
281+
},
282+
{
283+
"id": "ai-5-5",
284+
"order": 5,
285+
"title": "코드 리뷰 피드백 반영",
286+
"description": "리뷰 코멘트를 반영해 패치 품질과 가독성을 높입니다.",
287+
"difficulty": "advanced",
288+
"estimatedTime": 18
289+
},
290+
{
291+
"id": "ai-5-6",
292+
"order": 6,
293+
"title": "최종 패치 승인 기준 점검",
294+
"description": "머지 전 체크리스트를 적용해 최종 승인 여부를 판단합니다.",
295+
"difficulty": "advanced",
296+
"estimatedTime": 18
25297
}
26298
]
27299
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# ch2-api-client-debug-lab
2+
3+
Shared file set for `ai-2-1` ~ `ai-2-6`.
4+
5+
## Goal
6+
Train practical debugging workflow in one evolving codebase:
7+
- reproduce failure
8+
- isolate cause
9+
- apply minimal patch
10+
- verify + add regression test
11+
12+
## Files
13+
- `src/apiClient.ts` - fetch wrapper and retry logic
14+
- `src/mapper.ts` - response mapping logic (intentional bug)
15+
- `tests/apiClient.test.ts` - regression test skeleton
16+
17+
## Versioning model
18+
- `base + patch chain` 방식으로 운영
19+
- 모든 레슨은 전체 파일 복사본 대신 스냅샷 참조 + 패치로 표현
20+
- 기준 메타: `manifest.json`
21+
22+
### Snapshot layout
23+
- `snapshots/base` : 챕터 시작 상태 (buggy)
24+
- `snapshots/ai-2-1-fixed` : ai-2-1 패치 적용 후 상태
25+
- `snapshots/ai-2-2-fixed` : legacy text fallback 보강
26+
- `snapshots/ai-2-3-fixed` : 누락 응답 fail-fast 예외 처리
27+
- `snapshots/ai-2-4-fixed` : 재시도 조건 수정(4xx 제외)
28+
- `snapshots/ai-2-5-fixed` : retries 입력 정규화
29+
- `snapshots/ai-2-6-fixed` : 회귀 테스트 확장 완료
30+
- `patches/ai-2-1.patch` ~ `patches/ai-2-6.patch` : 레슨별 최소 변경 기록
31+
32+
## Intentional issues (for lessons)
33+
1. outdated path access (`choices[0].text`)
34+
2. missing null guard
35+
3. over-broad retry condition
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"id": "ch2-api-client-debug-lab",
3+
"version": 1,
4+
"strategy": "base-plus-patch-chain",
5+
"root": "packages/backend/prisma/content/ai-literacy/file-sets/ch2-api-client-debug-lab",
6+
"files": [
7+
"src/apiClient.ts",
8+
"src/mapper.ts",
9+
"tests/apiClient.test.ts"
10+
],
11+
"entrypoints": {
12+
"repro": "tests/apiClient.test.ts",
13+
"verify": "tests/apiClient.test.ts"
14+
},
15+
"snapshots": [
16+
{
17+
"id": "base",
18+
"path": "snapshots/base",
19+
"description": "챕터 시작 상태 (의도적 버그 포함)"
20+
},
21+
{
22+
"id": "ai-2-1-fixed",
23+
"path": "snapshots/ai-2-1-fixed",
24+
"description": "mapper 필드 경로 버그 수정 완료 상태",
25+
"from": "base",
26+
"patch": "patches/ai-2-1.patch"
27+
},
28+
{
29+
"id": "ai-2-2-fixed",
30+
"path": "snapshots/ai-2-2-fixed",
31+
"description": "legacy text fallback 매핑 보강 상태",
32+
"from": "ai-2-1-fixed",
33+
"patch": "patches/ai-2-2.patch"
34+
},
35+
{
36+
"id": "ai-2-3-fixed",
37+
"path": "snapshots/ai-2-3-fixed",
38+
"description": "누락 응답 fail-fast 예외 처리 상태",
39+
"from": "ai-2-2-fixed",
40+
"patch": "patches/ai-2-3.patch"
41+
},
42+
{
43+
"id": "ai-2-4-fixed",
44+
"path": "snapshots/ai-2-4-fixed",
45+
"description": "재시도 조건(4xx 제외, transient만 재시도) 수정 상태",
46+
"from": "ai-2-3-fixed",
47+
"patch": "patches/ai-2-4.patch"
48+
},
49+
{
50+
"id": "ai-2-5-fixed",
51+
"path": "snapshots/ai-2-5-fixed",
52+
"description": "retries 정규화로 패치 영향 범위 안정화 상태",
53+
"from": "ai-2-4-fixed",
54+
"patch": "patches/ai-2-5.patch"
55+
},
56+
{
57+
"id": "ai-2-6-fixed",
58+
"path": "snapshots/ai-2-6-fixed",
59+
"description": "회귀 테스트 스위트 확장 완료 상태",
60+
"from": "ai-2-5-fixed",
61+
"patch": "patches/ai-2-6.patch"
62+
}
63+
]
64+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--- a/src/mapper.ts
2+
+++ b/src/mapper.ts
3+
@@
4+
export function mapAssistantText(response: ChatApiResponse): string {
5+
- return response.choices![0].text!;
6+
+ return response.choices?.[0]?.message?.content ?? '';
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--- a/src/mapper.ts
2+
+++ b/src/mapper.ts
3+
@@
4+
export function mapAssistantText(response: ChatApiResponse): string {
5+
- return response.choices?.[0]?.message?.content ?? '';
6+
+ const first = response.choices?.[0];
7+
+ return first?.message?.content ?? first?.text ?? '';
8+
}

0 commit comments

Comments
 (0)