‘Clean’ 코드를 쓰는 것을 멈추고, 읽기 쉬운 코드를 작성하라

발행: (2026년 2월 15일 오후 03:36 GMT+9)
14 분 소요
원문: Dev.to

Source: Dev.to

Clean Code illustration

네, 또 다른 클린 코드에 관한 글입니다. 간단히 상기시켜 드리자면: according to various sources, 코드를 읽는 데 소비하는 시간과 코드를 작성하는 시간의 비율이 7:1 혹은 그보다 더 높아질 수 있습니다. 버그를 수정하든, 기능을 추가하든, 리팩터링을 하든, 결국 다른 사람이(또는 몇 달 전의 자신이) 작성한 로직에 몸을 담그게 됩니다. 그래서 가독성은 처음 코드를 얼마나 빨리 입력했는가보다 훨씬 더 중요한 요소입니다.

읽기 어려운 코드는 기술 부채이며, 장기적으로 전체 팀의 병목 현상을 초래하고 개발 비용을 상승시킵니다. 그것이 전부입니다.

가독성 높은 코드의 핵심 원칙

나는 이제 “클린 코드” 가 만능이거나 깨질 수 없는 절대적인 법칙 집합이 아니라는 것을 깨달아야 할 때라고 생각한다. 이상적인 코드는 존재하지 않으며 존재할 수도 없다. 이는 일종의 철학이며, 코드를 이해하기 쉽게 만들기 위한 권고사항들의 집합이다. 아이러니하게도, 이러한 “깨질 수 없는 법칙”들은 사람들로 하여금 어떤 합의도 이루지 못하게 만들고, 끝없는 논쟁과 상충되는 해석을 낳는다.

나는 이것이 또 다른 “올바른 코드” 요약이 되길 원하지 않는다. 순수하게 학술적인 코드를 작성하고 싶다면(사실 불가능하지만) 로버트 마틴의 Clean Code 를 읽어라. 이 글은 합리적인 청결 을 강조한다. 실제로 필요할 때, 즉 유지보수가 필요한 프로젝트에서 적용하라.

“가장 좋은 코드는 어리석을 정도로 읽기 쉬운 코드다.”

코드가 의도를 이해하기 위해 머리를 갈아붙여야 하지 않아야 한다. 기본을 살펴보자. 이것이 없으면 유지보수성 은 대화조차 시작되지 않는다.

1. 명확한 변수와 함수 이름

이것은 천 번이나 말했고, 이제 천 번째가 아니라 천 번째가 되었다. 이것이 절대적인 기본이다. 이름은 의도를 드러내야 한다. dlist1 같은 변수명을 보면 어디서부터 찾아야 할지, 혹은 구현을 깊게 파고들어야 할지 고민하게 된다. 반면 elapsedTimeInDaysactiveUsers 라고 하면 그런 질문은 사라진다.

2. 단일 책임 원칙 (SRP)

함수는 하나의 일을 해야 하며, 그 일을 잘 수행해야 한다. handleUserData 라는 함수가 폼 데이터를 가져오고, 검증하고, 데이터베이스에 저장하고, 이메일을 보내는 일을 모두 한다면—그것은 위험 신호다. validateForm, saveUserToDatabase, sendWelcomeEmail 로 나누라고 말할 수 있겠지만, 처음부터 하나의 함수가 모든 일을 담당하고 있다는 사실 자체가 진짜 경고다. 거대한 모놀리스를 다루고 있다면, 최소한 가독성을 위한 기준선으로 삼아라.

3. 일관된 코딩 스타일

탭을 쓸지 스페이스를 쓸지는 크게 중요하지 않다(탭이 메모리를 덜 차지하지만, 누가 신경 쓰겠는가?), 중괄호를 어디에 놓을지도 마찬가지다. 중요한 것은 팀 전체가 같은 방식을 따르는 것이다. 최소한 “술에 취한 채” 1 000 000 RPS 를 처리하도록 설계된 마이크로서비스를 작업하면서 서로 다른 패러다임을 섞어 쓰지는 말라. 일관성 없는 스타일은 시각적 잡음을 만든다. 다행히도 린터와 포매터가 오래전부터 이 문제를 해결해 왔다. 한 번 설정해 두면 로봇이 스타일을 담당한다.

뭐? 코드 리뷰?

코드 리뷰는 비난이 아니라 집단적 성장에 가장 효과적인 도구 중 하나입니다. 리뷰를 체계적으로 진행하려면 다음 체크리스트를 기억하세요:

영역질문 목록
논리작업을 해결합니까? 경계 상황을 처리했나요?
가독성이름이 명확합니까? 구조가 너무 복잡합니까?
아키텍처프로젝트 패턴을 따르고 있나요? 확장 가능합니까?
테스트테스트가 있나요? “행복한 경로”와 대안들을 커버하고 있나요?
자동화로봇에게 일을 맡기세요. 중복, 잠재적 버그, 취약점에 대한 일상적인 검사는 자동화에 위임해야 합니다. CI/CD 파이프라인에 SonarQube와 같은 도구를 사용하면 인간이 보기 전에 일반적인 문제의 ~90 %를 잡아낼 수 있습니다.
교육비판이 아니라 가르치는 데 집중하세요. “수정해라”와 같은 지시 대신 대화를 사용하세요: “이 접근법을 시도해 보면 어떨까요? 나중에 유지보수가 더 쉬워질 것 같아요.” 동료와 모든 사람에게 더 친절해야 합니다. 세상은 친절이 부족합니다.

패턴과 안티‑패턴: 고양이와 함께 설명

Cats and code

프로그래밍은 고양이와 함께 사는 것처럼, 우아한 해결책이 있기도 하고 뒤얽힌 엉망도 있습니다. 누군가 “아, 이건 그냥 클린 코드 요약이구나!” 라고 할 수도 있겠지만, 그렇지 않습니다. 지금 당장 필요한 일을 하도록 부릅니다. 아래 내용을 적용하면 미래의 자신이 고마워할 것입니다.

1. 깊은 중첩 (화살표 코드)

안티‑패턴

if (catWantsToPlay) {
  if (isLivingRoom) {
    if (blanketOnCouch) {
      if (boxUnderBlanket) {
        if (catnipInBox) {
          // Success, the cat is high!
        }
      }
    }
  }
}

들여쓰기 피라미드가 전체 체인을 머릿속에 유지하도록 강요합니다.

“조기 반환” 패턴 (Guard Clauses)

if (!catWantsToPlay) return;
if (!isLivingRoom)   return;
if (!blanketOnCouch) return;
if (!boxUnderBlanket) return;
if (!catnipInBox)    return;

// Success, the cat is high!

가드 절은 구조를 평탄하게 만들어 의도를 한눈에 명확히 합니다.

2. 미스터리 고양이 행동

안티‑패턴

if (catState === 1) {
  // Pet
} else if (catState === 2) {
  // Feed
} else if (catState === 3) {
  // Don't touch, the cat is dead
}

1, 2, 3이 무엇을 의미할까요? 이것은 매직 넘버입니다. 오늘은 기억할 수 있어도, 한 달 후에는 문서(존재한다면)를 뒤져 이 메시지를 해독해야 할 것입니다.

“명명된 상수” 패턴

const STATE_PURRING = 1;
const STATE_HUNGRY  = 2;
const STATE_DEAD    = 3;

if (catState === STATE_PURRING) {
  // Pet
} else if (catState === STATE_HUNGRY) {
  // Feed
} else if (catState === STATE_DEAD) {
  // Don't touch
}

3. 두 마리 동일한 고양이에게 먹이 주기

안티‑패턴 (복사‑붙여넣기)

// Feed Barsik
putInBowl("Barsik", "kibble");
pourInBowl("Barsik", "water");
callCat("Barsik");

// Feed Murzik
putInBowl("Murzik", "kibble");
pourInBowl("Murzik", "water");
callCat("Murzik");

비타민을 추가하면 두 곳을 모두 수정해야 합니다. 고양이 열 마리라면 하나를 놓치게 됩니다.

더 나은 방법 (DRY)

function feedCat(catName) {
  putInBowl(catName, "kibble");
  pourInBowl(catName, "water");
  callCat(catName);
}

feedCat("Barsik");
feedCat("Murzik");

경고: 이 패턴을 다른 사용 사례에 적용하지 마세요. 이는 서비스 헬이라는 안티‑패턴으로, 한 곳의 오류가 다른 곳에서 신비한 충돌을 일으킬 수 있습니다. 각 사용 사례는 별도로 격리되어야 합니다.

고양이 구동 프로젝트를 위한 클린 코드

코드는 평평하고 명확해집니다—마치 고양이가 목표까지 직접 가는 길처럼.

가독성 좋은 코드와 문서화

좋은 코드는 자체 문서화가 되지만, 그런지를 설명하기 위해서는 주석이 여전히 필요합니다. 외부 라이브러리의 버그에 대한 우회 방법을 사용했다면 링크를 남기세요. 그렇지 않으면 금요일 밤에 “프로덕션이 다운됐어요”라는 깜짝 전화를 받게 됩니다.

작성하기 전에 생각하세요: 코드는 업데이트되지만, 사람들은 종종 오래된 주석을 건드리는 것을 두려워합니다. 과도하게 달지 마세요.

실용적인 팁

  • Micro‑refactorings – 나쁜 이름이 보이나요? 바꾸세요. 모든 일을 하는 함수가 있나요? 나누세요—하지만 논리적인 블록으로, 3,000개의 작은 조각으로 나누지는 마세요. 코드를 찾았을 때보다 더 깨끗하게 남겨두세요. 마치 자리에 앉은 채로 다른 사람의 쓰레기를 줍는 것과 같습니다.
  • Pair Programming – 실시간 리뷰. 지식을 공유하거나 QuickSort와 MergeSort의 속도를 토론하기에 좋은 방법입니다.
  • Internal Guides – 규칙에 동의하고 지키세요. 가끔씩 실제로 확인해 보지 않으면 쓸모가 없습니다.

Pragmatism Above All

읽기 쉬운 코드는 개발 속도를 높입니다. 사실이죠. 하지만 “클린 코드”가 만병통치약은 아닙니다. 사람들은 여전히 “클린”이 무엇인지에 대해 싸울 것입니다. 작업에 필요하지 않다면 어떤 구루의 말을 맹목적으로 따르지 마세요.

한 번만 쓰는 마이그레이션 스크립트나 내일이면 버려질 프로토타입을 작성하고 있다면, 아키텍처에 몇 시간을 투자하는 것은 역효과를 낳습니다. 상황이 전부입니다.

가장 나쁜 일은 단순한 해결책이 가능한 곳에 복잡한 패턴을 무분별하게 적용하는 것입니다. 삼 주가 지난 뒤에는 실행보다 시작하는 데 더 오래 걸리는 괴물이 생겨, 존재하지도 않았던 문제를 해결하게 됩니다.

목표는 청결함을 위해 클린 코드를 쓰는 것이 아니라, 실제로 중요한 곳에서 maintainable(유지 보수 가능한) 코드를 작성하는 것입니다. 균형을 찾고, 프로젝트의 미래를 생각하며, 항상 배우는 자세를 유지하세요.

(그리고 한 가지 더: 독재 정권과는 절대 협업하지 마세요. 여러분이 만든 제한과 시스템이 바로 그들이 편안함을 느끼고 전쟁을 일으키게 하는 원동력입니다.)

끝났습니다. 행운을 빕니다!

0 조회
Back to Blog

관련 글

더 보기 »

[Talk::Overflow #23] 작은 ruby #{conf} 2025

tiny ruby {conf} 2025는 핀란드 헬싱키에서 열린 단일 트랙 Ruby 컨퍼런스였습니다. 6개의 강연, 하루 동안, 불필요한 내용 없이 진행되었습니다. Ruby 컨퍼런스는 종종 “Rails 컨퍼런스”와 혼동되곤 합니다.