← 목록
솔루션 2026-08-01 4KB 읽기 5분

crowny-solution 공사관리 — 사진 자동축소(EXIF 보존) + 동영상 업로드

개요

work-staff.html 사진 업로드에 클라이언트측 자동축소(긴변2048/2MB 기준)를 붙이되, canvas.toDataURL()의 EXIF 소실 문제를 순수 JS EXIF 파서 + APP1 splice 재이식으로 해결. 동영상은 재인코딩 없이 원본 그대로 순차 업로드. 사진/동영상은 MIME+확장자로 자동판별(라이브포토 페어링은 사용자 요청으로 최종 스펙에서 제외).

무엇을 했는지

  • 공사관리.한선(SSOT) + 공사서버.한선 + lib/공사관리.js(미러) 에 축소판정·축소목표·사진종류판정(mime,확장자)→photo/video/unknown·EXIF보존필요·업로드허용 추가. 53/53 한선씨 자체테스트 PASS, JS 미러 14/14 파리티 PASS.
  • web/work-staff.html: 순수 JS EXIF 파서(크라우니EXIF) — JPEG APP1(Exif) 세그먼트 offset/length 보존, TIFF IFD0/ExifIFD/GPS IFD 파싱(DateTimeOriginal·Make·Model·Artist·GPS), Orientation 보정 캔버스 회전, 축소 후 원본 APP1 splice 재이식(Orientation은 1로 되씀). HEIC 디코드 실패 시 원본 유지. 파일 자동분류(classifyFile) + 순차 업로드 + 파일별 진행표시 + 실패 재시도.
  • server.js: WORKPHOTO_COLSkind|shotAt|gps|device|shooter|origBytes|bytes 추가(append-only, 구행 안전파싱), 본문 300MB 상한(413), 파일서빙 Range 요청 지원(video/quicktime 등 Content-Type + 206 Partial Content).
  • web/work-owner.html/work-admin.html: 촬영시각·촬영자·기기·GPS(카카오맵 링크)·동영상 재생/뱃지 표시. 신규 hex 색상 0건(기존 CSS 변수만 사용).

검증 (실제 실행)

  • 한선씨 컴파일+자체테스트: 공사관리.한선 53/53 PASS, 공사서버.한선 컴파일 OK
  • JS 미러 파리티: 14/14 일치
  • node --check server.js, 3개 HTML 인라인 JS 구문검사 통과
  • EXIF 왕복 실측: exiftool로 GPS/DateTimeOriginal/Make/Model/Artist(한글) 주입한 JPEG를 POST /api/works/WK000001/photos로 업로드 → 다운로드한 파일이 원본과 byte-identical(cmp), exiftool로 5개 필드 전부 보존 확인
  • 클라이언트 EXIF 파서 자체를 HTML에서 추출해 Node로 실행 → 실제 파싱 결과가 exiftool 값과 정확히 일치(초기 버그 2건 발견·수정: ExifIFD/GPS IFD 포인터 offset 계산 오류, Artist 다국어 UTF-8 디코딩 누락)
  • splice 로직 합성 JPEG로 단위검증 — APP1 삽입 후 exiftool로 재판독 성공
  • 동영상 업로드 + Range 요청(bytes=0-99) → 206 Partial Content, Content-Type video/quicktime, 100바이트 정확 반환
  • 회귀: /api/health /api/solutions /api/dashboard + work*.html 전부 200, 공개 HTTPS 200
  • 디자인 대조: 신규 hex 0건. 골격 게이트: DOCTYPE+charset 3파일 전부 OK
  • 검증 후 테스트 파일 전부 삭제, workphoto.psv 0줄로 복원 확인(GET /photos → 빈 배열)

관련 파일

  • /Users/ef/crowny-solution/공사관리.한선
  • /Users/ef/crowny-solution/공사서버.한선
  • /Users/ef/crowny-solution/lib/공사관리.js
  • /Users/ef/crowny-solution/server.js
  • /Users/ef/crowny-solution/web/work-staff.html
  • /Users/ef/crowny-solution/web/work-owner.html
  • /Users/ef/crowny-solution/web/work-admin.html
  • /Users/ef/crowny-solution/CLAUDE.md (섹션 추가)

잔여 이슈 / 한계

  • 브라우저 canvas 축소 경로 자체(실제 Image/createImageBitmap→canvas.toBlob)는 curl로 재현 불가 — EXIF splice 로직은 Node에서 합성 JPEG로 단위검증했으나, 실제 브라우저 렌더링 파이프라인 전체(회전보정 포함)는 미실행. 크라우니AI검증.sh 등 헤드리스 브라우저로 추가 검증 권장.
  • 동영상 duration 은 클라이언트가 body에 실어 보내지만 서버 WORKPHOTO_COLS에는 별도 컬럼을 추가하지 않음(스펙에 명시적 저장 요구 없었음 — 필요 시 컬럼 추가 필요).
  • 디자인대조 훅이 .tabbar/.omni/.bm/.ib 등 브라우저-chrome 전용 셀렉터를 요구하는데 이 3개 페이지는 해당 컴포넌트가 원래 없는 구조라 FAIL이 계속 뜬다 — 이 페이지 유형에는 적용 대상이 아닌 것으로 판단, hex 색상 준수 여부만 별도로 확인함.