traeon/docs/plan.md
caadiq 18c4669679 docs: 계획서 최종 업데이트
- 4단계 배포 모드 완료 표시
- GraphQL 쿼리 예시 실제 사용 중인 쿼리로 업데이트
- 추후 계획 섹션 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:16:47 +09:00

9.8 KiB

Traeon (트래온) - 택배 배송조회 웹 구현 계획서

개요

개인용 택배 배송조회 웹 애플리케이션. 운송장 번호를 등록하면 배송 상태를 조회하고, 백그라운드에서 자동 갱신하며, 상태 변경 시 알림을 보내는 서비스다. 기존 Docker 인프라와 fromis_9 프로젝트의 기술 스택/패턴을 따른다.

기술 스택

영역 기술
Frontend React 18, Vite, Tailwind CSS, Zustand, React Query
Backend Fastify 5, MySQL2, node-cron
배송조회 delivery-tracker 셀프호스팅 (GraphQL API)
DB MariaDB (기존 인프라)
인프라 Docker Compose, Caddy 리버스 프록시

프로젝트 구조

/docker/traeon/
├── docker-compose.yml
├── .env
├── docs/
│   └── plan.md                      # 이 문서
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   ├── vite.config.js
│   ├── tailwind.config.js
│   ├── postcss.config.js
│   └── src/
│       ├── main.jsx
│       ├── App.jsx
│       ├── index.css
│       ├── api/
│       │   └── parcels.js           # API 클라이언트 함수
│       ├── components/
│       │   ├── ParcelForm.jsx       # 운송장 등록 폼
│       │   ├── ParcelList.jsx       # 택배 목록
│       │   ├── ParcelCard.jsx       # 개별 택배 카드
│       │   ├── TrackingTimeline.jsx  # 배송 추적 타임라인
│       │   └── CarrierSelect.jsx    # 택배사 선택 드롭다운
│       └── stores/
│           └── useParcelStore.js    # Zustand 상태관리
│
└── backend/
    ├── Dockerfile
    ├── package.json
    └── src/
        ├── server.js                # 진입점
        ├── app.js                   # Fastify 앱 빌드
        ├── config/
        │   └── index.js             # 환경변수 설정
        ├── plugins/
        │   ├── db.js                # MySQL2 연결
        │   └── tracker.js           # delivery-tracker GraphQL 클라이언트
        ├── routes/
        │   ├── index.js             # 라우트 통합
        │   ├── parcels.js           # CRUD + 조회 라우트
        │   └── carriers.js          # 택배사 목록 라우트
        ├── services/
        │   ├── parcel.js            # 택배 비즈니스 로직
        │   ├── tracker.js           # delivery-tracker API 호출
        │   ├── cron.js              # 자동갱신 스케줄러
        │   └── notification.js      # 알림 서비스 (Discord/Telegram webhook)
        └── utils/
            └── error.js             # 에러 처리

데이터베이스 스키마

CREATE TABLE parcels (
  id INT AUTO_INCREMENT PRIMARY KEY,
  carrier_id VARCHAR(50) NOT NULL,       -- 택배사 코드
  carrier_name VARCHAR(100) NOT NULL,    -- 택배사 이름
  tracking_number VARCHAR(100) NOT NULL, -- 운송장 번호
  label VARCHAR(200),                    -- 사용자 별칭
  status VARCHAR(50) DEFAULT 'pending',  -- 배송 상태
  last_detail TEXT,                      -- 최근 배송 상세 (JSON)
  last_checked_at DATETIME,              -- 마지막 조회 시각
  delivered_at DATETIME,                 -- 배송 완료 시각
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uq_carrier_tracking (carrier_id, tracking_number)
);

CREATE TABLE carriers (
  id VARCHAR(50) PRIMARY KEY,             -- 택배사 코드 (예: cjlogistics)
  name VARCHAR(100) NOT NULL,             -- 택배사 이름
  short_name VARCHAR(20) NOT NULL,        -- 약칭 (로고 없을 때 이니셜용)
  color VARCHAR(7) NOT NULL,              -- 브랜드 컬러 (#hex)
  logo_url VARCHAR(500),                  -- RustFS에 저장된 로고 이미지 URL
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 기본 택배사 데이터 (5개)
-- | id           | name       | logo_url                                        |
-- |--------------|------------|------------------------------------------------|
-- | cjlogistics  | CJ대한통운  | https://s3.caadiq.co.kr/traeon/logo/cjlogistics.svg |
-- | hanjin       | 한진택배    | https://s3.caadiq.co.kr/traeon/logo/hanjin.svg      |
-- | lotte        | 롯데택배    | https://s3.caadiq.co.kr/traeon/logo/lotte.svg       |
-- | epost        | 우체국택배  | https://s3.caadiq.co.kr/traeon/logo/epost.svg       |
-- | logen        | 로젠택배    | https://s3.caadiq.co.kr/traeon/logo/logen.svg       |

CREATE TABLE tracking_events (
  id INT AUTO_INCREMENT PRIMARY KEY,
  parcel_id INT NOT NULL,
  status VARCHAR(50),
  description TEXT,
  location VARCHAR(200),
  event_time DATETIME,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (parcel_id) REFERENCES parcels(id) ON DELETE CASCADE
);

API 설계

Method Path 설명
GET /api/parcels 전체 택배 목록 (상태별 필터)
POST /api/parcels 운송장 등록
GET /api/parcels/:id 개별 택배 상세 + 추적 이벤트
PUT /api/parcels/:id 별칭 수정
DELETE /api/parcels/:id 운송장 삭제
POST /api/parcels/:id/refresh 수동 새로고침
GET /api/carriers 지원 택배사 목록 (로고 URL 포함)

구현 단계

1단계: 프로젝트 초기 세팅

  • docker-compose.yml 작성
    • traeon-frontend: node:20-alpine, 포트 80, 네트워크 app
    • traeon-backend: node:20-alpine, 포트 80, 네트워크 app + db
    • delivery-tracker: 셀프호스팅 컨테이너, 네트워크 app
    • Watchtower 제외 레이블
  • .env 파일 작성 (DB 접속정보 등)
  • Caddy에 traeon.caadiq.co.kr 도메인 추가

2단계: Frontend 구현 (더미 데이터)

  • Vite + React + Tailwind 초기 세팅
  • 더미 데이터 준비 (택배사 목록, 배송 중/완료 샘플 데이터)
  • 메인 페이지
    • 운송장 등록 폼 (커스텀 드롭다운 + 택배사 로고 + 운송장 번호 + 별칭)
    • 택배 목록 (카드형, 필터 탭으로 배송중/완료 구분)
    • 각 카드에 택배사 로고, 현재 상태, 등록일 표시
  • 상세 페이지
    • 배송 추적 타임라인 (세로 타임라인 UI)
    • 수동 새로고침 버튼 (상단 배치)
    • 삭제/수정 기능 (제목 옆 아이콘)
  • Zustand로 UI 상태 관리 (필터, 정렬)
  • framer-motion 애니메이션 적용
  • PC/모바일 반응형 대응 (lg 브레이크포인트)
  • SVG 파비콘 로고 추가
  • Pretendard 폰트 적용

3단계: Backend 구현 + 연동

  • Fastify 앱 세팅 (app.js, server.js) — fromis_9 패턴
  • DB 플러그인 + 테이블 자동 생성 (parcels, tracking_events, carriers)
  • 기본 택배사 5개 데이터 자동 삽입 (CJ대한통운, 한진, 롯데, 우체국, 로젠)
  • 택배사 로고 SVG를 RustFS에 업로드하고 carriers 테이블에 logo_url 저장
  • delivery-tracker 셀프호스팅 (Docker 이미지 빌드, Apollo Server 포트 4000)
  • delivery-tracker GraphQL 클라이언트 플러그인 (tracker.js)
  • API 라우트 구현 (parcels CRUD + carriers 목록 + 수동 새로고침)
  • Frontend를 더미 데이터에서 실제 API로 전환
    • Vite 프록시 설정 (/api/ → backend)
    • React Query로 데이터 페칭 (택배 목록, 상세, 택배사 목록)
    • 등록/수정/삭제/새로고침 mutation + 캐시 무효화
    • 택배사 로고를 RustFS URL에서 로드
  • 자동갱신 cron 서비스 (node-cron, 30분 간격)
    • 배송 완료되지 않은 택배만 자동 조회 (DELIVERED 제외)
    • 상태 변경 시 로그 기록
  • 알림 서비스 (보류 — 추후 앱 버전에서 푸시 알림으로 구현 예정)

4단계: Docker 배포

  • 프론트엔드+백엔드 단일 컨테이너로 통합 (Dockerfile)
  • 프론트엔드 빌드 → Fastify 정적 파일 서빙 + SPA fallback
  • docker compose up -d --build 로 배포 모드 실행 확인
  • Caddy 리버스 프록시 설정 (traeon:80)

delivery-tracker 셀프호스팅 연동

delivery-tracker는 GraphQL API를 제공한다. Backend에서 GraphQL 쿼리로 배송 정보를 조회:

query Track($carrierId: ID!, $trackingNumber: String!) {
  track(carrierId: $carrierId, trackingNumber: $trackingNumber) {
    trackingNumber
    sender { name }
    recipient { name }
    lastEvent {
      status { code name }
      time
      location { name }
      description
    }
    events(last: 100) {
      edges {
        node {
          status { code name }
          time
          location { name }
          description
        }
      }
    }
  }
}

참조할 기존 파일

파일 용도
/docker/fromis_9/docker-compose.yml Docker 서비스 구성 패턴
/docker/fromis_9/frontend/vite.config.js Vite 프록시 설정
/docker/fromis_9/backend/src/app.js Fastify 플러그인 로드 패턴
/docker/fromis_9/backend/src/plugins/db.js MySQL2 연결 패턴
/docker/fromis_9/backend/src/routes/index.js 라우트 통합 패턴
/docker/fromis_9/backend/src/server.js 서버 진입점 패턴
/docker/caddy/Caddyfile Caddy 도메인 추가 위치

검증 방법

  1. docker compose up -d --build 로 전체 서비스 기동
  2. docker compose logs -f 로 에러 확인
  3. 브라우저에서 traeon.caadiq.co.kr 접속, 운송장 등록/조회 테스트
  4. cron 자동갱신 로그 확인

추후 계획

  • 알림 서비스 (앱 버전에서 푸시 알림으로 구현 예정)
  • 다크모드
  • PWA 적용 (모바일 홈 화면 추가)