마지막 업데이트 2026-09-22
감사 로그를 보면 “테스트교육1” 같은 이름이 저녁 수업 시간에 하루 수천 건씩 찍힙니다. 테스트 아동은 그 시간에 아무것도 하지 않았는데도요. 요청을 보내는 게 아니라, 이름표만 따라다니는 것입니다. 그림 6장으로 설명합니다.
로그만 보면 “테스트 아동이 수업 중에 요청을 보낸다”처럼 보입니다. 실제로는 아닙니다.
2026-09-21 20:00~22:00 실측 — 태깅 6,109건은 전부 진행자가 보낸 정상 수업 요청.
낮에 테스트 계정으로 로그인하면 이름표 한 장이 브라우저 가방에 들어갑니다. 유효기간 14일.
이름표는 로그아웃하지 않으면 사라지지 않습니다. 두 장이 나란히 공존합니다.
childSessionOptions.cookieOptions.maxAge = 60 * 60 * 24 * 14 (apps/web/lib/session-options.ts:41). 진행자용과 값이 같습니다.브라우저는 같은 도메인으로 요청을 보낼 때 가방 안 이름표를 전부 자동으로 함께 보냅니다. 골라 보내지 않습니다.
쿠키는 요청을 만들지 않습니다. 이미 가는 요청에 얹혀 갈 뿐입니다.
multiple이름표가 두 장이면 감사 로그는 둘 다 적습니다. 그래서 진행자 요청에 아동 이름이 붙습니다.
판정 코드는 apps/web/api-audit.js:93 — if (member && child) return { actorType: "multiple", ...member, ...child }.
2026-09-21 21:49:28, 로그 8줄에 같은 아동 이름이 연달아 찍혔습니다. 같은 요청의 반복처럼 보입니다.
21:49:28.685 childName:"테스트교육6" GET /api/lessons/4ef1aad0…/2
21:49:28.688 childName:"테스트교육6" GET /api/lessons/d579d955…/44
21:49:28.696 childName:"테스트교육6" GET /api/lessons/7fd2922e…/16
21:49:28.704 childName:"테스트교육6" GET /api/lessons/b81c61c7…/14
21:49:28.710 childName:"테스트교육6" GET /api/lessons/49099392…/20
21:49:28.720 childName:"테스트교육6" GET /api/lessons/0f0e940a…/34
21:49:28.729 childName:"테스트교육6" GET /api/lessons/b7896f37…/26
21:49:28.736 childName:"테스트교육6" GET /api/lessons/f2ef0613…/22
이름은 8줄 모두 같지만 경로의 아동 ID는 8개 전부 다릅니다. 진행자 화이트가 목록 화면을 한 번 열었고, 화면이 아동 수만큼 한 번씩 조회한 것입니다(N+1). 같은 요청의 반복이 아닙니다.
2026-09-09~09-21, 매일 20:00~22:00 ppi-web-prod 감사 로그 전수.
하루 31건에서 6,719건까지 40배 넘게 차이 납니다. 테스트 아동의 활동량과는 무관하고, 두 가지가 곱해진 결과입니다.
| 요인 | 내용 | 예 |
|---|---|---|
| ① 그날 수업이 있었나 | 주말은 전체 요청 자체가 300~1,300건뿐 | 09/20(일) 31건 · 09/12(토) 6건 |
| ② 어느 진행자가 근무했나 | 이름별로 붙는 진행자가 거의 고정. 그 사람이 쉬면 0건 | 테스트교육3 → 카이아(09/16·18·21에만 등장) |
| ③ 그 진행자의 그날 업무량 | 태깅 건수 = 그 브라우저의 모든 요청 | 09/21 그랜트 1,206건 전부가 태깅 |
테스트교육2, 09/16부터 테스트교육6으로 찍힙니다. 다른 테스트 계정으로 다시 로그인한 흔적입니다.| 항목 | 판정 | 근거 |
|---|---|---|
| 요청 수가 늘어난다 | 아니다 | 쿠키는 기존 요청에 얹혀 감. 로그 1줄 = 요청 1건 |
| 서버 부하를 만든다 | 아니다 | 쿠키 복호 0.095ms — 요청당 CPU 32.3ms의 0.3% |
| 테스트 아동 데이터가 조회된다 | 아니다 | 핸들러는 경로의 userId로 동작. 09/21 태깅 6,109건 중 테스트 아동 대상 0건 |
| 감사 로그가 틀린 아동에 귀속된다 | 그렇다 | 09/21 전체 63,081건 중 9.7%가 잘못된 아동 이름 |
| 아동 인증 토큰이 진행자 PC에 상주한다 | 그렇다 | ChildSession에 accessToken/refreshToken 포함, 최대 14일 |
| 그 토큰으로 아동 권한 API가 열리는가 | 미확인 | 토큰 사용처 추적 필요 — 이 문서의 후속 과제 |
api-audit.js:93 — member가 있으면 child를 actor로 쓰지 말고 staleChildName 같은 별도 필드로 분리maxAge를 수업 시간 수준으로 단축)| 무엇 | 어디 |
|---|---|
| 아동 로그인 · 쿠키 발급 | apps/web/app/api/users/auth/route.ts:41-43 |
쿠키 옵션 · maxAge 14일 | apps/web/lib/session-options.ts:34-43 |
| 요청마다 두 세션을 함께 읽음 | apps/web/proxy.ts:30-33 |
actor 판정 — multiple | apps/web/api-audit.js:93 |
| 감사 로그 기록 지점 | apps/web/proxy.ts:46-57 (started) · apps/web/server.js:77-94 (completed) |
instance="ppi-web-prod" 로그를 날짜별 20:00~22:00 범위로 내려받아 api_audit_started의 actorType·memberName·childName·path를 교차 집계했습니다. 로그 보관 범위가 20:00~22:00이라 쿠키가 발급된 낮 시각 자체는 확인하지 못했고, 해당 창에서 진행자 브라우저의 아동 로그인은 12일 통틀어 373건 중 2건뿐이었습니다 — 발급이 수업 시간 밖에 일어났다는 것은 이 관찰에 근거한 추정입니다.