인프라 운영 (Railway + 백엔드 설정)
환경변수 파일 (APP_ENV 기반)
config.go init 이 APP_ENV 값으로 .env.<APP_ENV> 자동 로드.
APP_ENV미설정 시 →.env.(빈) 로드 시도 → 실패 → 환경변수 없이 기동 → 카카오/JWT 빠져 로그인 깨짐. 반드시APP_ENV=local명시- 로컬 dev:
backend/.env.local(gitignore) - prod: Railway 가 OS 환경변수 직접 주입 — 파일 불필요
.env.example삭제됨 (2026-04-25)..env.prod는 Railway 참고용 로컬 파일
필수 키: DATABASE_URL, DART_API_KEY, KAKAO_CLIENT_ID/SECRET, JWT_SECRET, ADMIN_KEY.
필수 prod 환경변수
| 변수 | 값 | 이유 |
|---|---|---|
TRUSTED_CLIENT_IP_HEADER | CF-Connecting-IP | 레이트 리밋. 미설정 시 모든 사용자가 Railway 엣지 IP 묶여 정상 트래픽도 429. CF DNS 프록시(🟠) 켜져 있어야 헤더 채워짐 |
STOCK_SYNC_SCHEDULER_ENABLED | true (prod) / false (dev) | 종목 마스터 일일 동기화 |
DISCLOSURE_MONITOR_AUTO_START | true (prod) / false (dev) | 공시 모니터 |
ANALYSIS_SCHEDULER_AUTO_START | true (prod) / false (dev) | AI 분석 스케줄러 |
미들웨어 체인 (cmd/server/main.go)
바깥 → 안쪽: RateLimit → /auth 전용 RateLimit → CORS → JWT 파싱 → 인증 체크 → HTTPCache → mux
- 전역: 2 RPS / 10 burst (분당 120)
- /auth/*: 0.5 RPS / 5 burst (분당 30, 브루트포스 방어)
- HTTP 캐시 대상:
/disclosures/{rcept}5 분,/disclosures/recent30 초,/disclosures?corpCode=1 분,/stocks/search1 분,/companies/{corp}10 분 - Singleflight 내장 (100 동시 → upstream 1 회), non-2xx 는 5 초 negative cache
자세한 보안: backend/docs/security.md
DB 마이그레이션 (goose v3)
- 라이브러리: pressly/goose v3 (2026-04-22 golang-migrate 에서 전환)
- 위치:
backend/cmd/server/migrations/(embed.FS 로 바이너리 내장) - 포맷: 단일 파일에
-- +goose Up마커. down 섹션 없음 (pre-launch) - 서버 시작 시
goose.UpContext자동 실행 - schema-qualified 필수:
goose.SetTableName("dartbrief.goose_db_version")명시
Admin API
AI 분석 스케줄러
bash
curl -X POST -H "X-Admin-Key: $ADMIN_KEY" https://api.dartbrief.com/api/v1/admin/scheduler/{resume|pause}
curl -H "X-Admin-Key: $ADMIN_KEY" https://api.dartbrief.com/api/v1/admin/scheduler/status공시 백필 (DART list.json)
bash
curl -X POST -H "X-Admin-Key: $ADMIN_KEY" \
"https://api.dartbrief.com/api/v1/admin/backfill?fromDate=20260301&toDate=20260331&delayMs=200"
curl -H "X-Admin-Key: $ADMIN_KEY" https://api.dartbrief.com/api/v1/admin/backfill/status종목 마스터 동기화 (corpCode.xml + company.json, KOSPI/KOSDAQ)
bash
# bootstrap: 전수 (~4분, 초기 1회), incremental: 신규만 (~수초)
curl -X POST -H "X-Admin-Key: $ADMIN_KEY" \
"https://api.dartbrief.com/api/v1/admin/stocks/sync?mode=bootstrap"
curl -H "X-Admin-Key: $ADMIN_KEY" https://api.dartbrief.com/api/v1/admin/stocks/sync/status매일 05:00 KST 에 incremental 자동 실행 (prod 만).
Railway GraphQL API
엔드포인트: https://backboard.railway.com/graphql/v2 헤더: Project-Access-Token: <token> (⚠️ Bearer 아님!) 토큰 위치: ~/.config/cloud-tokens/railway.env
Project-Access-Token 으로 가능
- 변수 조회 (
variablesquery) - 변수 upsert (
variableUpsertmutation) — 쓰기 권한 (2026-04-23 확인) - 배포 목록 (
deploymentsquery) - 배포 로그 (
deploymentLogsquery)
변수 upsert 예시
bash
source ~/.config/cloud-tokens/railway.env
cat > /tmp/mut.json <<EOF
{
"query": "mutation(\$input: VariableUpsertInput!) { variableUpsert(input: \$input) }",
"variables": {
"input": {
"projectId": "$RAILWAY_PROJECT_ID",
"environmentId": "$RAILWAY_DARTBRIEF_ENVIRONMENT_ID",
"serviceId": "$RAILWAY_DARTBRIEF_SERVICE_ID",
"name": "AI_CONCURRENCY",
"value": "10"
}
}
}
EOF
curl -sS -X POST "https://backboard.railway.com/graphql/v2" \
-H "Project-Access-Token: $RAILWAY_PROJECT_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @/tmp/mut.json변수 변경 후 Railway 가 자동 재배포 트리거.
배포 상태 조회
bash
curl -sS -X POST "https://backboard.railway.com/graphql/v2" \
-H "Project-Access-Token: $RAILWAY_PROJECT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"query\":\"query { deployments(first: 3, input: { projectId: \\\"$RAILWAY_PROJECT_ID\\\", environmentId: \\\"$RAILWAY_DARTBRIEF_ENVIRONMENT_ID\\\", serviceId: \\\"$RAILWAY_DARTBRIEF_SERVICE_ID\\\" }) { edges { node { id status createdAt } } } }\"}"상태: SUCCESS / BUILDING / DEPLOYING / CRASHED / REMOVED.
로그 조회
graphql
query { deploymentLogs(deploymentId: "...", limit: 2000) {
timestamp severity message attributes { key value }
}}Go slog 구조화 필드 (error, rceptNo 등) 는 attributes 배열로. message 는 평문만.
함정: Python urllib + os.environ
환경변수 sourcing 순서 잘못하면 빈 헤더로 호출 → HTTP 403. curl + HEREDOC 가 더 신뢰.
Bash 도구에서 Go 명령 실행
PATH 초기화되지 않아 go not found 에러. Full path 사용:
bash
/opt/homebrew/bin/go build ./...
/opt/homebrew/bin/gofmt -l .
/opt/homebrew/bin/go vet ./...작업 디렉토리도 반드시 backend/ (go.mod 위치).