바이브시대의 클린코딩이란2

2026. 4. 13. 14:12소마일기

1. 리팩토링의 기본 원칙과 절차

코드를 개선하는 '리팩토링'을 언제, 어떻게 해야 하는지 설명합니다.

  • 리팩토링 시기 (The Rule of Three): 처음과 두 번째 비슷한 작업을 할 때는 일단 그냥 넘어가지만, 세 번째로 비슷한 일을 하게 된다면 그때 리팩토링을 해야 합니다(3 Strike 원칙).
  • 리팩토링 절차 (3단계):
    1. Test Code 준비: 분석 중인 코드의 기존 동작을 증명해 줄 견고한 테스트 코드를 먼저 준비합니다. 리팩토링 과정에서 내부 구조를 변경하더라도 외부의 결과값은 똑같이 유지되어야 하는데, 이를 보장해 주는 '안전망' 역할을 합니다.

     
    # 기존 동작을 증명해 주는 견고한 Test Code 예시
    def test_calculate_discount():
        # 회원이면 10% 할인된 9000원이 나와야 함을 증명
        assert calculate_discount(10000, True) == 9000
        # 비회원이면 원가인 10000원이 나와야 함을 증명
        assert calculate_discount(10000, False) == 10000
    
    1. 문제 찾기: '코드 스멜(Code Smell)'을 활용하여 코드 내의 문제점을 파악합니다. 코드 스멜이란 버그나 에러는 아니지만, 유지보수를 어렵게 하거나 구조적인 결함이 있음을 암시하는 '냄새(징후)'를 말합니다.
    2. 해결 및 확인: 리팩토링 기법을 적용하여 문제를 해결한 뒤, 테스트를 통해 제대로 수정되었는지 확인합니다.
  • 켄트 벡의 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. 먼저 위 프롬프트를 클로드에게 먹여서 "가드레일"을 세웁니다. (기둥 1)
  2. VS Code 등의 에디터에 Ruff나 Flake8 같은 파이썬 린터(Linter)를 설치해 둡니다. (기둥 2)
  3. 코딩을 진행하다가 클로드가 규칙을 어기는 실수를 하면, 위 프롬프트 하단에 **"실수할 때마다 한 줄씩 추가"**하는 방식으로 나만의 컨텍스트 파일을 점점 정교하게 진화시켜 나가시면 됩니다.

 

반응형

'소마일기' 카테고리의 다른 글

개발 협업 툴  (0) 2026.04.15
ai 비서 만들기 맥 미니 초기 세팅  (0) 2026.04.14
바이브시대의 클린 코딩이란  (0) 2026.04.12