Daejeon · Food Safety · Incident Report

대전 자가품질검사 시스템 — 인프라 분석·복구 리포트

FINGU-GRINDA/daejeon-food-inspection · 단일 EC2(t3.medium) · docker-compose 8컨테이너
2026-06-08 개인용 · noindex 상태: 정상화 완료

🩺한눈에 보기

8실행 컨테이너 (정상)
3→0연속 배포 실패 → 복구
2머지된 수정 PR (#10·#11)
44현행 알림(검사일정) 건수

🚨이슈 1 — 배포 3연속 실패 & "CORS" 에러

사용자 화면(:1880)에서 CORS request did not succeed (null) 다발 → 실제론 CORS가 아니라 백엔드 :3001 크래시 루프.

근본 원인 — non-root 전환(PR #8) 부작용
컨테이너가 USER app으로 실행되나 WORKDIR /app 디렉토리가 root 소유로 남음 → schedule.js의 winston File({filename:'~/server.log'})/app/~ mkdir 시도 → EACCES → exit 1 → :3001 재시작 루프 → 배포 헬스체크 4/5 실패.

해결 — 컨테이너 표준대로 stdout(Console) 단독 로깅으로 전환(파일로그 제거). 전 앱 fs-write 전수 스캔으로 이 1곳이 유일 지뢰임 확인. PR #10 머지·배포 성공

📑이슈 2 — 알림 데이터 "부분표시"

DB엔 알림(검사일정) 44건이 있는데 어드민 화면엔 10건만 노출.

근본 원인 — pageCount 이중 나눗셈
notifications/dao.jspageCount=ceil(total/limit)(=페이지 수)를 반환하는데 공유 PaginationComponent가 다시 ceil(pageCount/pageSize)로 나눔 → 버튼 1개만 생성. fee·frequency·institute dao는 모두 pageCount=total(행수)라 정상 → notifications만 규약 위반.

해결 — notifications dao를 pageCount=totalCount로 통일(공유 컴포넌트 무수정), web 알림 dao는 INNER→LEFT JOIN(방어적). PR #11 머지·배포 성공

🗃️알림 데이터 현황 (DB 실측)

구분테이블건수
현행 SSOTinspection_schedules_management44
└ D-7 발송완료26
└ D-3 발송완료27
└ D-1 발송완료27
└ 검사예정일 미래15
구 아키텍처 잔존tbl_notifications132
(코드 미참조)tbl_notification_users70
(코드 미참조)tbl_notification_products104

🧹인프라 정리

📌후속 권장 (미적용)