바이브시대의 클린코딩이란2
2026. 4. 13. 14:12ㆍ소마일기
1. 리팩토링의 기본 원칙과 절차
코드를 개선하는 '리팩토링'을 언제, 어떻게 해야 하는지 설명합니다.
- 리팩토링 시기 (The Rule of Three): 처음과 두 번째 비슷한 작업을 할 때는 일단 그냥 넘어가지만, 세 번째로 비슷한 일을 하게 된다면 그때 리팩토링을 해야 합니다(3 Strike 원칙).
- 리팩토링 절차 (3단계):
- Test Code 준비: 분석 중인 코드의 기존 동작을 증명해 줄 견고한 테스트 코드를 먼저 준비합니다. 리팩토링 과정에서 내부 구조를 변경하더라도 외부의 결과값은 똑같이 유지되어야 하는데, 이를 보장해 주는 '안전망' 역할을 합니다.
# 기존 동작을 증명해 주는 견고한 Test Code 예시 def test_calculate_discount(): # 회원이면 10% 할인된 9000원이 나와야 함을 증명 assert calculate_discount(10000, True) == 9000 # 비회원이면 원가인 10000원이 나와야 함을 증명 assert calculate_discount(10000, False) == 10000- 문제 찾기: '코드 스멜(Code Smell)'을 활용하여 코드 내의 문제점을 파악합니다. 코드 스멜이란 버그나 에러는 아니지만, 유지보수를 어렵게 하거나 구조적인 결함이 있음을 암시하는 '냄새(징후)'를 말합니다.
- 해결 및 확인: 리팩토링 기법을 적용하여 문제를 해결한 뒤, 테스트를 통해 제대로 수정되었는지 확인합니다.
- 켄트 벡의 Two Hats (두 개의 모자): 소프트웨어 개발 시 '기능 구현'과 '리팩토링(코드 가독성/유지보수성 향상)'이라는 두 가지 목적을 확실히 구분해야 합니다. 모자를 바꿔 쓰듯 현재 자신이 어떤 목적의 작업을 하고 있는지 명확히 인지해야 하며, 리팩토링 중에는 새로운 기능을 추가해선 안 됩니다.
2. 클린 코드를 위한 구조와 형식
읽기 좋고 유지보수하기 쉬운 코드를 작성하는 구체적인 방법론입니다.
2.1 함수와 형식 규칙
- 플래그(Boolean) 인수 피하기: bool 값을 넘긴다는 것은 함수가 내부에서 True일 때와 False일 때 각각 다른 두 가지 일을 처리하고 있다는 것을 자백하는 셈입니다. 따라서 플래그 인수를 피하고 대신 함수를 분리하는 것이 좋습니다.
# ❌ 나쁜 예 (코드 스멜: 플래그 인수) def render_page(is_suite: bool): if is_suite: print("스위트룸 전용 UI를 그립니다.") else: print("일반 객실 UI를 그립니다.") # ✅ 좋은 예 (리팩토링 후) def render_suite_page(): print("스위트룸 전용 UI를 그립니다.") def render_normal_page(): print("일반 객실 UI를 그립니다.") - 인수 개수 최소화: 인수는 적을수록 좋으며, 이항(2개) 함수도 가능하면 단항(1개)으로 바꾸려 노력해야 합니다. 삼항(3개) 함수는 이해하기 어려우므로 신중히 고려해야 합니다.
- 가로 형식 맞추기: 코드를 읽을 때 오른쪽으로 스크롤할 필요가 없도록 한 줄당 80~120자 정도의 적절한 길이를 유지해야 합니다.
- 세로 형식 맞추기 (High Level -> Low Level): 파일의 첫 부분에는 전체적인 흐름과 고차원(High Level)의 핵심 개념을 먼저 배치하고, 아래로 내려갈수록 의도를 세세하게 묘사하며 구체적이고 저차원(Low Level)인 세부 구현 함수들을 배치합니다. 마치 신문 기사를 읽는 것과 같은 구조입니다.
# High Level (전체 흐름 파악) def make_coffee(): grind_beans() boil_water() brew() # Low Level (세부 묘사) def grind_beans(): print("원두를 분쇄합니다.") def boil_water(): print("물을 끓입니다.") def brew(): print("커피를 내립니다.")
2.2 주의해야 할 '코드 스멜'의 주요 예시
리팩토링이 필요함을 알리는 대표적인 징후들은 다음과 같습니다.
- 중복 코드 (Duplicated Code): 똑같은 로직의 코드가 복사/붙여넣기 되어 있는 경우로, 수정 시 모든 곳을 고쳐야 해 누락 위험이 큽니다.
- 긴 매개변수 목록 (Long Parameter List): 함수에 넘겨주는 인자가 4~5개를 넘어가는 경우 연관된 데이터를 묶어 하나의 객체로 전달해야 합니다.
- 긴 함수 (Long Method): 함수가 너무 길면 파악하기 어렵고 테스트하기 힘들어지므로 서브 함수로 분리해야 합니다.
- 기본형 집착 (Primitive Obsession): 도메인 개념(전화번호, 화폐 등)을 별도 객체로 만들지 않고 기본 자료형으로만 처리하면 유효성 검사 로직이 흩어집니다.
2.3 SOLID 원칙의 올바른 이해
- SRP (단일 책임 원칙): 하나의 클래스는 하나의 책임만 가져야 합니다. (예: 모델 로드와 영상 전처리는 별도의 클래스로 분리).
# ❌ 한 클래스가 너무 많은 일을 함 class VideoAnalyzer: def load_model(self): pass def preprocess_video(self): pass # ✅ 책임을 명확히 분리 class ModelLoader: def load(self): pass class VideoPreprocessor: def process(self): pass - OCP (개방-폐쇄 원칙): 확장에 대해서는 열려 있어야 하지만, 수정에 대해서는 닫혀 있어야 합니다. (예: 새로운 결제 수단이 생길 때마다 if문을 수정하는 것은 나쁜 예입니다).
# ❌ 결제 수단이 추가될 때마다 코드 수정 필요 class PaymentProcessor: def process(self, payment_type): if payment_type == "card": print("카드 결제") # ✅ 인터페이스로 확장 class Payment: def pay(self): pass class CardPayment(Payment): def pay(self): print("카드 결제") - LSP (리스코프 치환 원칙): 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 합니다. (예: 펭귄은 새지만 날지 못하는데 부모의 fly 메서드를 상속받아 에러를 내면 안 됩니다).
# ❌ 펭귄에게 억지로 fly 상속 class Bird: def fly(self): pass class Penguin(Bird): def fly(self): raise NotImplementedError("못 날아요!") # ✅ 역할 분리 class FlyingBird(Bird): def fly(self): pass class Penguin(Bird): def swim(self): pass - ISP (인터페이스 분리 원칙): 사용하지 않는 메서에 의존하도록 강제해서는 안 됩니다. (예: 로봇은 밥을 먹지 않는데 eat을 강제로 구현하게 하면 안 됩니다).
# ❌ 로봇에게 eat 강제 class WorkerInterface: def work(self): pass def eat(self): pass # ✅ 인터페이스를 쪼갬 class Workable: def work(self): pass class Eatable: def eat(self): pass - DIP (의존성 역전 원칙): 구체적인 클래스보다 추상화된 인터페이스에 의존해야 합니다. (예: 서비스가 특정 데이터베이스(MySQL)에 강력하게 결합되는 것은 나쁜 예입니다).
# ❌ 특정 DB(구체화)에 직접 의존 class MySQLDatabase: def save(self): pass class UserService: def __init__(self): self.db = MySQLDatabase() # ✅ 추상화된 인터페이스에 의존 class DatabaseInterface: def save(self): pass class UserService: def __init__(self, db: DatabaseInterface): self.db = db
3. 바이브코딩 시대를 위한 CLAUDE.md 세팅법
AI(Claude 등)에게 코딩을 시킬 때 가이드라인(프롬프트)을 어떻게 작성해야 효율적인지 보여주는 아주 중요한 대목입니다. Anthropic 공식 문서에 따르면 두 가지 방법이 쓰입니다.
- CLAUDE.md 파일: 프로젝트의 최상위 루트 경로에 생성하여 프로젝트 전반의 공통/전역 규칙을 적어둡니다.
- .claude/rules/ 디렉토리: 지켜야 할 규칙이 많다면 규칙을 잘게 나누어 폴더 안에 저장해 필요할 때만 메모리에 로드되게 합니다.
- 조합: 이 두 가지를 병행하는 것이 상호 보완적으로 작동하는 모범 사례이며, 규칙 충돌 시 더 구체적인 지침이 우선적으로 적용됩니다.
3.1 토큰을 아끼는 프롬프트 최적화 원리
- 마크다운 개조식 활용: 사람이 읽기 좋은 긴 줄글 형태로 풀어서 쓰는 것은 비효율적입니다. 마크다운 문법을 활용해 핵심 키워드 중심의 개조식으로 압축하면, AI가 똑같이 이해하면서도 컨텍스트 토큰 소비량을 80%나 크게 절감(650 -> 120)할 수 있습니다.
- 왜 영어로 작성해야 할까?AI 모델(LLM)들은 텍스트를 글자 그대로가 아닌 '토큰(Token)' 단위로 변환하여 읽습니다. 영어는 대개 1단어가 1토큰으로 매핑되지만, 한국어는 토큰화 효율이 떨어져 보통 2배에서 3배 이상의 토큰을 소모하게 됩니다.
- 따라서, '마크다운 개조식 요약'에 '영어'를 결합하는 것이 바이브코딩 시대의 가장 완벽한 프롬프트 최적화입니다. 규칙 파일들은 AI가 코드를 짤 때마다 매번 읽어야 하는 파일이므로 토큰 최적화가 더욱 중요합니다.
3.2 권장되는 형태
# Code Rules (Python)
## Naming
- Vars/Funcs: snake_case. No abbreviations (e.g., `user` instead of `usr`).
- Funcs: Start with verbs (`get_`, `set_`, `is_`, `calculate_`).
- Classes: PascalCase (Nouns).
## Functions
- Strictly follow SRP (Single Responsibility).
- Max 20 lines. Split if longer.
- Prefer early return.
## Error Handling
- Use specific exceptions (e.g., `except NetworkError:`).
- NEVER use bare `except:` or `except Exception:`.
- Include context in error messages.
## Comments
- Comment WHY, let code explain WHAT.
- No redundant comments for self-explanatory code.
# 프로젝트 컨텍스트 및 AI 에이전트 행동 지침
## 1. 너의 역할과 기본 태도
너는 이 프로젝트를 담당하는 시니어 파이썬 개발자 겸 AI 에이전트야.
내가 지시하는 모든 작업은 아래의 '파이썬 코딩 컨벤션'과 '하네스 행동 지침'을 절대적으로 준수하며 수행해야 해.
## 2. 하네스 행동 지침 (Harness Rules)
- **성공은 조용히, 실패만 시끄럽게:** 코드를 수정했거나 린터(Linter)를 통과했다면 전체 4,000줄의 코드를 다시 출력하지 마. 수정된 '핵심 부분'만 코드 블록으로 보여주고 넘어가.
- **자동 교정 루프 (Auto-Correction):** 코드 작성 중 에러가 예상되거나 규칙 위반이 발견되면, 나에게 물어보지 말고 즉시 너 스스로 원인을 파악해서 교정한 코드를 제시해.
- **가비지 컬렉션 (Garbage Collection):** 코드를 작성하면서 사용하지 않는 더미 코드, 나쁜 패턴, 혹은 이 문서(컨텍스트)와 실제 코드가 달라진 부분이 보이면 즉시 나에게 리팩토링을 제안해.
## 3. 파이썬 코딩 컨벤션 (절대 규칙)
코드 작성 시 다음 규칙을 무조건 따른다.
* **Naming (명명 규칙)**
* 변수 및 함수: `snake_case` 사용. 의미를 알 수 없는 축약어는 절대 금지 (예: `usr` 대신 `user` 사용).
* 함수명: 반드시 동사로 시작 (`get_`, `set_`, `is_`, `calculate_` 등).
* 클래스명: `PascalCase` 사용 (명사형).
* **Functions (함수 설계)**
* 단일 책임 원칙(SRP) 엄수. 하나의 함수는 하나의 일만 한다.
* 길이 제한: 최대 20줄. 이를 초과하면 반드시 분리할 것.
* Early return 패턴을 적극 사용하여 들여쓰기(Depth)를 최소화할 것.
* **Error Handling (에러 처리)**
* 구체적인 예외 상황을 명시할 것 (예: `except NetworkError:`).
* `except:` 또는 `except Exception:`과 같은 광범위하고 무책임한 예외 처리는 절대 금지.
* 에러 메시지에는 반드시 디버깅이 가능하도록 당시의 컨텍스트(변수 상태 등)를 포함할 것.
* **Comments (주석)**
* 코드가 '무엇(WHAT)'을 하는지 설명하지 마라 (코드로 보여라).
* '왜(WHY)' 이렇게 작성했는지 설계 의도와 비즈니스 로직의 이유만 주석으로 남길 것.
* 자기 설명적(Self-explanatory)인 코드에는 중복 주석을 달지 않는다.
---
위 내용을 모두 숙지했다면, "하네스 시스템 설정 완료. 어떤 파이썬 코딩을 시작할까요?" 라고만 짧게 대답해.
아이디어가 모호한 상태에서 시스템만 완벽하게 구축하려고 하면 지치기 쉽습니다(Garbage In, Garbage Out).
- 먼저 위 프롬프트를 클로드에게 먹여서 "가드레일"을 세웁니다. (기둥 1)
- VS Code 등의 에디터에 Ruff나 Flake8 같은 파이썬 린터(Linter)를 설치해 둡니다. (기둥 2)
- 코딩을 진행하다가 클로드가 규칙을 어기는 실수를 하면, 위 프롬프트 하단에 **"실수할 때마다 한 줄씩 추가"**하는 방식으로 나만의 컨텍스트 파일을 점점 정교하게 진화시켜 나가시면 됩니다.
반응형
'소마일기' 카테고리의 다른 글
| 개발 협업 툴 (0) | 2026.04.15 |
|---|---|
| ai 비서 만들기 맥 미니 초기 세팅 (0) | 2026.04.14 |
| 바이브시대의 클린 코딩이란 (0) | 2026.04.12 |