# 아키텍처

## 1. 전체 흐름

```text
브라우저
  -> Apache/PHP/CodeIgniter 웹빌더
  -> MariaDB 설정·버전·작업 데이터
  -> Node Orchestrator API
  -> MariaDB Queue
  -> Node Worker
  -> Flutter CLI / Xcode / Android SDK
  -> runtime/artifacts
  -> 웹빌더에서 상태·로그·다운로드
```

## 2. 책임 분리

### PHP 웹 애플리케이션

- 사용자, 조직, 권한, 요금제·구독·결제 이력
- 앱 프로젝트 CRUD
- 앱 빌더 화면
- 설정 JSON 생성·검증
- 앱 버전 스냅샷
- 빌드·릴리스 요청
- 상태, 로그, 산출물 조회
- 스토어 연결정보 입력
- 감사 로그

### Node 오케스트레이터

- PHP 서버에서 온 요청의 HMAC 검증
- 작업 큐 등록
- 원자적 작업 선점
- Flutter 작업공간 생성
- 템플릿 복사와 설정 파일 생성
- Android/iOS 빌드 명령 실행
- 로그 스트리밍 저장
- 취소·재시도·타임아웃
- 산출물 체크섬과 메타데이터 저장
- 스토어 업로드 어댑터 실행

### Python

기본 실행에는 필수가 아닙니다. 향후 아이콘 리사이즈, 스토어 이미지 합성, 이미지 품질검사 등에 사용하도록 `scripts/generate_assets.py`를 제공합니다.

## 3. MariaDB 큐

Node 워커는 다음 패턴으로 작업을 선점합니다.

```sql
START TRANSACTION;
SELECT id
FROM build_jobs
WHERE status = 'queued'
  AND available_at <= NOW()
ORDER BY priority DESC, id ASC
LIMIT 1
FOR UPDATE SKIP LOCKED;

UPDATE build_jobs
SET status='running', locked_by=?, locked_at=NOW(), attempts=attempts+1
WHERE id=?;
COMMIT;
```

MariaDB 10.11 이상을 운영 기준으로 합니다. 현재 SQL은 MySQL 8.0에서도 호환되며, 여러 워커가 동시에 실행되어도 동일 작업을 중복 선점하지 않습니다.

## 4. 앱 설정 버전

편집 중 데이터는 `apps.definition_json`에 저장합니다. 빌드할 때 해당 JSON을 `app_versions`에 스냅샷으로 저장하여 동일 버전을 재현할 수 있게 합니다.

## 5. Flutter 생성 전략

매번 전체 Dart 코드를 임의 생성하지 않습니다.

1. `flutter create`로 표준 프로젝트 생성
2. `flutter_template/overlay`를 프로젝트에 덮어쓰기
3. 앱별 `app.json` 생성
4. 앱 이름, 패키지 ID, 권한, 버전 패치
5. `flutter pub get`, 분석, 테스트, 빌드

이 구조는 템플릿 업데이트, 플러그인 호환성 관리, 대량 앱 유지보수에 유리합니다.

## 6. 배포 토폴로지

### 단일 서버 개발 환경

- Apache + PHP-FPM 또는 mod_php
- MariaDB 10.11+
- Node 오케스트레이터
- Android Flutter SDK
- 로컬 파일 저장소

### 운영 권장

- 웹 서버와 Android 빌드 워커 분리
- iOS는 별도 Mac mini 또는 macOS CI 러너
- MariaDB 고가용성 및 백업
- 산출물은 S3 호환 스토리지
- 민감정보는 KMS/Vault
- 빌드 워커는 최소 권한 OS 사용자와 격리된 작업공간

## 릴리스 워커 잠금

릴리스 작업도 `locked_by`와 `locked_at`을 기록하고 10초마다 heartbeat를 갱신합니다. 오래된 작업은 외부 스토어 중복 업로드를 막기 위해 자동 재시도하지 않고 실패 처리합니다.


## 결제 도메인

CodeIgniter가 `billing_plans`, `organization_subscriptions`, `payment_transactions`, `payment_webhook_events`를 관리합니다. 현재 구현은 요금제 표시와 앱·월 빌드 사용량 제한까지 수행합니다. 실제 승인·취소·환불은 선택한 PG사의 서버 SDK와 서명 검증 웹훅 어댑터를 추가해야 합니다. 브라우저 결제 성공 콜백만으로 결제 상태를 `paid`로 변경하면 안 됩니다.
