왜 이 파이프라인이 필요했는가
해외 EPC 프로젝트는 현장마다 매주 주간보고 이메일이 들어오고, 사고·이슈는 LL·Project Issue·Pending List처럼 제각각 다른 엑셀 대장에 흩어져 쌓입니다. 그 안의 사실 — 호기별 진행상황, 마일스톤 날짜, 인력 파견, 이슈 조치이력 — 은 매번 사람이 다시 읽고 옮겨 적어야 다음 보고서(주간보고, LL보고서)가 나올 수 있었습니다. 메일로그는 이 반복 작업을 업로드 한 번으로 대체하는 것이 목적입니다 — 이메일 자체가 DB가 되고, 산출물은 그 DB에서 그때그때 다시 뽑아내는 방식으로.
프론트엔드 · 백엔드 · 개발 방식 세 축
사용자가 보는 화면
브라우저에서 바로 접속하는 웹앱. Cloudflare Pages에 정적 배포해 별도 서버 관리 없이 항상 접속 가능하도록 설계.
데이터와 추출 엔진
이메일 원본은 R2에, 구조화된 사실은 Supabase Postgres에. 기존 CCC 프로젝트의 DB를 emailpipeline 전용 스키마로 격리해 재사용.
설계 우선, 단계별 검증
Claude Code와 함께 9단계로 나눠 설계 문서를 먼저 확정하고, 매 단계 실제 코드를 짜서 가상 데이터로 로컬 검증한 뒤에만 다음 단계로 진행.
DB 스키마 기준, 6개 모듈
업로드 & 자동 분류
제목 패턴으로 주간보고 A형/B형, LL 대장을 자동 판별하고 RE:/FW: 스레드를 자동으로 묶는다.
하이브리드 추출 엔진
정규식으로 먼저 구조를 뽑고, 자유서술에 섞였거나 애매한 부분만 LLM에 보완 요청. 확정 전까지는 항상 검수 대기 상태.
마일스톤 추적
주차별 스냅샷을 쌓아 계획일이 실제로 얼마나, 언제부터 밀렸는지 이력으로 보존한다.
이슈 통합 로그
LL·Project Issue·Pending List, 서로 다른 4종 대장을 하나의 스키마로 통합하고 이슈 1건의 여러 조치이력을 자동 병합.
인력 파견 이력
표가 아니라 문장 속에 섞인 파견·휴가 정보까지 추출 대상으로 포착해 별도 이력으로 남긴다.
산출물 생성
DB에 쌓인 사실로부터 주간보고 A/B형, LL보고서를 요청 시점 기준으로 재구성해 뽑아낸다.
기능보다 먼저 지키기로 정한 5가지
정규식이 먼저, LLM은 빈 곳만
이메일 전체를 매번 LLM에 넘기지 않는다. 정규식으로 확정 못 한 필드만 골라 LLM에 보완 요청 — 비용과 신뢰도를 같이 잡기 위함.
자동 확정은 없다
정규식이든 LLM이든, 뽑아낸 값은 일단 pending_review. 사람이 한 번 확인해야 confirmed로 넘어간다.
억지로 채우지 않는다
못 뽑은 필드는 null로 두고 원문 스니펫만 보관한다. 실제로 그렇게 불완전한 데이터가 오기 때문.
지우지 않고 쌓는다
마일스톤은 덮어쓰지 않고 매주 스냅샷으로 적재해, 일정이 "얼마나 밀렸는지"까지 추적 가능하게 한다.
학습 데이터는 정답을 모른 채 만든다
추출 로직을 검증할 가상 이메일은 목표 DB 스키마를 보지 않고, 실제 서술 스타일만 참고해 노이즈까지 그대로 재현해서 만든다. 스키마를 알고 표본을 만들면 "깔끔하게 답이 보이는" 인풋만 생기고, 테스트가 테스트로서 의미를 잃기 때문 — 실제로 이 원칙 덕분에 검증 단계에서 진짜 파싱 버그를 발견했다.
9단계를 순서대로 — 설계 확정 후 코드, 코드 후 검증
phase_master로 공정단계 약어 체계를 여러 산출물이 공유하도록 정규화./api/emails) + xlsx 이슈대장(/api/issues) 업로드→파싱→Supabase 적재 전부 라이브 검증 완료 — 인력파견 이력, 마일스톤 표까지 저장. 진행 중 API 키 동기화 누락, 스키마 미노출, 권한 미부여, 배열 insert 키셋 불일치 등 실제 이슈 4건을 부딪히며 해결. LLM 실연동만 회사 결제 승인 대기로 보류..eml(MIME) 형식까지 정규식 파서가 처리하도록 일반화. 진행 중 실제 결함 다수를 발견해 수정 — 긴 헤더를 가진 실메일에서 MIME 판별이 실패하던 버그, 업로드 실패가 화면에 아예 안 보이던 버그, 아무것도 못 뽑았는데 "성공"으로 표시되던 허위 성공 버그. 메일 카드 클릭 시 원문 팝업, 발신/수신 표시, 프로젝트별 필터, 선택 삭제까지 추가.