# 🏆 WSC2026 Test Project - Web Technologies
## **Module D: AI-Powered Global City Explorer (Full-stack Integration)**

### **1. 과제 개요 (Project Overview)**
당신은 'Global City Explorer' 플랫폼의 풀스택 개발자입니다. 사내 AI 엔지니어링 팀이 로컬 AI 모델(Ollama)을 활용하여 도시의 텍스트 정보와 이미지의 키워드를 분석해 주는 **'AI 마이크로서비스(AI Middleware Server)'**를 개발하여 Starter Kit으로 제공했습니다.

당신의 임무는 제공된 AI 서버를 구동하고 API를 명확히 분석한 뒤, 관리자가 도시 정보를 등록, 조회, **수정 및 삭제(CRUD)** 할 수 있는 고도화된 **프론트엔드(UI)**와 엄격한 유효성 검사를 통과한 데이터만 안전하게 처리하는 **백엔드(DB Storage)**를 완벽하게 구축하는 것입니다.

---

### **2. 인프라 구축 방법 (Infrastructure Setup)**
과제를 수행하기 전, 로컬 PC가 AI 모델과 Node.js 서버를 구동하기 위한 요구사항을 충족하는지 확인하고 환경을 세팅해야 합니다.

#### **2.1. 하드웨어 권장 사양 (Hardware Requirements)**
로컬 환경에서 두 개의 AI 모델을 원활하게 구동하기 위해 아래 사양을 권장합니다.
* **Memory (RAM):** 최소 8GB / 권장 16GB 이상 (두 모델이 메모리에 적재되어야 하므로 RAM 용량이 중요합니다.)
* **GPU:** VRAM 6GB 이상의 NVIDIA GPU 권장 (CPU로도 구동은 가능하나, 이미지 분석 시 처리 시간이 다소 지연될 수 있습니다.)
* **Storage:** 최소 10GB 이상의 여유 공간 (HDD보다 SSD 사용을 강력히 권장합니다.)

#### **2.2. Node.js 확인 및 설치**
백엔드 미들웨어를 실행하기 위해 Node.js 환경이 필요합니다.
1. 터미널(또는 명령 프롬프트)을 열고 `node -v`를 입력하여 설치 여부를 확인합니다. (`v18.x.x` 이상의 버전이 표출되면 정상입니다.)
2. **미설치 시:** [Node.js 공식 홈페이지(nodejs.org)](https://nodejs.org/)에 접속하여 LTS(Long Term Support) 버전을 다운로드하고 설치하십시오.

#### **2.3. Ollama (AI 구동 엔진) 확인 및 설치**
1. 터미널을 열고 `ollama -v`를 입력하여 버전 정보가 나오는지 확인합니다.
2. **미설치 시:** Windows의 경우 **PowerShell**을 관리자 권한으로 실행한 뒤, 아래 명령어를 붙여넣어 설치를 진행하십시오.
   `irm https://ollama.com/install.ps1 | iex`
   *(설치가 완료되면 터미널을 재시작해야 환경변수가 적용됩니다.)*

#### **2.4. AI 모델 다운로드 및 특징**
터미널을 열고 아래 명령어를 순차적으로 실행하여 본 과제에 사용할 2개의 AI 모델을 다운로드합니다. (`ollama list` 명령어로 설치 완료 확인)

* **텍스트 처리 모델 다운로드:** `ollama pull phi3`
  * **[모델 특징]:** Microsoft에서 개발한 초경량 언어 모델(SLM)입니다. 가볍고 빠르면서도 훌륭한 문장 생성 및 논리적 추론 능력을 갖추고 있어 도시의 소개글을 작성하는 데 사용됩니다.
* **비전(이미지) 처리 모델 다운로드:** `ollama pull llava`
  * **[모델 특징]:** 텍스트뿐만 아니라 '눈(Vision)'을 가진 멀티모달(Multimodal) AI입니다. 사용자가 업로드한 명소 이미지를 분석하여 그 안의 객체나 풍경을 설명하고 핵심 키워드를 추출하는 역할을 합니다.

---

### **3. AI Middleware Server 설치 및 실행**
제공된 Starter Kit 안에는 AI 엔지니어링 팀이 작성한 `ai-api` 폴더가 있습니다. 이 폴더 안에는 `server.js`와 `package.json`이 포함되어 있습니다. **(🚨 주의: 이 서버의 코드는 절대 수정하지 마십시오.)**

1. 터미널을 열고 제공된 `ai-api` 폴더 경로로 이동합니다.
2. 아래 명령어를 입력하여 필수 패키지를 설치합니다.
   `npm install`
3. 설치가 완료되면 서버를 실행합니다.
   `npm start`
4. 터미널에 `🚀 AI Middleware Server running on http://localhost:3000` 메시지가 출력되면 서버가 정상 작동 중인 것입니다. 이 터미널은 과제가 끝날 때까지 닫지 마십시오.

---

### **4. HOPPSCOTCH를 활용한 API 테스트**
본격적인 개발에 앞서, Hoppscotch(또는 Postman)를 이용하여 제공된 두 개의 API가 어떤 형태의 데이터를 반환하는지 반드시 테스트하십시오.

* **API 1: 텍스트 정보 생성 (`POST /api/generate-text`)**
  * Body (`application/json`): `{"city_name": "Paris", "country": "France"}`
  ![텍스트 정보 생성 테스트 화면](generate-text.png)

* **API 2: 이미지 통합 분석 (`POST /api/analyze-image`)**
  * Body (`multipart/form-data`): `city_name` (Text), `country` (Text), `image` (File 형식으로 이미지 업로드)
  ![이미지 통합 분석 테스트 화면](analyze-image.png)

---

### **5. 선수들이 만들어야 할 과제 (Tasks to Complete)**

#### **5.1. Front-end 요구사항 (Advanced UI/UX)**
관리자가 사용할 `index.html` (또는 SPA 프레임워크) 화면을 구축하십시오. 화면은 크게 **'정보 등록/수정 영역'**과 **'등록된 목록 조회 영역'**으로 나뉘어야 합니다.

* **[정보 등록 및 수정 영역 (Form Area)]**
  * **이미지 미리보기 (Image Preview):** `<input type="file">`을 통해 이미지를 선택하면, 서버에 전송하기 전 화면에 즉시 이미지 썸네일이 미리보기로 표시되어야 합니다.
  * **AI 데이터 연동:** 도시명/국가명 입력 후 AI 텍스트 생성 API를 호출하고, 사진 등록 후 AI 비전 분석 API를 호출하여 반환된 데이터를 폼(Form)에 채우십시오.
  * **완벽한 비동기 상태 관리 (Form Lock & Loading):** 무거운 AI 분석 작업(10~30초 소요)이 진행되는 동안 사용자의 중복 클릭 및 오류를 방지하기 위해 **모든 입력 폼과 버튼을 비활성화(Disabled)** 처리해야 합니다. 또한 작업 진행 상태를 명확히 알 수 있는 로딩 UI(스피너 애니메이션, 프로그레스 바 등)를 화면에 표시하여 사용자 경험을 최적화하십시오.
  * **정보 수정 및 AI 다시 불러오기 (Re-fetch):**
    * 목록에서 특정 도시의 '수정' 버튼을 누르면 해당 도시의 데이터가 폼에 채워져야 합니다.
    * 수정 폼에는 **'AI에서 모든 정보 다시 불러오기'** 버튼이 있어야 합니다. 이 버튼을 클릭하면 현재 폼에 있는 도시, 국가, 이미지 데이터를 바탕으로 AI API 두 개를 다시 호출하고, 폼의 텍스트 값들(설명, 키워드 등)을 완전히 새로운 AI 응답으로 교체해야 합니다. 이후 사용자가 '최종 수정' 버튼을 누르면 업데이트됩니다.

* **[목록 조회 및 필터링 영역 (List & Interactive Filtering)]**
  * 최종 저장된 글로벌 도시 정보들을 DB에서 불러와 리스트(List) 또는 카드(Card) 갤러리 형태로 렌더링하십시오. 각 아이템에는 **'수정(Edit)'** 및 **'삭제(Delete)'** 버튼이 포함되어야 합니다.
  * **데이터 삭제 (Delete):** '삭제' 버튼 클릭 시, 실수로 삭제하는 것을 방지하기 위해 브라우저의 기본 `confirm` 창이나 커스텀 모달(Modal) 창으로 확인을 거친 후 DB에서 데이터를 삭제하고 목록을 즉시 갱신하십시오.
  * **해시태그 필터링:** 목록에 표시된 특정 키워드(예: `#에펠탑`)를 클릭하면, 전체 목록이 즉시 필터링되어 해당 키워드를 보유한 도시 카드들만 화면에 노출되어야 합니다.

#### **5.2. Back-end 요구사항 (DB 및 Server-side Validation)**
데이터의 생성(Create), 조회(Read), 수정(Update), 삭제(Delete)를 완벽하게 처리하는 본인만의 백엔드 서버와 데이터베이스를 구축하십시오.

* **DB 스키마:** MySQL/MariaDB에 `city_contents` 테이블을 직접 설계하여 생성하십시오.
* **API 구현 (CRUD):**
  1. **GET (조회):** DB에 저장된 전체 데이터를 JSON 형태로 반환합니다.
  2. **POST (생성):** 새로운 데이터를 DB에 `INSERT` 하고 이미지를 업로드 폴더에 물리적으로 저장합니다.
  3. **PUT 또는 PATCH (수정):** 특정 ID의 데이터를 수정합니다. (새로운 이미지가 전송되었다면 기존 이미지 파일을 교체하거나 새로운 경로를 업데이트해야 합니다.)
  4. **DELETE (삭제):** 특정 ID의 데이터를 DB에서 삭제합니다.
* **저장/수정 로직의 보안 검사 (Server-side Validation):** POST 및 PUT/PATCH 요청 시, 아래의 유효성 검사를 반드시 통과한 데이터만 서버에 저장해야 합니다.
  1. **파일 용량 제한:** 업로드된 이미지 파일이 **5MB**를 초과할 경우 처리를 거부하고 HTTP 상태 코드 400(Bad Request)과 함께 에러 메시지를 반환해야 합니다.
  2. **확장자 검사:** 허용된 이미지 포맷(`.jpg`, `.jpeg`, `.png`, `.webp`)이 아닐 경우 저장을 거부해야 합니다.

#### **5.3. 기타 요구사항 (함정 및 평가 포인트)**
* **데이터 파싱(Parsing):** 비전 API의 응답 중 `keywords`는 순수 배열이 아닌 **JSON 포맷으로 감싸진 텍스트 문자열(Stringified Array)**로 반환됩니다. 이를 화면에 깔끔한 태그로 렌더링하기 위해 프론트엔드에서 반드시 적절한 파싱(`JSON.parse`) 과정을 거쳐야 합니다.
* **예외 처리:** 백엔드 유효성 검사 실패 시(예: 용량 초과) 프론트엔드 프로그램이 멈추지 않고, 캐치(Catch)하여 사용자에게 `alert` 또는 모달 창으로 명확히 안내해야 합니다.

---

### **6. 선수 작업 안내 (Competitor Workspace Guide)**

* **AI Middleware 실행 위치:** 제공된 `ai-api` 폴더. (터미널 1에서 실행 후 방치)
* **선수 작업 위치:** 본인의 웹 서버 루트 폴더(예: `http://localhost/module-d/`).
* **평가 준비:** 과제 종료 시점에는 AI Middleware 터미널과 선수가 작성한 웹 서버가 모두 실행 중이어야 합니다. 심사위원(Expert)은 브라우저를 통해 접속하여 아래 사이클을 순차적으로 테스트할 것입니다.
  1. 5MB 초과 이미지 업로드 시도 (에러 처리 확인)
  2. 정상 데이터 생성 (Create)
  3. 목록 조회 및 해시태그 클릭 필터링 (Read & Filter)
  4. **'수정' 버튼 클릭 후 'AI 다시 불러오기'를 통한 내용 갱신 및 저장 (Update)**
  5. **'삭제' 버튼 클릭을 통한 데이터 완전 삭제 (Delete)**

---

### **7. Appendix: 테스트용 제공 데이터 (Sample Data)**
테스트 및 최종 시연을 위해 아래의 도시/국가 목록을 활용하십시오. **과제 테스트용 명소 이미지는 제공된 Starter Kit 내의 `sample-images` 폴더에 준비되어 있습니다.** (특히 5MB가 넘는 고해상도 이미지를 하나 준비하여 백엔드 방어 로직을 테스트하십시오.)

| 도시명 (City) | 국가명 (Country) | 대표 명소 |
| :--- | :--- | :--- |
| **Paris** | France | 에펠탑, 루브르 박물관 |
| **Seoul** | South Korea | 경복궁, N서울타워 |
| **Tokyo** | Japan | 도쿄 타워, 시부야 교차로 |
| **New York** | USA | 자유의 여신상, 타임스퀘어 |
| **Rome** | Italy | 콜로세움, 트레비 분수 |
| **Sydney** | Australia | 오페라 하우스, 하버 브릿지 |
| **Cairo** | Egypt | 기자 피라미드, 스핑크스 |
| **London** | UK | 빅 벤, 런던 아이 |

---

### **8. Mark Summary (채점 요약표 - Total 25 Marks)**
이 표는 평가 카테고리별 배점 요약입니다. 세부 채점 기준(Marking Scheme)은 별도로 제공됩니다.

| Category | Description | Max Marks |
| :--- | :--- | :---: |
| **A. Front-end UI & UX** | UI 구성, 비동기 상태 관리(로딩/잠금), 데이터 바인딩 및 파싱 처리 | 7 |
| **B. Data Interaction** | 데이터 목록 렌더링 및 해시태그 기반 필터링 기능 | 5 |
| **C. Back-end CRUD API** | 데이터베이스 및 파일 시스템 기반의 생성, 조회, 수정(AI 다시 불러오기 포함), 삭제 기능 | 8 |
| **D. Security & Validation**| 서버 측 파일 용량 및 확장자 검사, 클라이언트 측 예외 처리 | 5 |
| **Total Marks** | | **25** |