.gitignore: CLAUDE.md 심볼릭 링크를 전역 무시에서 되살린다

최초 커밋에서 CLAUDE.md 가 빠져 있었다. 레포 .gitignore 에서는 뺐지만
이 머신의 ~/.gitignore_global 5번 줄이 CLAUDE.md 를 전역으로 무시한다.
전역 설정은 사람마다 달라 레포가 의존할 수 없으므로 `!CLAUDE.md` 로
레포가 스스로 되살린다.

내용 자체는 AGENTS.md 로 이미 커밋돼 있었다 — 빠진 건 링크뿐이다.
This commit is contained in:
Mina Choi 2026-08-31 13:58:34 +09:00
parent 6784e59ca5
commit 08a95e2bd7
14 changed files with 29 additions and 21 deletions

View File

@ -15,7 +15,7 @@ APP_ENV=local
# DB_PORT=5432
# DB_USER=postgres
# DB_PASSWORD=
# DB_NAME=o2o_site_db
# DB_NAME=web4ai_db
# ── JWT 서명 키 ───────────────────────────────────────────
# ★ 도커 이미지는 시크릿을 굽지 않으므로(config.local.toml 이 플레이스홀더 사본)

7
.gitignore vendored
View File

@ -33,5 +33,12 @@ frontend/admin/dist/
# ── 에이전트 지침은 커밋한다 ──────────────────────────────────────────────
# AGENTS.md / CLAUDE.md 는 팀과 모든 에이전트가 공유하는 규약이라 반드시 커밋한다.
# 커밋 안 하면 클론한 사람이 "배포 후 republish_all.py 필수" 같은 함정을 전달받지 못한다.
#
# ★ `!CLAUDE.md` 를 지우지 말 것. 이 머신의 ~/.gitignore_global 이 CLAUDE.md 를 전역으로
# 무시하고 있어서, 레포 쪽에서 명시적으로 되살리지 않으면 심볼릭 링크가 커밋되지 않는다.
# (전역 설정은 사람마다 다르므로 레포가 스스로를 지킨다.)
!CLAUDE.md
# 개인용 오버라이드는 레포가 아니라 ~/.claude/CLAUDE.md 나 .claude/settings.local.json 에 둔다.
.claude/settings.local.json

1
CLAUDE.md Symbolic link
View File

@ -0,0 +1 @@
AGENTS.md

View File

@ -221,7 +221,7 @@ python web_main.py # APP_ENV 기본 local → http://localh
## 테스트
**테스트는 호스트(venv)에서 돌린다** — DB(PostgreSQL)만 `127.0.0.1:5432` 에 떠 있으면 된다.
test DB(`o2o_site_test_db`)는 알아서 만들어졌다 지워지므로 **수동 세팅이 필요 없다.**
test DB(`web4ai_test_db`)는 알아서 만들어졌다 지워지므로 **수동 세팅이 필요 없다.**
```bash
cd backend
@ -235,7 +235,7 @@ python -m pytest tests/test_auth.py # 파일 하나만
venv 를 활성화하지 않으면 `.venv/bin/python -m pytest` 로 직접 지정한다. 정상이면 마지막 줄에 `NN passed`.
동작 방식 (전부 [conftest.py](conftest.py) 가 자동 처리):
- `APP_ENV``test` 로 자동 설정 → [config.test.toml](config/config.test.toml) 의 **`o2o_site_test_db`** 사용(dev DB 와 완전 분리).
- `APP_ENV``test` 로 자동 설정 → [config.test.toml](config/config.test.toml) 의 **`web4ai_test_db`** 사용(dev DB 와 완전 분리).
- **세션 시작 시 test DB 를 새로 만들고(CREATE), 끝나면 내린다(DROP).** 매번 현재 모델로 새로 빌드돼 스키마가 낡을 일이 없다.
- 테이블은 `create_all` 로 자동 생성, 매 테스트 전 `TRUNCATE` 로 비워 격리.
- 안전가드: 이름에 `test` 없는 DB 는 만들지도 지우지도 않는다(실 DB 보호).

View File

@ -21,7 +21,7 @@ log_level = "debug"
# 관리형 DB(RDS/Aurora/Azure)는 host 에 엔드포인트, sslmode="require".
[MainDBConfig]
db_type = "postgresql"
name = "o2o_site_db"
name = "web4ai_db"
write_host = "127.0.0.1"
write_port = 5432
write_id = "<DB_USER>"

View File

@ -1,5 +1,5 @@
# 테스트는 APP_ENV=test 로 실행한다 (config.test.toml → o2o_site_test_db, dev DB 와 분리).
# 이 픽스처들은 TRUNCATE 를 하므로 dev DB(o2o_site_db)와 절대 공유하면 안 된다(아래 db_engine 안전가드 참고).
# 테스트는 APP_ENV=test 로 실행한다 (config.test.toml → web4ai_test_db, dev DB 와 분리).
# 이 픽스처들은 TRUNCATE 를 하므로 dev DB(web4ai_db)와 절대 공유하면 안 된다(아래 db_engine 안전가드 참고).
# config.server_configs 가 import 되는 순간 config.<APP_ENV>.toml 을 읽으므로 가장 먼저 설정.
import os
@ -72,11 +72,11 @@ async def _test_db_lifecycle():
async def db_engine(_test_db_lifecycle):
"""테스트용 스키마를 보장하고, 매 테스트 시작 시 테이블을 비워 격리한다.
픽스처는 TRUNCATE 한다 dev DB(o2o_site_db) 가리키면 실데이터가 날아간다.
픽스처는 TRUNCATE 한다 dev DB(web4ai_db) 가리키면 실데이터가 날아간다.
그래서 test 전용 DB(이름에 'test') 아니면 즉시 중단한다(config.test.toml / APP_ENV=test).
(DB_SESSION_MNG) APP_ENV=test 같은 test DB 접속하므로 여기서 만든 스키마를 공유한다.
"""
# 안전가드: dev DB 오염 방지. o2o_site_test_db 이외엔 절대 실행하지 않는다.
# 안전가드: dev DB 오염 방지. web4ai_test_db 이외엔 절대 실행하지 않는다.
assert "test" in main_db_config.name, (
f"테스트가 비-test DB('{main_db_config.name}')를 가리킵니다. "
"APP_ENV=test(config.test.toml)로 실행하세요. dev DB 보호를 위해 중단합니다."

View File

@ -19,7 +19,7 @@ from common.enums import DBType, DBWRType, JobStatus
# 잡 적재 시 워커를 즉시 깨우는 LISTEN/NOTIFY 채널(폴링 제거).
JOB_NOTIFY_CHANNEL = "o2o_site_job"
JOB_NOTIFY_CHANNEL = "web4ai_job"
def compute_backoff(attempts: int, base: float = 5.0, cap: float = 600.0) -> float:

View File

@ -2,7 +2,7 @@
python scripts/demo_build.py (backend/ 에서 실행)
DB(o2o_site_db) 데모 회사·계정·사업장을 만든다. 개발 DB 에서만 .
DB(web4ai_db) 데모 회사·계정·사업장을 만든다. 개발 DB 에서만 .
"""
import asyncio, os, sys, uuid
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

View File

@ -1,4 +1,4 @@
"""파이프라인 데모 — 실 DB(o2o_site_db)에 사업장 하나를 만들어 끝까지 돌린다.
"""파이프라인 데모 — 실 DB(web4ai_db)에 사업장 하나를 만들어 끝까지 돌린다.
python scripts/demo_pipeline.py (backend/ 에서 실행)

View File

@ -38,7 +38,7 @@ x-common-env: &common-env
DB_PORT: ${DB_PORT:-5432}
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-password}
DB_NAME: ${DB_NAME:-o2o_site_db}
DB_NAME: ${DB_NAME:-web4ai_db}
# ── JWT 서명 키 ──
# ★ DB 와 같은 이유로 반드시 주입해야 한다. 이미지의 config.local.toml 은 플레이스홀더라
# 주입하지 않으면 "<JWT_ACCESS_SECRET>" 이라는 공개된 문자열이 서명 키가 된다(부팅 시 경고 로그).

View File

@ -69,7 +69,7 @@
|---|---|---|
| 레이어 구조 | 원본 그대로 — `router``service``crud`, 람다 DB 실행, `Req_*`/`Res_*` 프로토콜, `RemoveNoneResponse` | "기존 컨벤션을 그대로 따른다" |
| 포트 | **9800** | negosium 9300 / negodata 9400 / agent 9500 / lps 9600 / anchoring 9700 다음 번호 |
| DB | `o2o_site_db` (테스트 `o2o_site_test_db`), 기존 로컬 postgres(`negosium-db` 컨테이너, 5432) 안의 **별도 database** | 원본과 같은 인스턴스·다른 DB. 스키마 네임스페이스 컨벤션 유지 |
| DB | `web4ai_db` (테스트 `web4ai_test_db`), 기존 로컬 postgres(`negosium-db` 컨테이너, 5432) 안의 **별도 database** | 원본과 같은 인스턴스·다른 DB. 스키마 네임스페이스 컨벤션 유지 |
| 마이그레이션 | Alembic 안 씀. `postgres-init/init-data/init.sql`(전체 DDL, 재실행 안전) + `postgres-init/alters/YYYY-MM-DD-<주제>.sql`(누적 ALTER) | 원본 방식 그대로 |
| 남긴 것 | config 로더 · 로거 · 싱글톤 · DB 세션 매니저(R/W 분리) · gmodel · gtime · authz · JWT/bcrypt dependencies · `company.companies`/`company.users` · auth 라우터 · 스케줄러 껍데기 · conftest(테스트 DB 자동 생성/삭제) | 전 모듈이 공통으로 쓰는 인프라. 인증은 places·facts·sites 전부가 `IsValidAccessToken` 에 의존한다 |
| 뺀 것 | quotation · supplier · item · card · dashboard · statistics · learning · renegotiation · landing · admin · notification · LPS 연동 · anchoring · 초청메일(ACS/SMTP) · Azure Blob 클라이언트 | negodata 고유 도메인. Blob 클라이언트만 1-2 결론 후 media 모듈과 함께 재이식 예정 |

View File

@ -12,7 +12,7 @@
-- 고유 키가 없는 소스를 위해 **(회사, 상호명, 도로명주소)** 대체 유니크를 둔다.
-- 도로명주소만으로는 안 된다 — 한 건물에 여러 가게가 있다.
\connect o2o_site_db
\connect web4ai_db
ALTER TABLE place.places
RENAME COLUMN kakao_place_id TO external_place_id;

View File

@ -11,7 +11,7 @@
-- → 후보(1=UNVERIFIED, 2=PENDING_OWNER)는 여러 건 공존 가능
-- → 재수집은 노출값을 건드리지 않고 후보로 쌓이고, 사람이 승인할 때 교체된다
\connect o2o_site_db
\connect web4ai_db
DROP INDEX IF EXISTS fact.uq_facts_place_key;
DROP INDEX IF EXISTS fact.uq_facts_unit_key;

View File

@ -2,9 +2,9 @@
-- 전부 IF NOT EXISTS 라 재실행 안전. 기존 DB 에 재실행하면 말미의 "기존 DB 보정(ALTER)" 섹션이 최신 스키마로 맞춰준다.
-- 컬럼 추가/타입 변경은 postgres-init/alters/YYYY-MM-DD-<주제>.sql 로 따로 쌓는다.
--
-- 단일 PostgreSQL 인스턴스, 단일 database(o2o_site_db) 안에서 도메인별 schema 로 묶는다.
-- 단일 PostgreSQL 인스턴스, 단일 database(web4ai_db) 안에서 도메인별 schema 로 묶는다.
-- postgres (1개 서버, 5432)
-- └── o2o_site_db
-- └── web4ai_db
-- ├── company : companies, users
-- ├── place : places, place_aliases, place_links, units, media
-- ├── fact : facts, faqs
@ -22,14 +22,14 @@
-- PostgreSQL 은 CREATE DATABASE IF NOT EXISTS 를 지원하지 않으므로,
-- 존재하지 않을 때만 생성하도록 psql \gexec 로 처리한다 (재실행 안전).
SELECT 'CREATE DATABASE o2o_site_db'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'o2o_site_db')\gexec
SELECT 'CREATE DATABASE web4ai_db'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'web4ai_db')\gexec
\connect o2o_site_db
\connect web4ai_db
-- 모든 세션에서 시각을 UTC 로 다룬다 (DEFAULT now() 가 UTC 기준으로 저장·조회됨).
ALTER DATABASE o2o_site_db SET timezone TO 'UTC';
ALTER DATABASE web4ai_db SET timezone TO 'UTC';
SET timezone TO 'UTC';
-- uuid 기본값(gen_random_uuid) 사용을 위한 확장 (public 스키마에 설치)