git 저장소가 없어 히스토리·협업 기반이 아예 없던 상태를 연다.
함께 문서를 재편했다. 그동안 문서가 있어도 "이 제품이 뭘 푸는가"와
"어떻게 도는가"를 담은 문서가 없어서, 목표 문장이 backend/frontend
README 두 곳에 복붙돼 있었다 — 상위 문서가 없어 아래로 샌 것이다.
신설
README.md 레포 진입점 + 문서 지도 + 문서 규칙 4가지
AGENTS.md 에이전트·신규 합류자용 함정 목록과 규약
(CLAUDE.md 는 여기로 걸린 심볼릭 링크)
docs/PRODUCT.md 제품 정의 — 문제·사용자·원칙·**non-goals**·성공 기준
docs/ARCHITECTURE.md payload 경계·발행 파이프라인·서빙 결정·앱 분리 설계
이동
backend/docs/DECISIONS.md → docs/DECISIONS.md
백엔드만의 결정이 아니다. 게다가 코드 주석 ~25곳이 이미
`docs/DECISIONS.md` 로 적고 있어 레포 루트 기준으로는 그게 맞다.
갱신
docs/DEPLOY.md 서빙 결정 반영 — nginx 정적 서빙이 지금 경로(3절),
Azure 는 나중에 켤 때(4절)로 분리
docs/ARCHITECTURE.md 사이트 = 한 장(2026-08-31) 구조 반영
docs/COLLECTION_SEO_AEO_FLOW.md
robots.txt·sitemap.xml 은 오리진 루트에만 굽는다는 점 명시
frontend/site/scripts/prerender.ts
헤더 주석의 렌더 보고서 경로가 실제(422줄)와 달라 수정
.gitignore
★ CLAUDE.md 를 더 이상 무시하지 않는다. 에이전트 지침은 팀과 모든
에이전트가 공유하는 규약이라 커밋해야 한다 — 무시하면 클론한 사람이
"배포 후 republish_all.py 필수" 같은 함정을 전달받지 못한다.
개인용 오버라이드는 ~/.claude/CLAUDE.md 에 둔다.
37 lines
1.9 KiB
Docker
37 lines
1.9 KiB
Docker
# o2o-web4ai 백엔드 이미지 — API 와 워커가 **같은 이미지**를 공유하고 command 로만 갈린다.
|
|
# API : python web_main.py (요청 접수/조회, :9800)
|
|
# 워커 : python worker_main.py (수집·비전분석·빌드 잡 처리, 포트 없음)
|
|
#
|
|
# Phase 1 은 collector 가 MockAdapter 만 등록하므로 브라우저가 필요 없다 → 이 lean 이미지 하나면 된다.
|
|
# 크롤링 법무 검토가 끝나 HeadlessAdapter 를 붙이면, 그때 Chrome+Xvfb 를 담은 별도 워커 이미지
|
|
# (Dockerfile.worker)를 만들어 갈라낸다 — 선례: o2o-negosium/lps/Dockerfile.worker
|
|
#
|
|
# 시크릿은 이미지에 굽지 않는다 — config 는 example(플레이스홀더)로 대체되고,
|
|
# 실제 값은 compose 의 env(DB_USER/DB_PASSWORD, *_API_KEY 등)로 주입된다(server_configs override).
|
|
FROM python:3.12-slim
|
|
|
|
WORKDIR /app
|
|
|
|
# 의존성 먼저 설치 (레이어 캐시 활용)
|
|
COPY requirements.txt .
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
COPY . .
|
|
|
|
# 시크릿 든 config.local.toml 은 .dockerignore 로 제외됨 → example(플레이스홀더)로 대체.
|
|
# 실값은 env 주입: DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME,
|
|
# PERPLEXITY_API_KEY/KAKAO_REST_API_KEY/GEMINI_API_KEY/TOUR_API_KEY
|
|
RUN cp config/config.local.toml.example config/config.local.toml
|
|
|
|
# 항상 APP_ENV=local 로 실행 → config.local.toml(=example 사본) + env override.
|
|
ENV APP_ENV=local
|
|
|
|
EXPOSE 9800
|
|
|
|
# API 컨테이너용. 워커는 command 를 갈아끼우고 이 헬스체크를 쓰지 않는다
|
|
# (워커는 포트가 없다 — 하트비트 파일 기반 체크는 필요해질 때 추가한다).
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:9800/healthz', timeout=4).status==200 else 1)"
|
|
|
|
CMD ["python", "web_main.py"]
|