발행일

클린코드 입문 정리 — 인프런 강의 노트

클린 코드: 효율적인 소프트웨어 개발의 핵심

클린 코드는 가독성과 유지보수가 뛰어난 코드로, 개발자가 효율적으로 협업하고 문제를 해결할 수 있도록 돕습니다. 이번 블로그에서는 클린 코드를 작성하기 위한 몇 가지 핵심 원칙과 팁을 소개합니다.


1. 변수 이름은 의도를 명확히 표현하라

  • 문제점: 애매한 변수명은 코드 이해를 어렵게 만듭니다. 예를 들어 tcbm 같은 이름은 역할을 추측하기 어렵습니다.

  • 해결책: 변수 이름만으로도 역할을 명확히 알 수 있도록 구체적으로 작성하세요.

    // Bad
    const t = '' // 유저가 선택한 날짜
    
    // Good
    const selectedDate = '' // 유저가 선택한 날짜
    

2. 매직 넘버와 하드코딩 금지

  • 문제점: 의미 없는 숫자나 값이 코드 곳곳에 하드코딩되어 있으면 유지보수가 어렵습니다.

  • 해결책: 매직 넘버를 상수나 열거형으로 정의하세요.

    // Bad
    if (comments.length > 140) {
      throw new Error('exceed comment length')
    }
    
    // Good
    const COMMENT_LIMIT = 140
    if (comments.length > COMMENT_LIMIT) {
      throw new Error('exceed comment length')
    }
    

3. 함수는 순수하게 만들라 (Pure Function)

  • 문제점: 함수가 외부 상태에 의존하거나 상태를 변경하면 예측 가능성이 떨어집니다.

  • 해결책: 입력값이 같으면 항상 같은 결과를 반환하도록 하고, 외부 상태를 건드리지 않도록 만드세요.

    // Bad
    let outerValue = 7
    function impure(input) {
      return input + outerValue // 외부 상태에 의존
    }
    
    // Good
    function pure(input, addValue) {
      return input + addValue // 외부 상태를 사용하지 않음
    }
    

4. 부수효과(Side Effect)를 피하라

  • 문제점: 함수 내부에서 발생하는 변화가 외부 상태에 영향을 미치면, 디버깅이 어렵고 유지보수가 복잡해집니다.

  • 해결책: 함수의 주된 책임 이외의 작업은 별도로 분리하세요.

    // Bad
    function checkPassword(password) {
      if (password === 'cleanCode123') {
        Session.init() // 부수효과 발생
        return true
      }
      return false
    }
    
    // Good
    function checkPassword(password) {
      return password === 'cleanCode123'
    }
    
    const isValid = checkPassword('cleanCode123')
    if (isValid) {
      Session.init() // 부수효과를 함수 밖으로 분리
    }
    

5. 단일 책임 원칙 (Single Responsibility Principle)

  • 문제점: 여러 가지 역할을 하는 함수는 테스트와 수정이 어렵습니다.

  • 해결책: 함수는 하나의 일만 하도록 작성하세요.

    // Bad
    function checkPasswordAndInitSession(password) {
      if (password === 'cleanCode123') {
        Session.init() // 유저 세션 초기화
        return true
      }
      return false
    }
    
    // Good
    function checkPassword(password) {
      return password === 'cleanCode123'
    }
    
    const isValid = checkPassword('cleanCode123')
    if (isValid) {
      Session.init()
    }
    

다시 보니 — 이 노트 자체의 문제 둘

개고하면서 위 예제들을 다시 읽었는데, 강의를 받아 적기만 하고 소화하지 못한 흔적이 보입니다.

  • 1번의 Good 예제에 주석이 남아 있습니다. const selectedDate = '' // 유저가 선택한 날짜 — 이름이 의도를 표현하게 고쳤으면 주석은 지워져야 완성입니다. Bad 쪽 주석을 그대로 들고 온 건데, "이름이 주석을 대체한다"는 원칙의 핵심을 예제가 스스로 어기고 있었어요.
  • 4번과 5번의 예제가 사실상 동일합니다. 부수효과 분리와 단일 책임 원칙을 둘 다 checkPassword/Session.init()으로 설명하는데, 같은 예제로 설명되는 두 원칙이라면 그 차이를 이해하지 못한 채 적었다는 뜻입니다. 구분하자면 — SRP는 책임의 개수(검증과 세션 초기화라는 두 가지 일), 부수효과는 외부 세계를 건드리는가(반환값 외의 흔적)의 문제라, SRP를 지켜도 부수효과는 있을 수 있습니다(로깅만 하는 함수처럼).

실무에서 — 원칙이 실제로 시험대에 오른 지점

  • 매직 값 금지(2번)를 알고도 어긴 사례가 실코드에 있습니다. 실제 프로젝트의 공통 API 모듈은 서버 에러를 message === '유효하지 않은 JWT 토큰입니다.'처럼 하드코딩 문구 완전 일치로 분류합니다. 매직 넘버의 문자열판이죠 — 서버가 문구를 바꾸면 분류가 무너집니다. 원칙을 아는 것과 마감 안에서 지키는 것 사이의 간극이었고, 그 코드의 결함 목록에 정직하게 적어뒀습니다.
  • 부수효과는 "피하라"보다 "모아라"가 실무 답이었습니다. 4번 원칙대로 부수효과를 밖으로 빼면, 실전에서는 그 부수효과들(토큰 갱신, 리다이렉트, alert)이 화면마다 복사되는 다음 문제가 옵니다. 우리가 겪은 로그인 풀림 버그들의 해법은 부수효과를 없애는 게 아니라 공통 래퍼 한곳에 모으는 것이었어요. 순수한 코어 + 부수효과 전담 계층 — 강의의 원칙이 실무에서 취하는 실제 모양이었습니다.
  • 이름 원칙(1번)이 제일 오래갔습니다. 5가지 중 2년 뒤에도 매일 쓰는 건 결국 이름이에요. 코드 리뷰에서 지적하는 것도, 지적받는 것도 대부분 이름이었습니다.