# ๐Ÿ”— ์†Œ์Šค ๋งคํ•‘ ๋ฐ ํ˜ธ์ถœ ๊ด€๊ณ„ (v13.4) ๋ณธ ๋ฌธ์„œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐฑ์—”๋“œ API, ๊ทธ๋ฆฌ๊ณ  ๋‚ด๋ถ€ ํ•จ์ˆ˜ ๊ฐ„์˜ ํ˜ธ์ถœ ๊ด€๊ณ„์™€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. ## ๐Ÿ“ฑ 1. ํ”„๋ก ํŠธ์—”๋“œ ๋ชจ๋“ˆ๊ฐ„ ๊ด€๊ณ„ | ๋ชจ๋“ˆ (Component) | ๊ธฐ๋Šฅ ์„ค๋ช… | ์ฃผ์š” ํ˜ธ์ถœ (Callee) | | :--- | :--- | :--- | | `app.js` | **Orchestrator** | `Visualizer`, `DrawerManager`, `ModalManager`, `API` | | `Visualizer.js` | **Nebula Engine** | `D3.js`, `ModalManager.open()`, `AppService` | | `DrawerManager.js` | **Explorer** | `AppService.filterMemos()`, `ModalManager` | | `ModalManager.js` | **Viewer** | `utils.parseInternalLinks()`, `utils.fixImagePaths()` | | `ComposerManager.js` | **Editor** | `API.saveMemo()`, `AttachmentBox` | --- ## โš™๏ธ 2. ๋ฐฑ์—”๋“œ ํ•ต์‹ฌ ํ•จ์ˆ˜ ๋งคํ•‘ ### 2.1 ๋ณด์•ˆ ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ | ํ•จ์ˆ˜๋ช… | ๋ชจ๋“ˆ | ์—ญํ•  | ํ˜ธ์ถœ์ž | | :--- | :--- | :--- | :--- | | `decrypt_file` | `app/security.py` | ์ฒจ๋ถ€ํŒŒ์ผ ๋ฌผ๋ฆฌ ๋ณตํ˜ธํ™” | `file.py:download_file` | | `extract_links` | `app/utils.py` | `[[#ID]]` ํŒจํ„ด ์ถ”์ถœ | `memo.py:create/update` | ### 2.2 ์šด์˜ ๋„๊ตฌ (Ops) | ํŒŒ์ผ๋ช… | ์—ญํ•  | ์ฃผ์š” ๋กœ์ง | | :--- | :--- | :--- | | `deploy.py` | **์ •๋ฐ€ ๋ฐฐํฌ** | SSH/SFTP ๊ธฐ๋ฐ˜ Surgical Cleanup & Upload | | `backup.py` | **๋ฐฑ์—…** | ํ•ต์‹ฌ ์ž์‚ฐ(.env, DB, Uploads) Tarball ์ƒ์„ฑ | --- ## ๐ŸŒ 3. ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ํ†ต์‹  ํŒŒ๋ผ๋ฏธํ„ฐ (API Flow) ### 3.1 `GET /api/download/` (๋ณด์•ˆ ํ•˜ํ–ฅ ๋งํฌ) - **Caller**: `ModalManager.js` (Inline Images) or `AttachmentBox.js` - **Security**: `session['logged_in']` ํ™•์ธ -> `is_encrypted` ์ƒํƒœ์— ๋”ฐ๋ฅธ ์ ‘๊ทผ ์ œ์–ด. - **Header**: ์ด๋ฏธ์ง€์ธ ๊ฒฝ์šฐ `Content-Disposition: inline`. ### 3.2 `PUT /api/memos/` (์ˆ˜์ • ๋ฐ ๋ณด์•ˆ ์ „์ด) - **Status Change**: ์•”ํ˜ธํ™” ํ•ด์ œ ์ €์žฅ ์‹œ `is_encrypted: 0`์œผ๋กœ DB ์ƒํƒœ ์—…๋ฐ์ดํŠธ. - **Process**: `memo.py:update_memo`์—์„œ `password` ์œ ๋ฌด์— ๋”ฐ๋ฅธ Re-encryption ์ˆ˜ํ–‰.