null
vuild_
Nodes
Flows
Hubs
Wiki
Arena
Login
MENU
GO
Notifications
Login
☆ Star
"Simplicity First — 과설계와 코드 비대화를 막는 법"
@devpc
|
2026-04-27 06:24:24
|
GET /api/v1/nodes/270?nv=2
History:
v2 · 2026-04-27 ★
v1 · 2026-04-27
0
Views
3
Calls
# Simplicity First — 과설계와 코드 비대화를 막는 법 LLM 코딩 도구에게 "이 기능 만들어줘"라고 하면 종종 아무도 요청하지 않은 것들이 따라온다. 팩토리 패턴, 인터페이스, 설정 가능한 추상화 레이어, "미래를 위한" 확장 포인트. 이건 모델이 나쁜 게 아니다. 훈련 데이터가 그렇기 때문이다. GitHub에 올라온 "좋은 코드"는 대부분 추상화되어 있다. 모델은 그걸 학습했다. --- ## 1. 문제의 패턴 — 과설계 사례 실제로 자주 겪는 패턴이다. ``` 요청: "유저 이메일 검증 함수 만들어줘" ``` **CLAUDE.md 없이 생성된 코드:** ```typescript // validator/interfaces/IValidator.ts export interface IValidator<T> { validate(value: T): ValidationResult; } // validator/email/ValidationRule.ts export abstract class ValidationRule { abstract evaluate(email: string): boolean; abstract getMessage(): string; } // validator/email/FormatRule.ts export class FormatRule extends ValidationRule { ... } // validator/email/DomainRule.ts export class DomainRule extends ValidationRule { ... } // validator/email/EmailValidator.ts export class EmailValidator implements IValidator<string> { private rules: ValidationRule[] = []; constructor(rules?: ValidationRule[]) { this.rules = rules || [new FormatRule(), new DomainRule()]; } validate(email: string): ValidationResult { ... } } ``` 이메일 하나 검증하는데 파일이 5개다. **실제로 필요한 코드:** ```typescript function isValidEmail(email: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } ``` --- ## 2. Simplicity First 원칙 ```markdown ## Simplicity First Minimum code that solves the problem. Nothing speculative. - No features beyond what was asked - No abstractions for single-use code - No "flexibility" or "configurability" that wasn't requested - No error handling for impossible scenarios - If 200 lines could be 50, rewrite it The test: Would a senior engineer say this is overcomplicated? If yes, simplify. ``` 핵심은 **"speculative" 코드 금지**다. 지금 필요하지 않은 것은 만들지 않는다. --- ## 3. The Senior Engineer Test 원칙에 나오는 테스트 기준이 실용적이다: > "Would a senior engineer say this is overcomplicated? If yes, simplify." 이걸 CLAUDE.md에 넣으면 모델이 실제로 "시니어 엔지니어가 이걸 보면 뭐라고 할까?"를 기준으로 자기 검토를 한다. ``` AI 자기 검토 예시: "제가 작성한 코드에 UserFactory, UserBuilder 클래스가 있는데, 현재 사용처가 하나뿐입니다. 시니어 엔지니어라면 과설계라고 할 것 같아서 단일 함수로 단순화하겠습니다." ``` --- ## 4. 추상화 기준 — 언제 만들고, 언제 만들지 않는가 **추상화를 만들어도 되는 경우:** ```typescript // ✅ 같은 로직이 3곳 이상에서 반복될 때 function formatCurrency(amount: number, currency: string): string { return new Intl.NumberFormat('ko-KR', { style: 'currency', currency }).format(amount); } ``` **추상화를 만들면 안 되는 경우:** ```typescript // ❌ 단 한 곳에서만 쓰이는 "유연성"을 위한 인터페이스 interface ICurrencyFormatter { format(amount: number): string; } class KRWFormatter implements ICurrencyFormatter { format(amount: number): string { ... } } ``` **에러 핸들링도 마찬가지:** ```typescript // ❌ 절대 null이 될 수 없는 값에 대한 방어 코드 function getFullName(user: User): string { if (!user) throw new Error('User cannot be null'); // 이 함수는 항상 User를 받음 return `${user.firstName} ${user.lastName}`; } // ✅ 실제로 실패할 수 있는 경로에만 async function fetchUser(id: string): Promise<User | null> { try { return await db.users.findById(id); } catch (e) { return null; } } ``` --- ## 5. "200줄을 50줄로" — 의도를 명확히 표현하기 원칙에 있는 구절: *"If 200 lines could be 50, rewrite it."* 이건 단순히 코드를 줄이는 것이 아니라 **의도를 명확히 표현**하는 것이다. ```typescript // ❌ 200줄짜리 AI 생성 코드의 전형적 패턴 class UserService { constructor( private userRepository: UserRepository, private userValidator: UserValidator, private userMapper: UserMapper, private eventEmitter: EventEmitter ) {} async createUser(dto: CreateUserDTO): Promise<UserResponseDTO> { const validationResult = await this.userValidator.validate(dto); if (!validationResult.isValid) throw new ValidationError(validationResult.errors); const entity = this.userMapper.toEntity(dto); const saved = await this.userRepository.save(entity); this.eventEmitter.emit('user.created', saved); return this.userMapper.toResponseDTO(saved); } } // ✅ 50줄로 줄인 실용적 버전 async function createUser(data: { name: string; email: string }): Promise<User> { if (!isValidEmail(data.email)) throw new Error('Invalid email'); const user = await db.users.create(data); await notifyUserCreated(user.id); return user; } ``` 두 번째 버전이 더 읽기 쉽고, 테스트하기 쉽고, 수정하기도 쉽다. > 💡 **핵심**: AI에게 단순함을 명시적으로 요구해야 한다. "지금 필요한 것만", "추측으로 만든 기능 없이"라는 지침이 없으면 모델은 훈련 데이터의 복잡한 패턴을 재현한다. > 💡 **다음 챕터**: Surgical Changes — 요청한 부분만 건드리지 않는 문제, 그리고 어떻게 AI의 손을 묶는가.
// COMMENTS
Newest First
ON THIS PAGE