# 실행 / 배포 명령어

> Docker Compose 기반 로컬·운영 오케스트레이션 명령어 모음.
> `.env.development` / `.env.production` 는 커밋된 `.env.*.example` 를 복사해 생성한다.
> (`.gitignore` 는 `.env.*` 를 무시하되 `.env.*.example` 만 추적한다.)

## 개발 환경

```bash
# 코드만 수정했을 때 (의존성 변경 없음)
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.development up -d

# 의존성 변경 시에만 --build
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.development up -d --build

# 로그 확인 (예: backend)
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.development logs -f backend
```

## 운영 환경

```bash
# 운영 환경 배포
sudo docker compose --env-file .env.production up -d --build

# 로그 확인
sudo docker compose --env-file .env.production logs -f backend
```

## 데이터베이스 마이그레이션 (TypeORM)

> 스키마 변경은 **마이그레이션**으로 관리한다. (SSOT: `backend/src/migrations/`, CLI 설정: `backend/src/data-source.ts`)

### 동작 방식

| 환경 | 동작 |
| ---- | ---- |
| 개발 | `synchronize: true` — 엔티티 변경이 DB에 **자동 반영**(마이그레이션 불필요) |
| 운영 | `synchronize: false` + `migrationsRun: true` — 컨테이너 **기동(부팅) 시** `dist/migrations` 의 미적용 마이그레이션을 **자동 실행** |

- **빌드만으로는 실행되지 않는다.** `up`(기동)해야 적용된다. 이미 적용된 마이그레이션은 `migrations` 테이블 기록으로 건너뛴다(멱등).
- 운영 배포(`sudo docker compose --env-file .env.production up -d --build`)는 빌드 시 마이그레이션을 이미지에 포함 → 기동 시 자동 적용 → **빈 운영 DB에 스키마가 자동 생성**된다. 별도 명령 불필요.
- ⚠️ **전제: 운영 DB가 비어 있어야 한다.** 이미 테이블이 있으면 `already exists` 로 부팅이 실패한다. (데이터 없으면 DB 재생성 후 배포, 데이터 보존이 필요하면 아래 *베이스라인* 참조)

### 스크립트 (backend/ 에서 실행 — DB 접속 env 필요)

```bash
cd backend
npm run migration:generate -- ./src/migrations/<이름>   # 엔티티 변경분으로 새 마이그레이션 생성
npm run migration:create   -- ./src/migrations/<이름>   # 빈 마이그레이션 파일(수동 SQL 작성용)
npm run migration:run                                   # 미적용 마이그레이션 실행
npm run migration:revert                                # 마지막 마이그레이션 1건 되돌리기
```

DB 접속값은 환경변수로 주입한다. 로컬에서는 dev DB가 호스트에 노출되어 있으므로(`DB_PORT`, `.env.development`) 그대로 사용:

```bash
# Linux/macOS (bash)
DB_HOST=localhost DB_PORT=<DB_PORT> DB_USER=<DB_USER> DB_PASSWORD=<DB_PASSWORD> DB_NAME=<DB_NAME> npm run migration:run
```

```powershell
# Windows PowerShell
$env:DB_HOST='localhost'; $env:DB_PORT='<DB_PORT>'; $env:DB_USER='<DB_USER>'; $env:DB_PASSWORD='<DB_PASSWORD>'; $env:DB_NAME='<DB_NAME>'; npm run migration:run
```

### 새 마이그레이션 만들기 (스키마 변경 시)

개발 DB는 `synchronize` 로 이미 최신 엔티티 상태라 **dev DB를 직접 diff 하면 변경분이 안 잡힌다.**
"기존 마이그레이션까지 적용된 임시 DB" 대비 차이만 추출한다(실 데이터 무손상):

```bash
DB=comrelay-db  # DB 컨테이너명, USER=<DB_USER>

# 1) 임시 빈 DB 생성
docker exec $DB psql -U <DB_USER> -d <DB_NAME> -c "CREATE DATABASE comrelay_miggen OWNER <DB_USER>;"

# 2) 임시 DB에 기존 마이그레이션 적용(= 변경 전 기준 스키마)
DB_HOST=localhost DB_PORT=<DB_PORT> DB_USER=<DB_USER> DB_PASSWORD=<DB_PASSWORD> DB_NAME=comrelay_miggen npm run migration:run

# 3) 엔티티 변경분만 새 마이그레이션으로 추출
DB_HOST=localhost DB_PORT=<DB_PORT> DB_USER=<DB_USER> DB_PASSWORD=<DB_PASSWORD> DB_NAME=comrelay_miggen npm run migration:generate -- ./src/migrations/<이름>

# 4) 생성된 파일 리뷰 후 임시 DB 삭제
docker exec $DB psql -U <DB_USER> -d <DB_NAME> -c "DROP DATABASE comrelay_miggen;"
```

생성된 마이그레이션을 커밋·푸시하면 다음 운영 배포의 기동 시 자동 적용된다.

### 기존 운영 DB 베이스라인 (이미 스키마가 있고 데이터 보존이 필요할 때)

운영 DB가 이미 동일 스키마를 갖고 있다면, 초기 마이그레이션을 "이미 적용됨"으로 기록해 재실행(=충돌)을 막는다.

```sql
-- migrations 추적 테이블이 없으면 생성(최초 1회)
CREATE TABLE IF NOT EXISTS "migrations" (
  "id" SERIAL PRIMARY KEY,
  "timestamp" bigint NOT NULL,
  "name" character varying NOT NULL
);
-- 초기 마이그레이션을 적용 완료로 표시(파일명의 타임스탬프·클래스명과 일치시킬 것)
INSERT INTO "migrations" ("timestamp", "name")
VALUES (1782060613058, 'CreateInitialSchema1782060613058');
```

이후 `up` 하면 기록된 마이그레이션은 건너뛰고, 이후 추가된 마이그레이션만 적용된다.

## 외부 노출 (선택)

```bash
# ngrok 으로 백엔드 포트(3000) 임시 노출 — <YOUR_DOMAIN> 을 본인 도메인으로 교체
ngrok http --domain=<YOUR_DOMAIN>.ngrok.app 3000
```
