# AIROUM 랜딩 페이지 기술 설계서 (v2.0 - Minimalist) ## 1. 프로젝트 목표 및 핵심 원칙 본 문서는 AIROUM 랜딩 페이지의 기술 설계를 정의합니다. v2.0 설계의 핵심 목표는 **'문의하기'라는 단 하나의 기능에 집중**하여, 가장 빠르고 안정적으로 사용자의 문의를 접수하는 것입니다. 모든 부가 기능(회원가입, 관리자 페이지 등)은 의도적으로 배제하여 복잡성을 최소화합니다. * **단일 책임 원칙 (Single Responsibility):** 이 시스템의 유일한 책임은 '문의 데이터 수신 및 저장'입니다. * **최소주의 아키텍처 (Minimalist Architecture):** 가장 필수적인 기술 요소만 사용하여 가볍고 빠른 시스템을 구축합니다. * **사용자 경험 최우선 (UX First):** 기능이 단순한 만큼, 사용자의 첫인상을 결정하는 랜딩 페이지의 UI/UX와 성능을 최우선으로 고려합니다. ## 2. 시스템 아키텍처 (Simplified Architecture) ### 2.1. 아키텍처 다이어그램 ```mermaid graph TD subgraph "사용자" A[사용자 브라우저] end subgraph "인프라 (자체 서버)" B[Nginx] --> D{Flask App} D --> E[SQLite DB] end A -- "Page Request" --> B B -- "Static Files" --> A B -- "Proxy API Request" --> D A -- "Submit Inquiry" --> D D -- "Save Data" --> E style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#ccf,stroke:#333,stroke-width:2px style D fill:#cfc,stroke:#333,stroke-width:2px style E fill:#fcf,stroke:#333,stroke-width:2px ``` ### 2.2. 아키텍처 설명 * **Nginx (웹 서버):** 모든 외부 요청의 진입점입니다. HTML, CSS, JavaScript, 이미지와 같은 정적 파일은 Nginx가 직접 처리하여 최고의 속도를 보장합니다. API 요청(`POST /api/inquiry`)만 Flask 애플리케이션으로 전달합니다. * **Flask App (백엔드):** 오직 하나의 역할, 즉 `POST /api/inquiry` 요청을 받아 유효성을 검사하고 데이터베이스에 저장하는 역할만 수행합니다. * **SQLite (데이터베이스):** 문의 내용을 저장하기 위한 단일 파일 기반 데이터베이스입니다. 별도의 설정이 필요 없어 배포가 매우 간단하며, 소규모 데이터 처리에 적합합니다. ## 3. 데이터베이스 설계 (Single Table Design) 시스템의 유일한 데이터 모델은 '문의(Inquiry)'입니다. ### 3.1. `INQUIRIES` 테이블 스키마 | 컬럼명 | 데이터 타입 | 제약 조건 | 인덱스 | 설명 | | ------------ | -------------- | ------------------------------ | ------ | --------------------- | | `id` | `INTEGER` | `PRIMARY KEY AUTOINCREMENT` | PK | 고유 식별자 | | `name` | `VARCHAR(50)` | `NOT NULL` | | 문의자 이름 | | `email` | `VARCHAR(100)` | `NOT NULL` | INDEX | 문의자 이메일 | | `phone` | `VARCHAR(20)` | `NULL` | | 문의자 연락처 (선택) | | `message` | `TEXT` | `NOT NULL` | | 문의 내용 | | `created_at` | `DATETIME` | `NOT NULL, DEFAULT CURRENT_TIMESTAMP` | | 문의 접수 일시 | **선택 이유:** `USERS`, `COURSES` 등 모든 부가 테이블을 제거하고 `INQUIRIES` 테이블만 남겨 데이터 모델을 극도로 단순화했습니다. 이는 시스템의 복잡성을 줄이고 유지보수 비용을 최소화합니다. ## 4. API 명세 (Single Endpoint Specification) 시스템에는 단 하나의 API 엔드포인트만 존재합니다. ### **문의 등록 API** * **Endpoint:** `POST /api/inquiry` * **Description:** 사용자의 문의를 시스템에 등록합니다. * **Request Body (JSON):** ```json { "name": "김에이", "email": "airoum.kim@example.com", "phone": "010-1234-5678", "message": "AI 윤리 교육에 대해 더 자세히 알고 싶습니다." } ``` * **Success Response (201 Created):** ```json { "status": "success", "message": "문의가 성공적으로 접수되었습니다." } ``` * **Error Response (400 Bad Request):** ```json { "status": "error", "message": "입력값을 확인해주세요.", "errors": { "email": "올바른 이메일 형식이 아닙니다." } } ``` ## 5. 프론트엔드 구현 전략 (UI/UX & Performance Focus) 기능이 최소화된 만큼, 랜딩 페이지 자체의 완성도가 프로젝트의 성패를 좌우합니다. ### 5.1. 핵심 목표 * **빠른 로딩 속도:** 사용자가 페이지를 이탈하지 않도록 2초 이내에 주요 콘텐츠가 렌더링되는 것을 목표로 합니다. * **명확한 CTA (Call to Action):** 사용자가 '문의하기' 버튼을 쉽게 찾고 클릭할 수 있도록 디자인합니다. * **직관적인 UI/UX:** 불필요한 정보를 제거하고, AIROUM의 핵심 가치와 교육 프로그램을 명확하게 전달합니다. ### 5.2. 성능 최적화 전략 * **이미지 최적화:** 모든 이미지는 WebP 포맷으로 변환하고, `lazy loading`을 적용하여 초기 로딩 속도를 개선합니다. * **CSS/JS 최소화:** 순수 CSS와 최소한의 Vanilla JS를 사용합니다. CSS는 Critical CSS를 인라인으로 삽입하고, 나머지는 비동기적으로 로드합니다. JavaScript는 `defer` 속성을 사용하여 HTML 파싱을 방해하지 않도록 합니다. * **브라우저 캐싱 활용:** Nginx 설정을 통해 정적 파일에 대해 긴 만료 시간(long expiry dates)을 설정하여 반복 방문 시 로딩 속도를 높입니다. ### 5.3. '문의하기' 폼 UX 전략 * **입력 필드 최소화:** `이름`, `이메일`, `연락처(선택)`, `문의 내용` 필드를 배치하여 사용자 피로도를 줄입니다. * **실시간 유효성 검사:** 이메일 형식 등을 실시간으로 검사하여 사용자에게 즉각적인 피드백을 제공합니다. * **명확한 피드백:** '제출' 버튼 클릭 시, 로딩 상태를 명확히 보여주고, 성공 또는 실패 메시지를 모달이나 토스트 메시지로 명확하게 표시합니다. ## 6. 백엔드 및 인프라 설계 (Simplified) ### 6.1. 디렉토리 구조 `tech-stack.md`에 제안된 가장 단순한 구조를 채택합니다. ``` airoum-landing/ ├── app.py # 단일 파일 Flask 애플리케이션 ├── requirements.txt # 의존성 (Flask, Gunicorn) ├── templates/ │ └── index.html # 메인 랜딩 페이지 └── static/ └── css/ └── style.css # 스타일시트 ``` ### 6.2. 배포 전략 * **인프라:** 자체 서버 + Nginx + Gunicorn * **프로세스:** 1. GitHub에 코드를 Push합니다. 2. 서버에서 Git Pull을 실행합니다. 3. `pip install -r requirements.txt`로 의존성을 업데이트합니다. 4. Gunicorn 서비스를 재시작하여 변경 사항을 적용합니다. * (주: CI/CD 파이프라인은 초기 단계에서 오버헤드가 될 수 있으므로, 수동 배포로 단순화합니다.) ## 7. 비기능적 요구사항 (Minimal) * **로깅:** Gunicorn과 Nginx의 기본 access/error 로그를 파일로 기록합니다. Flask 애플리케이션에서는 에러 발생 시에만 `stderr`로 로그를 출력합니다. * **에러 핸들링:** * `404 Not Found`: Nginx 단에서 처리하거나, Flask에서 간단한 "페이지 없음" 메시지를 반환합니다. * `500 Internal Server Error`: "서버 오류" 메시지를 반환하고, 상세 내용은 로그에만 기록합니다.