9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
9.3 KiB
9.3 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quality-refactoring | Refactoring — 작은 step / 안전 변경 | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
Refactoring
작은 reversible step. 매 step 후 test. Behavior 변경 X — 단지 structure. Martin Fowler 의 카탈로그 + IDE refactoring tools.
📖 핵심 개념
- Code smell: 변경 신호.
- Extract / Inline / Move / Rename.
- Test first — 안전망.
- Parallel change — 큰 변경 점진.
💻 코드 패턴
가장 일반 refactoring
1. Extract function/method: 긴 function → 작은 function
2. Inline: 과도한 indirection 제거
3. Rename: 의미 명확
4. Move: 적절 위치
5. Extract variable: 복잡 expression 명명
6. Replace conditional with polymorphism
7. Replace magic number with constant
8. Encapsulate field
Extract function (가장 자주)
// Before
function processOrder(order: Order) {
// Calculate tax (10 lines)
let tax = 0;
for (const item of order.items) {
tax += item.price * 0.08;
}
// Calculate shipping (15 lines)
let shipping = 0;
if (order.weight > 10) shipping = 20;
else if (order.weight > 5) shipping = 10;
else shipping = 5;
// Apply discount (8 lines)
// ...
return order.subtotal + tax + shipping - discount;
}
// After
function processOrder(order: Order) {
const tax = calculateTax(order.items);
const shipping = calculateShipping(order.weight);
const discount = applyDiscount(order);
return order.subtotal + tax + shipping - discount;
}
function calculateTax(items: Item[]): number {
return items.reduce((sum, i) => sum + i.price * 0.08, 0);
}
function calculateShipping(weight: number): number {
if (weight > 10) return 20;
if (weight > 5) return 10;
return 5;
}
→ 의미 명명 + test 가능.
Replace conditional with polymorphism
// Before
class Animal {
sound(): string {
if (this.type === 'dog') return 'Woof';
if (this.type === 'cat') return 'Meow';
if (this.type === 'cow') return 'Moo';
return '';
}
}
// After
abstract class Animal {
abstract sound(): string;
}
class Dog extends Animal { sound() { return 'Woof'; } }
class Cat extends Animal { sound() { return 'Meow'; } }
class Cow extends Animal { sound() { return 'Moo'; } }
또는 lookup table:
const sounds: Record<AnimalType, string> = {
dog: 'Woof', cat: 'Meow', cow: 'Moo',
};
function sound(type: AnimalType): string {
return sounds[type];
}
Parallel change (큰 변경)
3 phase:
1. Expand: New 가 추가됨 (old 도 keep)
2. Migrate: 사용자가 new 로 이동
3. Contract: Old 제거
각 phase = deployable.
// Phase 1: Add new method
class API {
oldMethod(x: number) { return x * 2; }
newMethod(x: number, y: number) { return x * 2 + y; }
}
// Phase 2: Migrate callers (PR by PR)
api.oldMethod(5) → api.newMethod(5, 0)
// Phase 3: Remove old method
class API {
newMethod(x: number, y: number) { ... }
}
→ Big bang 보다 안전.
Strangler fig
큰 system 의 일부 점진 교체:
Phase 1: Old system 그대로.
Phase 2: New system + facade — 일부 traffic.
Phase 3: 점진 traffic 이동.
Phase 4: Old system 제거.
// Facade
class OrderService {
async create(order: Order) {
if (featureFlag('use-new-system')) {
return newSystem.create(order);
}
return oldSystem.create(order);
}
}
Code smells (refactor 신호)
1. Long method (50+ lines): extract function
2. Large class (500+ lines): extract / split
3. Long parameter list (5+): parameter object
4. Duplicate code: extract + reuse
5. Switch statements: polymorphism / lookup
6. Feature envy (다른 class 의 데이터): move method
7. Data clumps (같은 그룹 매번): data class
8. Primitive obsession: value object
9. Comments explaining what: extract function (이름 붙임)
10. Dead code: delete
Test first
// 1. Test 작성 (현재 behavior)
test('processOrder calculates correctly', () => {
const order = makeOrder(...);
expect(processOrder(order)).toBe(95.20);
});
// 2. Refactor
function processOrder(order: Order) {
const tax = calculateTax(order.items);
// ...
}
// 3. Test 통과 = behavior 같음
IDE refactoring (안전)
VS Code / WebStorm:
- F2: Rename (모든 reference)
- Ctrl+Shift+R: Extract method
- Ctrl+Alt+M: Extract variable
- Move file (drag)
- Auto-import organize
→ Manual 보다 안전 + 빠름.
TS 의 점진 typing
// Phase 1: any 만
function process(input: any): any { ... }
// Phase 2: 입력 type
function process(input: Order): any { ... }
// Phase 3: 출력 type
function process(input: Order): Result { ... }
// Phase 4: 내부 변수 type
→ 점진 strict.
Inline (과도 indirection 제거)
// Before
function getEmail(user: User): string {
return user.email;
}
const email = getEmail(user); // 의미 없는 wrapping
// After
const email = user.email;
Rename (semantic)
// Before
function calc(x: number, y: number) { ... }
// After
function calculateTotalPrice(quantity: number, unitPrice: number) { ... }
→ 의미 명확.
Extract variable
// Before
if (order.items.length > 10 && order.totalAmount > 1000 && order.user.tier === 'gold') {
// ...
}
// After
const isLargeOrder = order.items.length > 10;
const isHighValue = order.totalAmount > 1000;
const isVipUser = order.user.tier === 'gold';
if (isLargeOrder && isHighValue && isVipUser) {
// ...
}
Encapsulate field
// Before
class User {
email: string; // 누가나 변경 가능
}
user.email = '...'; // validation 없음
// After
class User {
#email: string;
get email(): string { return this.#email; }
setEmail(value: string) {
if (!isValid(value)) throw new Error('invalid');
this.#email = value;
}
}
Replace magic number
// Before
if (statusCode === 429) { ... }
// After
const TOO_MANY_REQUESTS = 429;
if (statusCode === TOO_MANY_REQUESTS) { ... }
// 또는
import { StatusCode } from './http-status';
if (statusCode === StatusCode.TooManyRequests) { ... }
Move method to better class
// Before — Order class 가 customer 데이터 사용
class Order {
getCustomerDiscount() {
return this.customer.tier === 'gold' ? 0.1 : 0;
}
}
// After — Customer class 안
class Customer {
getDiscount() {
return this.tier === 'gold' ? 0.1 : 0;
}
}
→ Feature envy 제거.
Replace inheritance with composition
// Before
class Reader extends FileSystem { ... }
// After
class Reader {
constructor(private fs: FileSystem) { ... }
}
Simplifying conditionals
// Before
if (x) {
return true;
} else {
return false;
}
// After
return Boolean(x);
// Before
if (x === null || x === undefined) return defaultVal;
return x;
// After
return x ?? defaultVal;
Refactor in sprint
Friday: refactor day.
또는 매 PR 의 작은 cleanup.
큰 refactor = 별 sprint 또는 분기.
Continuous refactoring
Boy scout rule + 매 PR + IDE 도구 = 코드 점차 개선.
Big-bang refactor 거의 안 함.
When NOT to refactor
- 작동하는 코드 + 안 변경할 영역
- Critical path + test 없음
- Deadline 임박
- 이해 안 됐을 때 (먼저 이해)
- 명확 owner X
→ Refactor = 변경 시 우선.
Communication
PR description:
"This PR is pure refactor — no behavior change.
Reduces complexity score from 25 → 12."
→ Reviewer 가 변경 검사.
Test gap (refactor 전)
Test 없으면:
1. 작은 black-box test (입력/출력)
2. Refactor
3. Test 가 behavior lock
Tools
- VS Code / WebStorm refactoring
- ESLint --fix
- ts-prune (unused exports)
- knip (unused files / deps)
- prettier (style — refactor 의 friend)
- AI assist (Cursor, Copilot)
Refactor categories (Fowler)
1. Composing methods
2. Moving features between objects
3. Organizing data
4. Simplifying conditional expressions
5. Making method calls simpler
6. Dealing with generalization
7. Big refactorings
→ refactoring.com 무료.
🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| 매 PR | Boy scout (작은 cleanup) |
| Code review 발견 | 즉시 또는 follow-up issue |
| Hot spot (자주 변경) | 우선 refactor |
| 큰 architecture | Strangler fig + parallel change |
| Library version | Phased migration |
| Critical path | Test 먼저 |
❌ 안티패턴
- Big bang refactor: 깨짐 위험.
- Test 없는 refactor: behavior 변경 모름.
- Refactor + new feature 같은 PR: review 어려움.
- Style only refactor: lint / formatter 가 처리.
- 모든 코드 refactor 시도: focus 잃음.
- 이해 못 한 코드 refactor: bug 가능성.
- Refactor 미공지 (대규모): surprise.
🤖 LLM 활용 힌트
- 작은 reversible step.
- IDE refactoring 도구 활용.
- Test first 안전.
- Parallel change / strangler 큰 변경.