Skip to content

[fix] 프레임 최소 간격을 이전 프레임 시작 시각부터 세기 - #263

Merged
minwoo-3 merged 4 commits into
developfrom
fix/face-frame-interval-start
Oct 28, 2026
Merged

minwoo-3 merged 4 commits into
developfrom
fix/face-frame-interval-start

Conversation

@minwoo-3

Copy link
Copy Markdown
Contributor

✨ 작업 내용

  • 프레임 최소 간격(기본 200ms)을 이전 프레임을 시작한 시각부터 세도록 바꿨습니다. 지금까지는 이전 프레임 처리가 끝난 시각(잠금 해제 시각)부터 세었습니다.
    • face_recognition_session.last_frame_started_at 컬럼을 추가했습니다(V22, NULL 허용).
    • claim은 last_frame_started_at이 NULL이거나 now - 간격 이전일 때만 잡고, 시작 시각과 활동 시각을 같이 갱신합니다. release는 지금처럼 활동 시각만 갱신합니다.
    • 첫 프레임은 last_frame_started_at이 NULL이라 바로 받습니다. 세션 생성 때 활동 시각을 now - 간격으로 당겨 두던 우회는 없앴습니다.
  • 세션마다 한 번에 한 프레임만 처리하는 잠금은 그대로입니다.
  • 프레임 인식 swagger에 간격 기준, 429 두 종류, 429 뒤에도 세션이 유지된다는 설명을 추가했습니다.

🔍 리뷰 시 참고사항

웹은 프레임 간격을 250300ms로 줄이고 전송 시작 시점 기준으로 간격을 두려고 합니다. 이전 기준에서는 다음 계산 때문에 처리 시간이 50100ms만 넘어도 429가 납니다.

  • 예: 0ms에 보냄, 150ms에 응답이 끝남, 250ms에 다음 프레임을 보냄.
  • 이전 기준으로는 응답이 끝난 지 100ms라 429가 납니다.
  • 바뀐 기준으로는 시작한 지 250ms라 받습니다.
  • 처리가 200ms보다 오래 걸리면 끝난 뒤 바로 다음 프레임을 받습니다.

#262 질문 답변:

  1. 다른 층 재비교: 하지 않습니다. [fix] 얼굴 인식 세션 후보를 고른 층 학생으로 제한하고 OTHER_FLOOR 제거 #257 이후 서버는 고른 층 학생만 AI 세션 후보로 보냅니다. AI는 그 세션 후보와만 비교하고, 다른 층 학생은 UNKNOWN입니다. OTHER_FLOOR는 더 이상 보내지 않습니다(main 반영됨).
  2. 200ms 기준: 세션(카메라 페이지) 단위입니다. 계정·IP 단위가 아닙니다. 이 PR 뒤로는 이전 프레임의 시작 시각 기준이고, 처리 중인 프레임이 있으면 간격과 상관없이 거절합니다.
  3. 너무 빠르면: 429 FACE_FRAME_RATE_LIMITED이고 Retry-After는 없습니다. 서버 전체 동시 처리 한도(FACE_MAX_CONCURRENT_FRAMES, 기본 4)를 넘으면 429 FACE_SERVICE_BUSY이고, 이것도 Retry-After가 없습니다. 둘 다 그 요청만 거절하고 세션은 끊지 않습니다. 세션은 5분 동안 프레임이 없을 때, 그리고 AI 5xx·404 오류일 때 닫힙니다.
  4. 프레임 처리 시간: 서버에서 측정한 실측값은 없습니다. 이 레포에는 프레임 처리 시간 지표가 없습니다. AI 저장소의 구성 요소 벤치마크(합성 데이터)는 아래와 같습니다.
    • 200명 × 20벡터 비교: 중앙값 약 0.6ms
    • 임베딩: 얼굴 1개당 약 2~4ms
    • 디코딩·검출·네트워크를 포함한 전체 시간은 측정되지 않았습니다. 웹 측정 로그로 확인해야 합니다.
    • 최대는 Spring이 기다리는 AI 시간 제한인 연결 2초 + 응답 30초입니다.
  5. 카메라 3대 동시: 세션마다 처리 중 프레임은 최대 1개입니다. 3대면 동시 3개라 동시 처리 한도 4 안에 들어갑니다. 4번째 카메라 페이지가 같이 보내면 FACE_SERVICE_BUSY가 날 수 있습니다. AI가 프로세스 하나 CPU로 250ms마다 3대를 따라가는지는 측정하지 않았습니다.
  6. 한 프레임 인원: 서버는 인원을 제한하지 않습니다. AI 검출이 최대 8명(MediaPipe num_faces=8)이라 응답 faces도 최대 8개입니다.
  7. 250~300ms 간격: 이 PR이 배포되면, 이전 응답을 받은 뒤 보내는 한 간격 때문에 429는 나지 않습니다. 응답 전에 겹쳐 보내면 처리 중 잠금 때문에 429입니다. 세션은 끊기지 않습니다.

검사: 로컬 PostgreSQL(compose)과 CI와 같은 테스트 env로 ./gradlew build를 실행해 통과했습니다. 실제 AI 서버·카메라로 간격을 측정하지는 않았습니다.

✅ 체크리스트

  • 문서(README, .env.example 등) 변경이 필요한 경우 작성 또는 수정했나요?
  • 작업한 코드가 정상적으로 동작하는 것을 직접 확인했나요?
  • 필요한 경우 테스트 코드를 작성하거나 수정했나요?
  • Merge 대상 브랜치를 올바르게 설정했나요?
  • PR에 관련 없는 작업이 포함되지 않았나요?
  • 적절한 라벨과 리뷰어를 설정했나요?

📎 관련 이슈(선택)

@minwoo-3
minwoo-3 merged commit 2e8c555 into develop Oct 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants