개발 일지 요약 (pposiraegi 프로젝트 인프라 구축 및 배포)

다음은 개발자와 AI 간의 오늘 하루 대화 로그야. 이 로그를 분석해서 내가 하루 동안 무엇에 집중하고 시간을 썼는지 한눈에 파악할 수 있도록 Obsidian 마크다운 형식으로 요약해줘.

1. 작업 분포

카테고리비중
인프라 구축/테라폼35%████░░░░░░
백엔드 배포/데이터30%███░░░░░░░
프론트엔드 연동/UI25%██░░░░░░░░
디버깅/문제 해결10%█░░░░░░░░░

2. 집중 영역 / 시간 소모 포인트

  • 생산적 작업

    • terraform plan을 통해 VPC, ALB, RDS, ElastiCache, CloudFront 등 52개의 AWS 리소스 배포 계획 수립 및 실행.
    • Docker Compose 구조를 운영용과 로컬용으로 분리하여 환경 변수 관리 체계 개선.
    • Redis와 DB 간의 재고 동기화 로직(StockSyncScheduler) 수정 및 1인 1구매 제한 로직(TimeDealDetail) 구현.
    • Mock PG 팝업 결제 연동(PaymentCallback 컴포넌트) 및 Same-Origin 전략으로의 CORS 이슈 근복적 해결.
  • 삽질/시간 소모 포인트

    • Terraform 배포 에러: Security Group 규칙 초과(CloudFront Prefix List 문제)와 Route53 레코드 중복 이슈로 인한 apply 재시도.
    • CloudFront 404 마스킹: 백엔드 API 에러(404)를 CloudFront가 index.html(200 OK)로 변환하여, 프론트엔드에서 에러를 JSON으로 파싱하지 못하고 undefined 크래시가 발생하는 원인을 파악하는 데 시간 소요.
    • Redis Codec 불일치: Lua 스크립트는 String로 쓰고 스케줄러는 Long으로 읻어 디코딩 실패, 재고 동기화가 안 되는 문제를 해결하기 위해 로직 분석.
    • 주문 번호 충돌: 컨테이너 재시작 시 메모리 기반 OrderNumberGenerator가 초기화되어 DB 기존 데이터와 중복 충돌 발생, DB 초기화로 임시 해결.

3. 타임라인

  • 10:03 ⌨️ terraform 디렉토리 이동 및 plan 명령어 실행.
  • 10:08 🦦 terraform apply 시도 중 사용자 승인(yes) 요구로 EOF 오류 발생.
  • 10:11 ⌨️ 사용자가 로컬 터미널에서 apply 수동 실행.
  • 10:33 ⌨️ Terraform apply 실패 (Security Group 규칙 초과, Route53 CNAME 중복).
  • 11:03 ⌨️ Route53 Hosted Zone 소스를 data로 변경하여 destroy 방지.
  • 11:55 🦦 Docker Compose 구조 개편(dev-override.yml 분리) 및 user_data.sh를 .env 파일 방식으로 수정.
  • 13:14 🦦 DB 스키마 생성 및 Seed 데이터 삽입 완료.
  • 13:50 🦦 체크아웃 시 undefined 에러 발생. CloudFront의 404 변환 설정 문제로 추정.
  • 14:05 🦦 CloudFront가 API 404 응답을 index.html로 변환하여 파싱 실패하는 현상 확인.
  • 14:20 🦦 CORS 문제 발견. CloudFront가 Preflight 헤더를 포워딩하지 않음.
  • 14:27 🦦 Same-Origin 전략 수립: 프론트엔드 API URL을 pposiraegi.cloud로 변경.
  • 14:37 🦦 WebSocket Mixed Content 에러(ws:// vs wss://) 발생.
  • 14:42 🐹 GCP Cloud Run Mock PG 서비스에 CORS 미들웨어 추가 후 재배포.
  • 15:02 🦦 수정 사항이 로컬 브랜치에 있어 EC2(main)에는 적용되지 않은 문제 발견.
  • 15:07 ⌨️ 시간 부족으로 EC2 내부에서 sed 명령어로 MockPgClient 로직 직접 패치 후 재빌드.
  • 15:53 ⌨️ 로그인 시 특수문자(!) 이스케이프 문제로 실패, 테스트 유저 생성.
  • 15:55 ⌨️ CloudFront가 /api 요청에 대해 HTML을 반환, 캐시 무효화 실행.
  • 15:57 ⌨️ 주문 생성 시 orders_order_number_key 중복 에러 발생, DB 테이블 초기화.
  • 16:02 🦦 주문 DB 저장 실패 로그 확인. Redis 재고 복구 스케줄러 동작 의심.
  • 16:05 🦦 StockSyncScheduler가 LongCodec으로 읽어 StringCodec과 충돌하는 원인 발견.
  • 16:06 ⌨️ StockSyncScheduler.java 코덱 수정(StringCodec로 변경) 후 재배포.
  • 16:21 🦦 프론트엔드 timedeal.js에서 딜 레벨 수량 대신 SKU 재고 합계 사용하도록 수정.
  • 16:31 🦦 뒤로가기 재결제 방지 로직(sessionStorage + replace: true) 추가.
  • 16:44 🦦 auth.js에 401 인터셉터 추가하여 자동 로그아웃 처리.
  • 16:58 🦦 SKU 재고 0일 경우 ACTIVE 상태를 SOLDOUT으로 오버라이드하는 로직 추가.
  • 17:33 🦦 PaymentCallback.jsx 생성 및 팝업 호출 로직 구현.
  • 17:39 🦦 팝업 강제 종료(X 버튼) 감지 폴링 로직 추가.
  • 17:53 🦦 로컬과 클라우드런 Mock PG 소스 혼동 문제 지적, 단일 소스(epicodix/mock-pg-server)로 통일 작업.
  • 18:00 ⌨️ 구버전 mock-pg 폴더 삭제.
  • 18:15 🦦 TimeDealDetail.jsx에 1인 1구매 제한 로직 구현.
  • 18:18 🦦 사용자가 여전히 결제 페이지로 넘어간다고 보고, 원인 분석 중 AI 사용량 제한(Rate limit) 도달.

4. 해결한 문제와 인사이트

  • 문제 1: Terraform Apply EOF 오류

    • 해결: AI 도구 내 비대화형 환경 제약으로 인해 terraform apply 시 승인 입력(yes)이 불가능하여 발생. 사용자가 로컬 터미널에서 직접 명령어를 입력하여 해결.
    • 인사이트: 사용자 승인이 필요한 명령어는 자동화 도구보다 로컬 터미널 실행이 유리하거나 -auto-approve 옵션 활용이 필요함.
  • 문제 2: CloudFront 404 → HTML 변환

    • 해결: SPA 호스팅을 위해 CloudFront에 설정된 404 Custom Error Response(→ index.html)가 API 경로에도 적용되어, 프론트가 JSON 대신 HTML을 받아 파싱 실패하는 문제였음. API 경로에 대한 에러 변환 설정을 제거하거나 Behavior를 분리하여 해결.
    • 인사이트: 백엔드 에러 응답이 프론트까지 정확히 전달되지 않으면 디버깅 난이도가 급상승하므로, CDN/LB 설정 시 API와 프론트의 에러 처리를 명확히 분리해야 함.
  • 문제 3: Redis-DB 재고 동기화 실패

    • 해결: Lua 스크립트는 SKU ID를 String으로 dirty set에 저장하지만, StockSyncScheduler는 Long으로 읽으려 시도하여 디코딩에 실패함. StockSyncScheduler.java의 코덱 설정을 StringCodec으로 변경하여 해결.
    • 인사이트: 분산 환경(Redis 등)에서 데이터를 주고받을 때는 직렬화/역직렬화 방식(String/Long 등)을 양측에서 정확히 일치시켜야 함.
  • 문제 4: 주문 번호 충돌 (Order Number Collision)

    • 해결: 메모리 기반 OrderNumberGenerator가 컨테이너 재시작 시 초기화되어 DB 기존 데이터와 중복됨. DB 테이블을 초기화하여 임시 해결.
    • 인사이트: 메모리 상태에 의존하는 ID 생성 로직은 서버 재시작 시 유지되지 않으므로, DB Sequence나 Snowflake와 같은 안전한 생성 전략이 필요함.
  • 문제 5: 팝업 결제 창 닫힘 미감지

    • 해결: 단순 postMessage 의존 시 사용자가 팝업을 강제 종료(X 버튼)하면 이벤트가 누락됨. setInterval로 500ms마다 popup.closed 상태를 폴링하여 강제 종료를 감지하도록 수정.
    • 인사이트: 사용자 인터랙션(팝업 닫기 등)은 엣지 케이스(강제 종료)까지 고려하여 이중으로 감지하는 로직이 필요함.
  • 문제 6: CORS 및 Same-Origin

    • 해결: 복잡한 CORS 헤더 설정을 디버깅하는 대신, 프론트엔드 API 도메인을 pposiraegi.cloud로 통일하여 Same-Origin 정책을 만듦으로써 근본적인 해결.
    • 인사이트: 가능하다면 도메인을 통일하여 SOP(Same-Origin Policy) 내에서 운영하는 것이 CORS 설정 복잡도를 줄이는 가장 좋은 방법임.

Supported by ai-log-sync & GLM-4.7