# ๐Ÿ“Œ ํ•€๋…ธํŠธ (Pinnote) ์–ด๋–ค ์›น์‚ฌ์ดํŠธ์—๋“  **์Šคํฌ๋ฆฝํŠธ ํ•œ ์ค„**์„ ๋ถ™์ด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ํ™”๋ฉด ์š”์†Œ์— ํ•€์„ ๊ฝ‚์•„ ์˜๊ฒฌ์„ ๋‚จ๊ธฐ๊ณ , ์—ฌ๋Ÿฌ ์‚ฌ์ดํŠธ์˜ ์˜๊ฒฌ์ด ํ•œ๊ณณ์— ๋ชจ์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž(์‚ฌ๋žŒ ๋˜๋Š” AI)๋Š” **์–ด๋А ์‚ฌ์ดํŠธยทํ™”๋ฉดยท์š”์†Œ**์— ๋Œ€ํ•œ ์˜๊ฒฌ์ธ์ง€ ์ •ํ™•ํžˆ ๋ณด๊ณ  ๊ณ ์นฉ๋‹ˆ๋‹ค. ๊ณ ์นœ ๋’ค์—๋Š” ๊ฑด๋งˆ๋‹ค **์™„๋ฃŒ ์‘๋‹ต**์„ ๋‚จ๊ธฐ๊ณ , ์˜๊ฒฌ์„ ๋‚จ๊ธด ์‚ฌ๋žŒ์ด ํ™•์ธํ•˜๊ฑฐ๋‚˜ ๋‹ค์‹œ ์—ฝ๋‹ˆ๋‹ค. - ๊ด€๋ฆฌ ํ™”๋ฉด: https://pinnote.itemview.co.kr/admin/ - ๋ฐ๋ชจ: https://pinnote.itemview.co.kr/demo/?pinnote=1 (์ด๋ฆ„๋งŒ ๋ฐ”๋€ ๋ฒ„์ „ `?v=2`, ์š”์†Œ๊ฐ€ ์‚ฌ๋ผ์ง„ ๋ฒ„์ „ `?v=3`) - ๋ฌธ์„œ: https://pinnote.itemview.co.kr/docs/ (๋ถ™์ด๊ธฐ ยท API ยท ์„ค๊ณ„). **๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ๋ถ™์ผ ๋•Œ๋Š” [docs/INSTALL.md](docs/INSTALL.md) ํ•œ ์žฅ๋งŒ ๋ณด๋ฉด ๋œ๋‹ค.** ## ์„ค์น˜ ํ•œ ์ค„ ```html ``` ์„ ํƒ ์†์„ฑ | ์†์„ฑ | ๋œป | |---|---| | `data-version="1.4.2"` | ์•ฑ ๋ฒ„์ „(์˜๊ฒฌ์— ํ•จ๊ป˜ ์ €์žฅ) | | `data-env="staging"` | ํ™˜๊ฒฝ | | `data-mode="toggle"` | `toggle`(๊ธฐ๋ณธ, ๐Ÿ“Œ ๋ฒ„ํŠผ์œผ๋กœ ์ผœ๊ธฐ) ยท `always`(ํ•ญ์ƒ ์ผœ์ง) ยท `off` | | `data-capture="off"` | ์š”์†Œ ์ฃผ๋ณ€ ์บก์ฒ˜ ๋„๊ธฐ | | `data-errors="off"` | ์ตœ๊ทผ JS ์˜ค๋ฅ˜ ์ˆ˜์ง‘ ๋„๊ธฐ | | `data-lang="ko"` | ์–ธ์–ด(์ง€๊ธˆ์€ ํ•œ๊ตญ์–ด๋งŒ) | | `data-position="left"` | ๐Ÿ“Œ ๋ฒ„ํŠผ์„ ์™ผ์ชฝ์— ๋‘”๋‹ค(๊ธฐ๋ณธ `right`) | | `data-offset-bottom="72"` | ๐Ÿ“Œ ๋ฒ„ํŠผ์„ ๋ฐ”๋‹ฅ์—์„œ ์ด๋งŒํผ(px) ์˜ฌ๋ฆฐ๋‹ค. ํ•˜๋‹จ ๊ณ ์ • ๋ฒ„ํŠผยทํƒญ๋ฐ”๊ฐ€ ์žˆ๋Š” ์‚ฌ์ดํŠธ์šฉ | | `data-offset-x="16"` | ๐Ÿ“Œ ๋ฒ„ํŠผ๊ณผ ํ™”๋ฉด ์˜† ๊ฐ€์žฅ์ž๋ฆฌ ์‚ฌ์ด(px) | | `data-name="ํ™๊ธธ๋™"` | ์˜๊ฒฌ ์ฐฝ ์ด๋ฆ„ ์นธ์˜ ๊ธฐ๋ณธ๊ฐ’(์ €์žฅ๋œ ์ด๋ฆ„์ด ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ์ด ์šฐ์„ ). ํ‘œ์‹œ์šฉ ์ด๋ฆ„๋งŒ ๋„ฃ๋Š”๋‹ค | - ์‚ฌ์ดํŠธ CSS์˜ `:root`์— `--pinnote-offset-bottom: 72px`๋ฅผ ๋‘์–ด๋„ ๋œ๋‹ค(์†์„ฑยท`setPosition`์ด ์šฐ์„ ). - ์ฃผ์†Œ์— `?pinnote=1`์„ ๋ถ™์ด๋ฉด ์˜๊ฒฌ ๋ชจ๋“œ๊ฐ€ ์ผœ์ง‘๋‹ˆ๋‹ค(`?pinnote=0`์€ ๋„๊ธฐ). - **์‚ฌ์ดํŠธ์— Content-Security-Policy๊ฐ€ ์žˆ์œผ๋ฉด** ๋‹ค์Œ ํ•ญ๋ชฉ์— `https://pinnote.itemview.co.kr`์„ ๋”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - `script-src`, `connect-src`: ํ•„์ˆ˜ - `img-src`: ๋‹ค์‹œ ์—ฐ๊ฒฐ ์ธ๋„ค์ผ์šฉ - ์‚ฌ์ดํŠธ ์š”์†Œ์— `data-ui="order.submit"` ๊ฐ™์€ ์•ˆ์ • ์ด๋ฆ„์„ ๋ถ™์ด๋ฉด ์š”์†Œ๋ฅผ ๊ฐ€์žฅ ์ •ํ™•ํžˆ ๋‹ค์‹œ ์ฐพ์Šต๋‹ˆ๋‹ค. - ๊ฐ€๋ฆด ์˜์—ญ์—๋Š” `data-pinnote-mask` ๋˜๋Š” `.pn-mask`๋ฅผ, ํ•€์„ ๋‹ฌ์ง€ ์•Š์„ ์˜์—ญ์—๋Š” `data-pinnote-ignore`๋ฅผ ๋ถ™์ž…๋‹ˆ๋‹ค. ### ์‚ฌ์ดํŠธ ์ฝ”๋“œ์—์„œ ์“ฐ๊ธฐ ```js Pinnote.setContext({ screen: 'checkout', journey_id: 'J123' }); // ์˜๊ฒฌ์— ํ•จ๊ป˜ ์ €์žฅ Pinnote.setName('ํ™๊ธธ๋™'); // ์ด๋ฆ„ ์นธ ๊ธฐ๋ณธ๊ฐ’ (''์ด๋ฉด ์ง€์šฐ๊ธฐ, ์ฐฝ์ด ์—ด๋ ค ์žˆ์œผ๋ฉด ๋ฐ”๋กœ ๋ฐ˜์˜) Pinnote.setPosition({ bottom: 72, side: 'right' }); // ํ•˜๋‹จ ๋ฐ” ๋†’์ด๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์•Œ๋ ค ์ฃผ๊ธฐ Pinnote.open({ page: true }); // ํ™”๋ฉด ์ „์ฒด ์˜๊ฒฌ ์ฐฝ Pinnote.open({ selector: '#pay-button' }); // ํŠน์ • ์š”์†Œ ์˜๊ฒฌ ์ฐฝ Pinnote.open(); // ์š”์†Œ ๊ณ ๋ฅด๊ธฐ ๋ชจ๋“œ Pinnote.on('submitted', (d) => console.log('์˜๊ฒฌ', d.id)); document.addEventListener('pinnote:submitted', (e) => console.log(e.detail)); ``` ์„ค์น˜ ํ•œ ์ค„(`defer`)์ด ์‹คํ–‰๋œ ๋’ค์˜ ํ˜ธ์ถœ์€ ์œ„์ ฏ ๋ณธ์ฒด๊ฐ€ ์•„์ง ์•ˆ ์™”์–ด๋„ ๋กœ๋”๊ฐ€ ์Œ“์•„ ๋‘์—ˆ๋‹ค๊ฐ€ ๋„˜๊น๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ์ดํŠธ ์ฝ”๋“œ๋Š” `DOMContentLoaded` ์•ˆ์—์„œ ๋ถ€๋ฅด๋ฉด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค. ## ๊ธฐ๋Šฅ - **Shadow DOM ์œ„์ ฏ** - ํ˜ธ์ŠคํŠธ ํŽ˜์ด์ง€์˜ ๋ ˆ์ด์•„์›ƒยทCSS์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ผœ๊ธฐ ์ „ํ›„์— ์š”์†Œ ์ขŒํ‘œ๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. - ์ธ๋ผ์ธ style์„ ๋ง‰๋Š” ์—„๊ฒฉํ•œ CSP์—์„œ๋„ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. - **ํ•€** - `[data-ui]` ์š”์†Œ๋ฅผ ๋จผ์ €, ๋‚˜๋จธ์ง€๋Š” ํœด๋ฆฌ์Šคํ‹ฑ์œผ๋กœ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ๋†“๊ณ , ๋ชจ๋ฐ”์ผ์—์„œ๋Š” 28px๋กœ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. - ๊ธฐ์กด ์˜๊ฒฌ ๊ฐœ์ˆ˜์™€ ์ƒํƒœ๋ฅผ ๋ฐฐ์ง€๋กœ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. - ์š”์†Œ ์ง์ ‘ ๊ณ ๋ฅด๊ธฐ์™€ ํ™”๋ฉด ์ „์ฒด ์˜๊ฒฌ๋„ ๋ฉ๋‹ˆ๋‹ค. - **์˜๊ฒฌ ์ฐฝ** - ์ž…๋ ฅ: ์ข…๋ฅ˜(์•„์ด๋””์–ดยท๋ถˆํŽธยท์˜ค๋ฅ˜ยท๋ฌธ๊ตฌยท๋””์ž์ธ, ๊ธฐ๋ณธ์€ ์•„์ด๋””์–ด), ๋‚ด์šฉ, ์ด๋ฆ„(`data-name`ยท`Pinnote.setName()`์œผ๋กœ ๋ฏธ๋ฆฌ ์ฑ„์šธ ์ˆ˜ ์žˆ์Œ) - ์ด ์š”์†Œ์˜ ๊ธฐ์กด ์˜๊ฒฌ(์ƒํƒœยท๊ณต๊ฐยท๋Œ“๊ธ€ยท์™„๋ฃŒ ์‘๋‹ต) - **์—ฌ๋Ÿฌ ๊ฒน์˜ ๊ตฌ๋ถ„์ž** - ์‚ฌ์ดํŠธ: ๋„๋ฉ”์ธ, URL, ํ™”๋ฉด ํ‚ค(๊ฒฝ๋กœ ๊ทœ์น™ `/t/:token`), ์ œ๋ชฉ, ๋ฒ„์ „ยทํ™˜๊ฒฝ - ์š”์†Œ ์ฐพ๋Š” ๋ฐฉ๋ฒ• 9๊ฐ€์ง€: data-ui, id, ์งง์€ ์„ ํƒ์ž, DOM ๊ฒฝ๋กœ, ํƒœ๊ทธยท์—ญํ• ยท์ ‘๊ทผ์„ฑ ์ด๋ฆ„, ํ…์ŠคํŠธ, ๊ธฐ์ค€ ์ œ๋ชฉ, ์ขŒํ‘œ ๋น„์œจ, ์†์„ฑ - ์š”์†Œ ์›๋ž˜ ๋ชจ์Šต: HTMLยท์Šคํƒ€์ผยทํฌ๊ธฐ, ์š”์†Œ ์ฃผ๋ณ€ ์บก์ฒ˜ - ํ™˜๊ฒฝยท์‚ฌ์šฉ์ž ๋ฌธ๋งฅ - **์š”์†Œ๊ฐ€ ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ์‚ฌ๋ผ์งˆ ๋•Œ** - ๋ฐฉ๋ฌธ๋งˆ๋‹ค ๋‹ค์‹œ ์ฐพ์•„ ATTACHED / RELOCATED(์„ ํƒ์ž ์ž๋™ ๊ฐฑ์‹  + ์ด๋ ฅ) / MISSING(๋ฐฉ๋ฌธ N๋ฒˆยทN์ผ)์œผ๋กœ ๋‚˜๋ˆ•๋‹ˆ๋‹ค. - **์‚ฌ๋ผ์ง„ ์š”์†Œ** ๋ชฉ๋ก์—์„œ ์›๋ž˜ ๋ชจ์Šต์„ ๋ณด๊ณ  [์ˆ˜์ •์œผ๋กœ ํ•ด๊ฒฐ๋จ] / [๋‹ค์‹œ ์—ฐ๊ฒฐ](ํŽ˜์ด์ง€์—์„œ ์ƒˆ ์š”์†Œ ํด๋ฆญ) / [๋ณด๊ด€]์œผ๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค. - **์ƒํƒœ ํ๋ฆ„** - `NEW โ†’ TRIAGED โ†’ IN_PROGRESS โ†’ RESOLVED(์™„๋ฃŒ ์‘๋‹ต ํ•„์ˆ˜) โ†’ VERIFIED / REOPENED` - ๊ทธ ๋ฐ–์— `WONT_FIX`(์‚ฌ์œ ), `DUPLICATE`(์›๋ณธ), `NEEDS_INFO`๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. `VERIFIED`ยท`REOPENED`๋Š” ๊ด€๋ฆฌ ํ™”๋ฉดยทRESTยทCLI์—์„œ๋งŒ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. - ๋ชจ๋“  ๋ณ€๊ฒฝ์€ ํžˆ์Šคํ† ๋ฆฌ์— ๋‚จ์Šต๋‹ˆ๋‹ค: ๋ˆ„๊ฐ€ยท์–ธ์ œยท์ด์ „โ†’์ดํ›„ยท๋ฉ”๋ชจ. - **๋ณด๊ณ ์ž์—๊ฒŒ ์ฒ˜๋ฆฌ ์‹œ๊ฐยท์ฒ˜๋ฆฌ ์•Œ๋ฆผ์„ ๋ณด์ด์ง€ ์•Š์Œ**: ์œ„์ ฏ์—๋Š” "N๋ถ„ ์ „"ยท"์ฒ˜๋ฆฌ๋์–ด์š”" ์•Œ๋ฆผยท[ํ™•์ธํ–ˆ์–ด์š”]๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค(์ž‘์—… ์‹œ๊ฐ„ ์ถ”์  ๋ฐฉ์ง€). ํ™•์ธ ์™„๋ฃŒยท๋‹ค์‹œ ์—ด๊ธฐ๋Š” ๊ด€๋ฆฌ ํ™”๋ฉดยทRESTยทCLI์—์„œ ํ•ฉ๋‹ˆ๋‹ค. - **์ „์†ก ์‹คํŒจ ๋ณด๊ด€ ํ›„ ์žฌ์ „์†ก**, **ํฌ์ปค์Šค ๋ชจ๋“œ**(`?pinnote_focus=๋ฒˆํ˜ธ`: ์Šคํฌ๋กค + ๊นœ๋นก์ž„) - **๊ฐœ๋ฐœ์žยทAI** - REST API v1(ํ† ํฐ) - ๋งˆํฌ๋‹ค์šด/JSON ๋‚ด๋ณด๋‚ด๊ธฐ(์‚ฌ์ดํŠธ โ†’ ํ™”๋ฉด โ†’ ์š”์†Œ โ†’ ์˜๊ฒฌ) - CLI `bin/pinnote.php` - **๊ด€๋ฆฌ ํ™”๋ฉด**: ๋ฐ›์€ ์˜๊ฒฌํ•จ(ํ•„ํ„ฐยท์ผ๊ด„ ์ฒ˜๋ฆฌ), ์‚ฌ์ดํŠธ๋ณ„ ๋ณด๊ธฐ, ์˜๊ฒฌ ์ƒ์„ธ(์Šค๋ƒ…์ƒทยท๋ฌธ๋งฅยท๋Œ“๊ธ€ยทํžˆ์Šคํ† ๋ฆฌยท์ƒํƒœ ๋ฒ„ํŠผ), ์‚ฌ๋ผ์ง„ ์š”์†Œ, ์‚ฌ์ดํŠธ ์„ค์ •, API ํ† ํฐ, ํ†ต๊ณ„ - **๋ณด์•ˆ** - ์œ„์ ฏ API: ๊ณต๊ฐœ ํ‚ค + Origin ํ—ˆ์šฉ ๋ชฉ๋ก, CORS, IP ํ•ด์‹œ ๊ธฐ์ค€ ์‹œ๊ฐ„๋‹น ์ œํ•œ, ํฌ๊ธฐ ์ œํ•œ - ๊ด€๋ฆฌ ํ™”๋ฉด: CSRF, ์„œ๋ช… ์ฟ ํ‚ค - ์ถœ๋ ฅ ์ด์Šค์ผ€์ดํ”„, ๋ฏผ๊ฐ ๊ฐ’ ๊ฐ€๋ฆผ - ์„ค์ •ยท์ €์žฅ์†Œ๋Š” ์›น ๋ฃจํŠธ ๋ฐ– ## ๊ด€๋ฆฌ ํ™”๋ฉด - **[์œ„์ ฏ ๋‹ซ๊ธฐ] / [์œ„์ ฏ ์—ด๊ธฐ]**: ์ฒซ ํ™”๋ฉด ์œ„์ ฏ ์ค„๊ณผ ์‚ฌ์ดํŠธ ๋ชฉ๋ก์—์„œ ํ•œ ๋ฒˆ ๋ˆ„๋ฅด๋ฉด ๋œ๋‹ค. ๋‹ซ์œผ๋ฉด ๊ทธ ์‚ฌ์ดํŠธ์—์„œ ํ•€๋…ธํŠธ๊ฐ€ ํ”์  ์—†์ด ์‚ฌ๋ผ์ง€๊ณ (๋ฒ„ํŠผยท์˜ค๋ฅ˜ยท์žฌ์‹œ๋„ ์—†์Œ), ์˜๊ฒฌ๊ณผ ๊ธฐ๋ก์€ ๊ทธ๋Œ€๋กœ ๋‚จ๋Š”๋‹ค. 1. `/admin/`์—์„œ ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ์ด๋ฆ„(๋ชฉ๋ก์—์„œ ๊ณ ๋ฅด๊ฑฐ๋‚˜ ์ƒˆ๋กœ ์ž…๋ ฅ)์œผ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. 2. **์‚ฌ์ดํŠธ ์„ค์ • โ†’ ์ƒˆ ์‚ฌ์ดํŠธ**: ๋„๋ฉ”์ธ์„ ๋„ฃ์œผ๋ฉด ์‚ฌ์ดํŠธ ํ‚ค์™€ ์„ค์น˜ ํ•œ ์ค„์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฒฝ๋กœ ๊ทœ์น™, ์‚ฌ๋ผ์ง ๊ธฐ์ค€, ์บก์ฒ˜ ์ผœ๊ธฐยท๋„๊ธฐ๋ฅผ ์ •ํ•ฉ๋‹ˆ๋‹ค. 3. **๋ฐ›์€ ์˜๊ฒฌ**์—์„œ ์ •๋ฆฌํ•˜๊ณ , ์˜๊ฒฌ ์ƒ์„ธ์—์„œ **์ด ์š”์†Œ๋ฅผ ์‹ค์ œ ํŽ˜์ด์ง€์—์„œ ๋ณด๊ธฐ**๋กœ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. 4. ํ•ด๊ฒฐํ•  ๋•Œ๋Š” **์™„๋ฃŒ ์‘๋‹ต**(๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ๊ณ ์ณค๋Š”์ง€)์„ ์ ์Šต๋‹ˆ๋‹ค. 5. **API ํ† ํฐ**์„ ๋งŒ๋“ค์–ด ์—์ด์ „ํŠธ๋‚˜ CI์— ๋„˜๊น๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋ฒ•์€ [docs/API.md](docs/API.md)์— ์žˆ์Šต๋‹ˆ๋‹ค. ## API ํ•œ๋ˆˆ์— ```bash curl -H "Authorization: Bearer $PN_TOKEN" "https://pinnote.itemview.co.kr/api/v1/items?site=1&status=open" curl -H "Authorization: Bearer $PN_TOKEN" "https://pinnote.itemview.co.kr/api/v1/export?site=1&status=open" # ๋งˆํฌ๋‹ค์šด curl -X POST -H "Authorization: Bearer $PN_TOKEN" -H 'Content-Type: application/json' \ -d '{"status":"RESOLVED","note":"๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ๊ณ ์ณค๋Š”์ง€","version":"1.4.2"}' https://pinnote.itemview.co.kr/api/v1/items/12/status php bin/pinnote.php resolve 12 "๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ๊ณ ์ณค๋Š”์ง€" --version=1.4.2 ``` ## ์„œ๋ฒ„ ์„ค์น˜ยท์šด์˜ ```bash # PHP 8.2 + MariaDB + Apache(AllowOverride All), ์›น ๋ฃจํŠธ = public/ cp config.local.php.example config.local.php # db, base_url, admin_password, app_secret (์›น ๋ฃจํŠธ ๋ฐ–, git ์ œ์™ธ) php bin/migrate.php # db/migrations/NNN_*.sql ์ˆœ์„œ๋Œ€๋กœ ์ ์šฉ (์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•ด๋„ ์•ˆ์ „) php bin/seed.php # ๊ธฐ๋ณธ ์›Œํฌ์ŠคํŽ˜์ด์Šคยท๋‰ดํŒ… ๋ฐ๋ชจยทํ•€๋…ธํŠธ ๋ฐ๋ชจ ์‚ฌ์ดํŠธ์™€ ์‚ฌ์ดํŠธ ํ‚ค ์ถœ๋ ฅ (์ค‘๋ณต ์—†์Œ) ``` - `config.local.php`๋Š” apache๊ฐ€ ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(`chgrp apache`, 640). - `storage/`(logs, shots)๋Š” apache๊ฐ€ ์“ธ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ## ํด๋” ``` public/ ์›น ๋ฃจํŠธ w.php /w.js ๋กœ๋”(์บ์‹œ ์•ˆ ํ•จ) โ†’ widget/pinnote.js?v=๋ฒ„์ „(๊ธธ๊ฒŒ ์บ์‹œ) widget/ ์œ„์ ฏ ๋ณธ์ฒด vendor/ html2canvas 1.4.1 (MIT, ๋ผ์ด์„ ์Šค ํŒŒ์ผ ํฌํ•จ) api/w/ ์œ„์ ฏ API api/v1/ REST API v1 admin/ ๊ด€๋ฆฌ ํ™”๋ฉด demo/ ๋ฐ๋ชจ ์‚ฌ์ดํŠธ(์ƒ˜ํ”Œ ํŽ˜์ด์ง€ 2๊ฐœ) docs/ ๋ฌธ์„œ ๋ณด๊ธฐ shot.php ์บก์ฒ˜ ๋ณด๊ธฐ(์„œ๋ช… URL) lib/ ๊ณตํ†ต ์ฝ”๋“œ(์›น ๋ฃจํŠธ ๋ฐ–) db/migrations/ ์Šคํ‚ค๋งˆ bin/ migrate, seed, pinnote(CLI) docs/ INSTALL.md, API.md, DESIGN.md storage/ logs, shots (git ์ œ์™ธ) ```