5주차부터 수습생에게 줄 실전 티켓 34개예요(기본 20 + 고도화 점검 추가 14). 각 티켓에 🎯 우리 건 — 여러분이 매일 쓰는 이 학습 플랫폼(mirim-app)의 실제 코드에서 찾아 둔 구체적인 일감이 붙어 있어요. 여러분이 고치면 이 플랫폼이 정말로 좋아집니다. 파일 경로까지 적어 뒀으니, 배정받으면 바로 코드를 열어 보세요.
주지 말 것: 운영 DB 마이그레이션 · 인증/권한 로직 · 결제 · 배포 설정 · 고객사 SLA가 걸린 긴급 건 · "리팩터링 알아서" 같은 범위 무한 티켓.
.map() 돌리는 목록 중 length가 0일 때 분기가 없는 곳이 후보.frontend/src/pages/CodingPage.jsx에 FE-04로 언어·난이도 필터가 생기면 "조건에 맞는 문제 0건"이라는 새 상태가 태어난다. 0건일 때 "조건에 맞는 문제가 없어요" 안내 + [필터 초기화] 버튼을 보여줄 것. FE-04 담당자와 둘이 짝으로 진행 — 남의 코드 위에 얹는 연습.grep -rn "불러오는 중" frontend/src로 직접 세어 보기). components/Loading.jsx를 만들어 카드 모양 스켈레톤으로 통일하고, 우선 대시보드(DashboardPage.jsx)와 학습 문서(DocsPage.jsx) 2곳만 교체. 나머지는 후속 티켓.frontend/src/pages/ChangePasswordPage.jsx — 지금은 새 비밀번호를 현재 것과 똑같이 넣어도 통과된다(바꾼 게 아닌데 바꿨다고 안내됨). 프론트 validate에 "현재와 다른 비밀번호를 써 주세요" 추가 + 백엔드 AuthService.changePassword에도 같은 검사(프론트는 우회 가능 — 서버가 최종 방어선이라는 걸 몸으로 익히는 티켓).frontend/src/pages/CodingPage.jsx — 문제 25개(JS 12·SQL 5·Java 8)가 한 줄로 길게만 나온다. 언어(전체/JS/SQL/Java)와 난이도(쉬움/보통/어려움) 필터 칩을 추가. useState 2개와 .filter()면 충분 — 새 API 불필요. 퀴즈 페이지의 탭 UI(tabs 클래스)를 참고. 완료되면 FE-01(0건 빈 상태)로 이어진다.frontend/src/api/client.js의 401 인터셉터가 /login으로 보낼 때 아무 설명이 없다 — 학생 입장에선 "쓰다가 갑자기 로그인 화면"이다. 인터셉터에서 /login?expired=1로 보내고, LoginPage.jsx가 쿼리스트링(useSearchParams)을 읽어 "세션이 만료됐어요. 다시 로그인해 주세요"를 폼 위에 표시.global.css의 .topnav-menu)가 "코딩 문…"처럼 잘리는데, 스크롤바까지 숨겨져 있어(::-webkit-scrollbar) 더 있다는 표시가 전혀 없다. 오른쪽 가장자리 그라데이션 페이드(mask-image 또는 ::after)로 "더 있음"을 암시할 것. CSS만으로 해결 — JS 불필요.hero compact 블록(eyebrow + 제목 + 설명)이 7개 페이지에 복붙되어 있다. components/PageHero.jsx로 추출(eyebrow·title·children props 설계)하고 2~3개 페이지부터 적용. "언제 컴포넌트로 뽑는가(3번 반복되면)"와 props 설계를 연습하는 티켓.CodingController의 ProblemSummary record에는 attempts가 없다(상세 ProblemDetail에는 있음). 목록 응답에 추가하고, 프론트 CodingPage.jsx 목록에 "3번째 도전 중" 배지 표시. record 필드 추가 → 서비스 → 화면까지 세로로 관통하는 첫 티켓으로 적당.CodingController.SubmitRequest의 code 필드에 길이 제한이 없다 — 수 MB를 보내도 DB가 그대로 받는다. @Size(max = 20000)(약 500줄) + 컨트롤러 @Valid 확인 + 프론트 초과 시 안내. "받을 수 있는 것"과 "받아도 되는 것"은 다르다는 검증 원칙 티켓.@Valid 실패 시 응답 message가 "Validation failed for object='loginRequest'…" 영어 원문이다(기본기 감사에서 발견). @RestControllerAdvice + MethodArgumentNotValidException 핸들러를 만들어 첫 번째 필드 에러의 한국어 메시지(DTO에 이미 다 적어 둠)를 {"message": "..."}로 내려주기. 전역 예외 처리 입문 티켓.MentorController)에는 전체 제출 최신순(GET /api/mentor/submissions)만 있고 학생별로 모아보기가 없다. GET /api/mentor/students/{userId}/submissions 신규 작성(단순 R) + MentorPage.jsx에서 학생 이름 클릭 시 필터. hasRole("MENTOR") 권한이 어떻게 걸리는지(SecurityConfig) 함께 확인.LoginAttemptService의 5회/5분이 static final 상수로 박혀 있다. security.login-lock.max-failures·lock-minutes를 application.yml에 ${ENV:기본값} 패턴으로 추출(@Value 주입) — 컨테이너 재빌드 없이 정책을 조정할 수 있게. 기존 테스트(LoginAttemptServiceTest)가 깨지지 않게 유지하는 것까지가 완료 조건.MentorController·CodingService 주석에 "학생 4~5명이라 괜찮다(N+1)"고 적어 둔 지점이 있다(grep -rn "N+1" backend/src). SQL 로그를 켜고(logging.level...SQL: DEBUG) 멘토 화면을 열어 쿼리가 몇 번 나가는지 직접 센 뒤, 학생 100명 가정으로 IN 절/JOIN FETCH로 줄이기. 측정→개선→재측정 수치를 PR에 첨부.frontend/src/pages/DocViewerPage.jsx — notFound가 한 번 true가 되면 되돌리는 코드가 없다. 지금은 문서 간 직행 링크가 없어 안 터질 뿐(전수 감사에서 "결함 실재, 현재 도달 불가"로 판정된 건). 재현 경로를 직접 구성(없는 slug 접속 → 정상 문서로 이동)해 버그를 드러내고, slug 변경 시 상태 리셋으로 수정. "도달 불가한 결함은 언제 고치는가"를 토론해 보는 티켓.backend/src/test/.../service/ 목록과 대조). ProgressServiceTest 패턴(Mockito + 한국어 @DisplayName) 그대로 — 재제출 시 상태가 SUBMITTED로 돌아오는지, 없는 과제 404, 빈 내용 400 등 분기마다 1개. 전체 테스트가 25개+로 늘어나는 걸 확인.README.md에 텔레그램 알림·로그인 잠금·내 정보·주소찾기 등 최근 기능이 하나도 없다(grep 0건). README만 보고 처음부터 로컬 실행을 따라 해 보고, 막히는 지점(환경변수·포트·시드 계정)을 전부 고쳐 쓰기. "문서는 새 팀원이 검증한다" — 여러분이 그 새 팀원이다.npm run lint 결과를 기준으로 frontend/src/pages 디렉터리의 미사용 import·변수만 정리. 범위를 벗어난 "김에 수정"은 금지 — 정리 PR은 작아야 리뷰가 된다는 걸 배우는 티켓. lint 경고 개수 before/after를 PR 설명에 기록.QuizPage.jsx 채점 후) — 틀린 문제를 다시 보는 흐름을 동료 2명이 쓰는 걸 관찰하고(어디서 머뭇거리나), 개선안 1장(before/after 스케치)을 멘토에게 제안 → 승인되면 개발 티켓으로 전환. "관찰 → 제안 → 반영"의 UX 사이클 한 바퀴.global.css의 버튼(btn·btn-primary·btn-ghost)·배지(badge-*)·칩·카드 변형을 화면 캡처로 전수 수집해 피그마 정리표로. 색·간격·글자 크기 토큰까지 뽑으면 이 플랫폼의 미니 디자인 시스템 v0.1이 된다. DZ-01·FE-07과 자연스럽게 연결.depends_on을 condition: service_healthy로 올린다.docker ps에 (healthy) 표시, 일부러 hang 상황을 만들어 재기동되는지 확인..gitea/workflows/ci.yml — push마다 백엔드 mvn test + 프론트 npm run build, deploy/CI.md 참고). 이 티켓은 그 위에 얹는 확장이다.deploy/CI.md로 러너 구조를 이해한다.npm test 단계로 추가, (3) Maven·npm 캐시로 실행 시간 단축, (4) main 브랜치 보호(체크 통과해야 merge)./api/mentor/students→401, (2) STUDENT 세션→403, (3) MENTOR→통과, (4) /api/auth/login·signup→permitAll 도달.@WebMvcTest + spring-security-test로 위 5가지 단언, 전부 초록.log.info로 남긴다. 세션 Authentication에서 행위자를 얻는다.POST /api/auth/signup과 PUT /api/profile/me에 분당 상한을 건다./api/mentor/students(전체 인적사항)와 /export.csv에 접근 한 줄(사용자·행위·시각) 로그를 남긴다. SEC-02와 짝.mvn versions:display-dependency-updates(또는 OWASP dependency-check) 1회, frontend는 npm audit를 돌려 결과를 읽고 STUDY.md에 정리한다.frontend/src/lib/runSql.js의 순수함수 gradeSql 단위테스트를 작성한다.seed/quiz/ 폴더(코스별 71개 파일)를 제거하거나, 최소한 "실사용은 quizzes.json"이라는 안내를 남겨 단일 출처로 정리한다.SeedDataLoader가 seed/quizzes.json(단일 355문항)만 읽는다. quiz/ 폴더는 어디서도 참조 안 됨(grep 0건) — 고쳐도 앱에 반영 안 되는 함정.LearnHubPage에 loading 가드를 추가해, fetch 도착 전 순간적으로 "0% · 모든 코스 미완료"가 보였다 갱신되는 깜빡임을 없앤다.위 패턴에서 찾은 실제 건을 이 양식으로 옮기면 수습생에게 바로 줄 수 있는 티켓이 됩니다. 이슈 트래커에 그대로 복붙해도 돼요.
[제목] (패턴ID) 화면/기능 — 한 줄 요약 예: (FE-01) 알림 목록 — 빈 상태 화면 추가 [배경] 왜 필요한가 (1~2문장) [할 일] 무엇을 어떻게 (구체적으로) [범위] 건드릴 파일/영역 · 건드리지 말 것 [완료 조건] - [ ] 조건 1 (눈으로 확인 가능하게) - [ ] 조건 2 - [ ] PR에 전/후 스크린샷 또는 테스트 [참고] 비슷한 기존 코드 위치, 참고 문서 [난이도/예상] ★ or ★★ / 예상 소요 [멘토] 담당 멘토 이름
✅ 2026-07-17 구체화 완료 — 20건 모두 이 학습 플랫폼(mirim-app) 실코드 기준으로 검증했습니다. 이제 5~6주차에 배정만 하면 됩니다. 학생 1명당 5~6주 동안 2~4건이 적당해요.
| 패턴 | 실제 티켓 제목 | 구체화 | 배정 대상 | 배정일 | 상태 |
|---|---|---|---|---|---|
| FE-01 | 코딩 문제 필터 결과 0건 빈 상태 | ☑ | |||
| FE-02 | 공용 로딩 컴포넌트(스켈레톤) 도입 | ☑ | |||
| FE-03 | 비밀번호 변경: 새 비번 = 현재 비번 차단 | ☑ | |||
| FE-04 | 코딩 문제 목록에 언어·난이도 필터 | ☑ | |||
| FE-05 | 세션 만료 안내 메시지 | ☑ | |||
| FE-06 | 상단 메뉴 가로 스크롤 힌트 | ☑ | |||
| FE-07 | 페이지 히어로 공통 컴포넌트 추출 | ☑ | |||
| BE-01 | 코딩 문제 목록에 시도 횟수(attempts) 내려주기 | ☑ | |||
| BE-02 | 코딩 제출 코드 길이 제한 | ☑ | |||
| BE-03 | 검증 실패(400) 응답 메시지 한국어 통일 | ☑ | |||
| BE-04 | 학생 한 명의 과제 제출 모아보기 API | ☑ | |||
| BE-05 | 로그인 잠금 정책을 설정값으로 추출 | ☑ | |||
| BE-06 | N+1 지점 측정하고 개선하기 | ☑ | |||
| QA-01 | 잠재 버그: 문서 뷰어 notFound 상태 미리셋 | ☑ | |||
| QA-02 | SubmissionService·CourseProgressService 단위 테스트 | ☑ | |||
| QA-03 | README 현행화 — 따라 하면 실행되게 | ☑ | |||
| QA-04 | 미사용 import·변수 정리 (frontend/src/pages 한정) | ☑ | |||
| DZ-01 | 빈 상태·오류 화면 디자인 세트 | ☑ | |||
| DZ-02 | 퀴즈 결과 화면 UX 관찰·개선 제안 | ☑ | |||
| DZ-03 | 미니 디자인 시스템 정리표 | ☑ | |||
| OP-01 | 컨테이너 헬스체크 + 의존성 조건 | ☐ | |||
| OP-02 | push 시 자동 테스트 게이트 (Gitea Actions) | ☐ | |||
| SEC-01 | 보안·권한 계약 통합테스트 (@WebMvcTest) | ☐ | |||
| SEC-02 | 민감 PII 작업 감사로그 | ☐ | |||
| SEC-03 | 공개 쓰기 엔드포인트 레이트리밋 | ☐ | |||
| SEC-04 | 개인정보 열람·내보내기 접근 로그 | ☐ | |||
| SEC-05 | 의존성 취약점 손으로 점검해 보기 | ☐ | |||
| QA-05 | 프론트 첫 테스트 — 채점 함수 gradeSql 검증 | ☐ | |||
| QA-06 | 죽은 퀴즈 사본 정리 (seed/quiz 71개) | ☐ | |||
| FE-08 | 학습센터 진도율 로딩 가드 (0% 깜빡임) | ☐ | |||
| FE-09 | 멘토 '리뷰 대기' 한눈에 보기 | ☐ | |||
| FE-10 | '개발 환경 설치 가이드' 진입점 만들기 | ☐ | |||
| EDU-01 | '웹 보안·인증 기초' 코스 신설 | ☐ | |||
| EDU-02 | 코딩 문제·캡스톤 문서를 주차별 교육안에 연결 | ☐ |