# Kavenix Social

Instagram과 Threads 계정을 브랜드별로 연결하고 게시물을 예약하는 자체 호스팅용 Next.js 애플리케이션입니다. 데이터는 서버의 SQLite 파일에 저장되며, 별도 스케줄러 컨테이너가 1분마다 발행 예정 게시물을 처리합니다.

## 서버 배포

Node.js 22와 Docker Compose가 설치된 서버에서 실행합니다.

```bash
git clone --branch live https://github.com/k-ssoft/autoke.git
cd autoke
cp .env.example .env
# .env의 모든 비밀값과 공개 URL을 설정
docker compose up -d --build
```

이후 자동 배포에서는 다음 명령으로 최신 `live` 브랜치를 반영할 수 있습니다.

```bash
git pull --ff-only origin live
docker compose up -d --build --remove-orphans
```

기본 포트는 `3000`입니다. `APP_PORT`로 호스트 포트를 바꾸고, 실제 운영에서는 Nginx 또는 Caddy에서 HTTPS 리버스 프록시를 연결하세요. 상태 확인 주소는 `/api/health`입니다.

## 환경 변수

- `APP_USERNAME`, `APP_PASSWORD`: 웹과 일반 API에 적용되는 HTTP Basic 로그인
- `DEFAULT_OWNER_ID`: 저장 데이터의 소유자 식별자
- `PUBLIC_APP_URL`: 외부에서 접속하는 HTTPS 주소(마지막 `/` 제외)
- `DATABASE_PATH`: SQLite 경로. Docker에서는 `/app/data/kavenix.sqlite`로 고정됩니다.
- `TOKEN_ENCRYPTION_KEY`: Meta 액세스 토큰 암호화 키
- `SCHEDULER_SECRET`: 앱과 예약 발행 워커 사이의 인증 키
- `INSTAGRAM_APP_ID`, `INSTAGRAM_APP_SECRET`: Meta 앱의 Instagram 자격 증명
- `THREADS_APP_ID`, `THREADS_APP_SECRET`: Meta 앱의 Threads 자격 증명

긴 비밀값은 서버에서 각각 생성하세요.

```bash
openssl rand -hex 32
```

## Meta 앱 설정

Meta for Developers 앱에 다음 OAuth 리디렉션 URI를 등록합니다.

```text
https://내-도메인/api/oauth/meta/callback
```

애플리케이션에서 사용하는 권한은 다음과 같습니다.

- Instagram: `instagram_business_basic`, `instagram_business_content_publish`
- Threads: `threads_basic`, `threads_content_publish`

Instagram 게시에는 Meta 서버가 접근할 수 있는 공개 이미지 또는 영상 URL이 필요합니다. 앱이 개발 모드일 때는 앱 역할이 부여된 계정만 연결할 수 있습니다.

## 데이터와 백업

Compose의 `kavenix_data` 볼륨에 SQLite 데이터가 유지되므로 컨테이너를 다시 빌드해도 게시물과 계정 정보가 보존됩니다. 백업 전에는 앱과 스케줄러를 잠시 중지한 뒤 볼륨의 `kavenix.sqlite`, `kavenix.sqlite-wal`, `kavenix.sqlite-shm` 파일을 함께 복사하세요.

## 로컬 개발

```bash
npm ci
cp .env.example .env.local
npm run dev
```

개발 모드에서는 `APP_USERNAME`/`APP_PASSWORD`가 없어도 접속할 수 있습니다. 운영 모드에서는 두 값이 없으면 앱이 `503`을 반환합니다.

검증 명령:

```bash
npm test
npm run lint
npm run build
```
