# ๐Ÿ›ก๏ธ ์•ˆ์ „ํ•œ ๊ฐœ๋ฐœ ์‹ค์ฒœ ๊ทœ์น™ (Safe Development Practice) ## ํ•ต์‹ฌ ์›์น™: "๊ธฐ์กด ๊ธฐ๋Šฅ ์šฐ์„  ๋ณดํ˜ธ" **๋ชจ๋“  ๊ธฐ๋Šฅ ์ˆ˜์ •, ์ถ”๊ฐ€, ๋ฒ„๊ทธ ํ”ฝ์Šค ์‹œ ๊ธฐ์กด ์ •์ƒ ๊ธฐ๋Šฅ๋“ค์ด ์˜ํ–ฅ๋ฐ›์ง€ ์•Š๋„๋ก ์‚ฌ์ „ ์ฒดํฌ ๋ฐ ์•ˆ์ „์žฅ์น˜ ์ ์šฉ์ด ์ตœ์šฐ์„ ** --- ## ๐Ÿ“‹ ํ•„์ˆ˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ### Phase 1: ์‚ฌ์ „ ์˜ํ–ฅ๋„ ๋ถ„์„ (Pre-Impact Analysis) - [ ] **๊ธฐ์กด ๊ธฐ๋Šฅ ๋งคํ•‘**: ์ˆ˜์ •ํ•  ์˜์—ญ๊ณผ ์—ฐ๊ด€๋œ ๋ชจ๋“  ๊ธฐ์กด ๊ธฐ๋Šฅ ์‹๋ณ„ - [ ] **API ์˜์กด์„ฑ ๋ถ„์„**: ๊ธฐ์กด API ์—”๋“œํฌ์ธํŠธ, ์š”์ฒญ/์‘๋‹ต ํ˜•์‹ ํ™•์ธ - [ ] **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ํ™•์ธ**: ํ…Œ์ด๋ธ”, ์ œ์•ฝ์กฐ๊ฑด, ์ธ๋ฑ์Šค ์˜ํ–ฅ๋„ ๋ถ„์„ - [ ] **ํ”„๋ก ํŠธ์—”๋“œ ์—ฐ๋™ ํ™•์ธ**: ์ปดํฌ๋„ŒํŠธ, ๋ผ์šฐํŒ…, ์ƒํƒœ๊ด€๋ฆฌ ์˜ํ–ฅ๋„ ๋ถ„์„ ### Phase 2: ์•ˆ์ „ํ•œ ์„ค๊ณ„ (Safe Design) - [ ] **๋…๋ฆฝ์  ๊ตฌ์กฐ**: ์ƒˆ ๊ธฐ๋Šฅ์€ ๊ธฐ์กด ๊ธฐ๋Šฅ๊ณผ ๋ถ„๋ฆฌ๋œ ๋…๋ฆฝ์  ๊ตฌ์กฐ๋กœ ์„ค๊ณ„ - [ ] **ํ•˜์œ„ ํ˜ธํ™˜์„ฑ**: ๊ธฐ์กด API ์ŠคํŽ™, ๋ฐ์ดํ„ฐ ํ˜•์‹ ์œ ์ง€ - [ ] **์ ์ง„์  ์ ์šฉ**: ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ์˜์—ญ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ๋‹จ๊ณ„๋ณ„ ์ ์šฉ - [ ] **๋กค๋ฐฑ ๊ณ„ํš**: ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ์ฆ‰์‹œ ์ด์ „ ์ƒํƒœ๋กœ ๋ณต๊ตฌ ๊ฐ€๋Šฅํ•œ ๊ณ„ํš ์ˆ˜๋ฆฝ ### Phase 3: ๊ตฌํ˜„ ์ค‘ ์•ˆ์ „์žฅ์น˜ (Implementation Safeguards) - [ ] **์ƒˆ๋กœ์šด API ์—”๋“œํฌ์ธํŠธ**: ๊ธฐ์กด API ์ˆ˜์ • ๋Œ€์‹  ์ƒˆ ์—”๋“œํฌ์ธํŠธ ์ƒ์„ฑ - [ ] **๋ณ„๋„ ๋ฉ”์„œ๋“œ/ํ•จ์ˆ˜**: ๊ธฐ์กด ๋กœ์ง ์ˆ˜์ • ๋Œ€์‹  ์ƒˆ ๋ฉ”์„œ๋“œ ์ƒ์„ฑ - [ ] **๋ฐ์ดํ„ฐ ์•„์นด์ด๋ธŒ**: ๊ธฐ์กด ๋ฐ์ดํ„ฐ ์‚ญ์ œ ๋Œ€์‹  ๋น„ํ™œ์„ฑํ™” ๋˜๋Š” ์•„์นด์ด๋ธŒ - [ ] **์กฐ๊ฑด๋ถ€ ํ™œ์„ฑํ™”**: ํ”Œ๋ž˜๊ทธ๋‚˜ ์„ค์ •์„ ํ†ตํ•œ ์ƒˆ ๊ธฐ๋Šฅ ์กฐ๊ฑด๋ถ€ ํ™œ์„ฑํ™” ### Phase 4: ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ (Testing & Validation) - [ ] **๊ธฐ์กด ๊ธฐ๋Šฅ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ**: ๋ชจ๋“  ๊ธฐ์กด ๊ธฐ๋Šฅ ์ •์ƒ ์ž‘๋™ ํ™•์ธ - [ ] **API ์‘๋‹ต ๊ฒ€์ฆ**: ๊ธฐ์กด API ์‘๋‹ต ํ˜•์‹ ๋ฐ ๋ฐ์ดํ„ฐ ์ •ํ™•์„ฑ ํ™•์ธ - [ ] **๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ**: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ œ์•ฝ์กฐ๊ฑด, ๊ด€๊ณ„ ์ •์ƒ ํ™•์ธ - [ ] **UI/UX ๊ฒ€์ฆ**: ๊ธฐ์กด ํ™”๋ฉด ๋ฐ ์‚ฌ์šฉ์ž ํ”Œ๋กœ์šฐ ์ •์ƒ ์ž‘๋™ ํ™•์ธ --- ## ๐Ÿšซ ๊ธˆ์ง€์‚ฌํ•ญ (Never Do) ### ๊ธฐ์กด ์ฝ”๋“œ ์ง์ ‘ ์ˆ˜์ • ๊ธˆ์ง€ ```javascript // โŒ ๊ธฐ์กด ํ•จ์ˆ˜ ์ง์ ‘ ์ˆ˜์ • function existingFunction() { // ๊ธฐ์กด ๋กœ์ง // ์ƒˆ๋กœ์šด ๋กœ์ง ์ถ”๊ฐ€ - ์œ„ํ—˜! } // โœ… ์ƒˆ๋กœ์šด ํ•จ์ˆ˜ ์ƒ์„ฑ function newFeatureFunction() { // ์ƒˆ๋กœ์šด ๋กœ์ง } ``` ### ๊ธฐ์กด API ์ŠคํŽ™ ๋ณ€๊ฒฝ ๊ธˆ์ง€ ```javascript // โŒ ๊ธฐ์กด API ์‘๋‹ต ํ˜•์‹ ๋ณ€๊ฒฝ { "success": true, "data": [], // ๊ธฐ์กด ๊ตฌ์กฐ ๋ณ€๊ฒฝ - ์œ„ํ—˜! "newField": "์ƒˆ ํ•„๋“œ ์ถ”๊ฐ€" // ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€ } // โœ… ์ƒˆ๋กœ์šด API ์—”๋“œํฌ์ธํŠธ POST /api/new-feature { "success": true, "data": { "newStructure": "์ƒˆ ๊ตฌ์กฐ" } } ``` ### ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ๊ดด์  ๋ณ€๊ฒฝ ๊ธˆ์ง€ ```sql -- โŒ ๊ธฐ์กด ํ…Œ์ด๋ธ”/์ปฌ๋Ÿผ ์‚ญ์ œ DROP TABLE existing_table; ALTER TABLE users DROP COLUMN important_field; -- โœ… ์ƒˆ๋กœ์šด ํ…Œ์ด๋ธ”/์ปฌ๋Ÿผ ์ถ”๊ฐ€ CREATE TABLE new_feature_table (...); ALTER TABLE users ADD COLUMN new_optional_field VARCHAR(255); ``` --- ## ๐Ÿ”ง ์•ˆ์ „ํ•œ ์ˆ˜์ • ํŒจํ„ด ### 1. ๊ธฐ๋Šฅ ํ™•์žฅ ํŒจํ„ด ```javascript // ๊ธฐ์กด ๊ธฐ๋Šฅ ์œ ์ง€ํ•˜๋ฉด์„œ ํ™•์žฅ class OriginalService { existingMethod() { // ๊ธฐ์กด ๋กœ์ง ๊ทธ๋Œ€๋กœ ์œ ์ง€ } newMethod() { // ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€ } } ``` ### 2. ์กฐ๊ฑด๋ถ€ ๋ถ„๊ธฐ ํŒจํ„ด ```javascript function processRequest(type) { if (type === 'existing') { return existingLogic(); // ๊ธฐ์กด ๋กœ์ง } else if (type === 'new') { return newLogic(); // ์ƒˆ ๋กœ์ง } } ``` ### 3. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ/๋ž˜ํผ ํŒจํ„ด ```javascript function enhancedFunction(originalFunction) { return function(...args) { // ์ƒˆ๋กœ์šด ์ „์ฒ˜๋ฆฌ const result = originalFunction(...args); // ๊ธฐ์กด ๋กœ์ง // ์ƒˆ๋กœ์šด ํ›„์ฒ˜๋ฆฌ return result; }; } ``` --- ## ๐Ÿ“Š ์˜ํ–ฅ๋„ ๋งคํŠธ๋ฆญ์Šค | ์ˆ˜์ • ์˜์—ญ | ๊ธฐ์กด ๊ธฐ๋Šฅ ์˜ํ–ฅ๋„ | ์•ˆ์ „์žฅ์น˜ | |-----------|------------------|----------| | ์ƒˆ API ์ถ”๊ฐ€ | ๐ŸŸข ๋‚ฎ์Œ | ๋…๋ฆฝ์  ์—”๋“œํฌ์ธํŠธ | | ๊ธฐ์กด API ์ˆ˜์ • | ๐Ÿ”ด ๋†’์Œ | ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ๋ณด์žฅ | | ์ƒˆ DB ํ…Œ์ด๋ธ” | ๐ŸŸข ๋‚ฎ์Œ | ๋…๋ฆฝ์  ์Šคํ‚ค๋งˆ | | ๊ธฐ์กด DB ์ˆ˜์ • | ๐ŸŸก ์ค‘๊ฐ„ | ๋น„ํŒŒ๊ดด์  ๋ณ€๊ฒฝ๋งŒ | | ์ƒˆ UI ์ปดํฌ๋„ŒํŠธ | ๐ŸŸข ๋‚ฎ์Œ | ๋ณ„๋„ ์ปดํฌ๋„ŒํŠธ | | ๊ธฐ์กด UI ์ˆ˜์ • | ๐ŸŸก ์ค‘๊ฐ„ | ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง | --- ## ๐Ÿšจ ๊ธด๊ธ‰ ์ƒํ™ฉ ๋Œ€์‘ ### ๊ธฐ์กด ๊ธฐ๋Šฅ ์žฅ์•  ๋ฐœ์ƒ ์‹œ 1. **์ฆ‰์‹œ ๋กค๋ฐฑ**: ์ƒˆ ๊ธฐ๋Šฅ ๋น„ํ™œ์„ฑํ™” ๋˜๋Š” ์ด์ „ ๋ฒ„์ „ ๋ณต๊ตฌ 2. **์›์ธ ๋ถ„์„**: ์–ด๋–ค ๋ณ€๊ฒฝ์ด ๊ธฐ์กด ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์—ˆ๋Š”์ง€ ๋ถ„์„ 3. **๊ธด๊ธ‰ ํŒจ์น˜**: ๊ธฐ์กด ๊ธฐ๋Šฅ ๋ณต๊ตฌ๋ฅผ ์ตœ์šฐ์„ ์œผ๋กœ ์ฒ˜๋ฆฌ 4. **์žฌ์„ค๊ณ„**: ์•ˆ์ „ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ƒˆ ๊ธฐ๋Šฅ ์žฌ๊ตฌํ˜„ ### ๋กค๋ฐฑ ์ ˆ์ฐจ ```bash # 1. ์ฆ‰์‹œ ์ด์ „ ์ƒํƒœ๋กœ ๋ณต๊ตฌ git revert HEAD git push origin main # 2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณต๊ตฌ (ํ•„์š”์‹œ) mysql -u root -p < backup_before_change.sql # 3. ์บ์‹œ ํด๋ฆฌ์–ด redis-cli FLUSHALL ``` --- ## ๐Ÿ“ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ํ…œํ”Œ๋ฆฟ ### ๊ธฐ๋Šฅ ์ˆ˜์ • ์ „ ์ฒดํฌ ```markdown ## ๊ธฐ๋Šฅ ์ˆ˜์ • ์•ˆ์ „์„ฑ ์ฒดํฌ๋ฆฌ์ŠคํŠธ **์ˆ˜์ • ๋‚ ์งœ**: ___________ **์ˆ˜์ •์ž**: ___________ **์ˆ˜์ • ๋‚ด์šฉ**: ___________ ### Phase 1: ์˜ํ–ฅ๋„ ๋ถ„์„ - [ ] ๊ด€๋ จ ๊ธฐ์กด ๊ธฐ๋Šฅ ๋ชฉ๋ก ์ž‘์„ฑ - [ ] API ์˜์กด์„ฑ ํ™•์ธ - [ ] ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์˜ํ–ฅ๋„ ํ™•์ธ - [ ] ํ”„๋ก ํŠธ์—”๋“œ ์˜ํ–ฅ๋„ ํ™•์ธ ### Phase 2: ์•ˆ์ „ํ•œ ์„ค๊ณ„ - [ ] ๋…๋ฆฝ์  ๊ตฌ์กฐ ์„ค๊ณ„ - [ ] ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ๋ณด์žฅ - [ ] ๋กค๋ฐฑ ๊ณ„ํš ์ˆ˜๋ฆฝ ### Phase 3: ๊ตฌํ˜„ - [ ] ์ƒˆ๋กœ์šด ์—”๋“œํฌ์ธํŠธ/๋ฉ”์„œ๋“œ ์‚ฌ์šฉ - [ ] ๊ธฐ์กด ์ฝ”๋“œ ์ง์ ‘ ์ˆ˜์ • ์—†์Œ - [ ] ์กฐ๊ฑด๋ถ€ ํ™œ์„ฑํ™” ์ ์šฉ ### Phase 4: ํ…Œ์ŠคํŠธ - [ ] ๊ธฐ์กด ๊ธฐ๋Šฅ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ - [ ] ์ƒˆ ๊ธฐ๋Šฅ ์ •์ƒ ์ž‘๋™ ํ™•์ธ - [ ] ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ํ™•์ธ ``` --- ## ๐Ÿ’ก ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค 1. **"๊ธฐ์กด ๊ธฐ๋Šฅ ์šฐ์„ "** ๋งˆ์ธ๋“œ์…‹ ์œ ์ง€ 2. **์ ์ง„์  ๊ฐœ๋ฐœ**: ์ž‘์€ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ์•ˆ์ „ํ•˜๊ฒŒ ๊ตฌํ˜„ 3. **์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ**: ์ƒˆ ๊ธฐ๋Šฅ๊ณผ ๊ธฐ์กด ๊ธฐ๋Šฅ ๋ชจ๋‘ ํ…Œ์ŠคํŠธ 4. **๋ฌธ์„œํ™”**: ๋ณ€๊ฒฝ์‚ฌํ•ญ๊ณผ ์•ˆ์ „์žฅ์น˜ ์ƒ์„ธ ๊ธฐ๋ก 5. **ํŒ€ ๊ณต์œ **: ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํŒ€์›๋“ค๊ณผ ์‚ฌ์ „ ๊ณต์œ  ๋ฐ ๋ฆฌ๋ทฐ **"์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋˜, ๊ธฐ์กด์˜ ๊ฐ€์น˜๋ฅผ ์ง€์ผœ๋ผ"** description: globs: alwaysApply: false ---