나쁜 코드는 저품질 소스 코드를 가리키는 속어입니다: 읽기 어렵고, 구조가 나쁘며, 유지보수가 어렵습니다. Stripe 보고서(2022)에 따르면, 개발자는 작업 시간의 최대 40%를 잘못 작성된 코드를 읽고 이해하는 데 소비합니다. 러시아어 사용 커뮤니티에서는 이 용어가 매우 널리 퍼져 있어, 개발자들이 특히 눈에 띄는 사례의 예제를 게시하는 전문 웹사이트 govnokod.ru가 존재합니다.
핵심 요점
나쁜 코드는 최소 품질 기준을 충족하지 못하는 코드에 대한 주관적이지만 일반적으로 인정되는 특성입니다. Robert Martin은 그의 책 Clean Code(2008)에서 나쁜 코드를 “무엇을 하는지 이해하는 것을 방해하는 코드”라고 정의합니다. 나쁜 코드는 구문적으로 올바르고 심지어 작동할 수도 있지만, 그 유지보수는 팀에게 악몽이 됩니다.
나쁜 코드라는 용어는 특히 러시아어 사용 커뮤니티에서 널리 퍼져 있습니다. 영어에서는 스파게티 코드, 더티 코드, 기술 부채 코드와 같은 더 공식적인 용어가 사용됩니다. 그러나 “나쁜 코드”의 감정적 색채는 개발자들의 그러한 코드에 대한 태도—짜증, 혐오, 직업적 모욕의 혼합—를 더 정확하게 전달합니다.
McKinsey 연구(2023)에 따르면, 기술 부채가 높은 회사—나쁜 코드가 주요 구성 요소입니다—는 새로운 기능 개발에 20~40% 더 많은 자원을 소비합니다. 코드 품질은 비즈니스 지표에 직접적인 영향을 미치며, 이것은 은유가 아니라 확인된 사실입니다.
객관적인 지표는 존재하지 않지만 실용적인 기준은 있습니다: 개발자가 20줄짜리 함수를 이해하는 데 5분 이상 걸린다면—그것은 나쁜 코드입니다. 한 줄을 변경했는데 관련 없는 세 모듈이 깨진다면—그것은 나쁜 코드입니다. 완전한 재작성 없이 테스트로 코드를 커버할 수 없다면—그것은 나쁜 코드입니다.
복사-붙여넣기 프로그래밍은 가장 명백하고 쉽게 감지할 수 있는 징후 중 하나입니다. 동일한 코드 블록이 최소한의 변경으로 여러 위치에서 반복된다면, 그것은 단순한 나쁜 코드가 아니라 미래 버그의 원천입니다. 한 곳에서 수정하고 다른 곳에서 놓치는 것은 전형적인 상황입니다.
의미 없는 변수명은 고전입니다. `a`, `b`, `x`, `data`, `temp`, `tmp`, `result`, `list`, `obj`와 같은 이름의 변수는 그 목적에 관한 어떤 정보도 제공하지 않습니다. 코드를 읽는 사람은 변수에 무엇이 들어있는지 이해하기 위해 전체 함수를 분석해야 합니다. Robert Martin은 이것을 “이름의 거짓말”이라고 부릅니다—이름은 정보를 약속하지만 제공하지 않습니다.
깊은 중첩—조건문, 루프, 오류 처리가 5단계 이상의 들여쓰기 구조를 만들 때입니다. 이러한 코드는 가로 스크롤이나 모든 레벨의 정신적 추적 없이는 읽는 것이 불가능합니다. 이것은 오류로 가는 직접적인 경로입니다: 논리 연산자를 쉽게 혼동하고 닫는 괄호를 놓칠 수 있습니다.
| 징후 | 나쁜 코드 예 | 깨끗한 코드 |
|---|---|---|
| 복사-붙여넣기 | 하나의 블록을 5번 복사 | 함수로 추출 |
| 이름 | `var a = getData()` | `var userList = getData()` |
| 중첩 | if/for 6단계 | 조기 반환으로 2~3단계 |
| 함수 | 300줄짜리 함수 | 3~5개 메서드로 분할 |
| 주석 | `i++ // i 증가` | 주석 없는 자체 설명 코드 |
데드 코드—어디에서도 사용되지 않는 함수, 변수, 클래스. 이것은 코드 양을 늘리고, 개발자를 산만하게 하며, 시스템의 기능에 대한 잘못된 인상을 만듭니다. 매직 넘버—컨텍스트 없는 숫자. God 클래스—단일 책임 원칙(SOLID: S)을 위반하며 모든 것을 한 번에 수행하는 클래스.
시간 부족이 가장 흔한 이유입니다. 마감일이 임박하면 개발자는 속도를 위해 품질을 희생합니다. 전술적으로는 정당화될 수 있지만, 전략적으로는 기술 부채를 축적하는 것입니다. 문제는 “임시” 나쁜 코드가 수정하기 위해 재검토되는 경우가 거의 없다는 것입니다.
코드 리뷰의 부재가 두 번째로 중요한 이유입니다. 코드가 동료 검토 없이 혼자 작성되면, 나쁜 패턴이 뿌리내리고 증식합니다. 코드 리뷰는 단순한 품질 관리가 아니라 팀 내 지식 전달이기도 합니다. 리뷰 없는 프로젝트는 필연적으로 나쁜 코드로 빠집니다.
개발자의 낮은 자격이나 멘토링 부족. 감독 없이 방치된 주니어 개발자는 자연스럽게 나쁜 코드를 작성합니다—그것은 학습 과정의 일부입니다. 문제는 이 코드가 리뷰와 리팩토링 없이 프로덕션에 들어갈 때 발생합니다.
“작동하면 됐지”가 모토인 팀에서는 나쁜 코드가 번성합니다. 코딩 표준, 테스트 요구 사항, 리뷰 프로세스의 부재는 코드 품질이 누구의 관심사도 아닌 환경을 만듭니다. 그러한 프로젝트는 빠르게 “레거시”—모두가 건드리기를 두려워하는 코드—가 됩니다.
나쁜 코드의 주요 결과는 개발 속도 저하입니다. 나쁜 코드의 역설은 첫 번째 버전을 빠르게 작성할 수 있게 하지만, 이후의 각 수정에 점점 더 많은 시간이 소요된다는 것입니다. 코드 품질 대 개발 속도의 그래프는 기하급수적입니다—특정 임계값을 넘으면 새로운 기능 추가가 실질적으로 불가능해집니다.
직원 이직은 간접적이지만 심각한 결과입니다. 개발자, 특히 경험 많은 개발자는 나쁜 코드로 작업하기를 원하지 않습니다. Stack Overflow Developer Survey 2024에 따르면, 개발자의 47%가 직장 선택 시 코드베이스 품질을 핵심 요소 중 하나로 꼽습니다. 코드가 나쁜 프로젝트는 최고의 직원을 잃습니다.
보안은 나쁜 코드의 또 다른 희생자입니다. 잘못 작성된 코드에는 더 많은 취약점이 포함됩니다: 처리되지 않은 예외, SQL 인젝션, XSS, 메모리 누수. 유닛 테스트와 코드 리뷰를 갖춘 품질 좋은 코드는 프로덕션 전에 이러한 문제의 대부분을 잡아냅니다.
SonarQube 및 유사한 도구는 기술 부채를 인시 또는 일수로 추정할 수 있습니다. 예를 들어, 복사-붙여넣기에 관한 500개의 경고, 매직 넘버에 관한 200개, 깊은 중첩에 관한 50개는 30일의 기술 부채 추정치를 제공합니다. 이 숫자는 리팩토링을 정당화하기 위해 관리자에게 보여질 수 있고 또 보여져야 합니다.
DRY(Don’t Repeat Yourself) 원칙은 가장 먼저 구현해야 할 것입니다. 모든 로직 조각은 단일 위치에 존재해야 합니다. 복사-붙여넣기 대신—반복 코드를 별도의 함수, 클래스 또는 모듈로 추출하세요. 매직 넘버 대신—명명된 상수를 사용하세요. 긴 함수 대신—여러 개의 작은 함수로 나누세요.
KISS(Keep It Simple, Stupid) 원칙은 과도한 복잡성으로부터 보호합니다. 작업을 10줄로 해결할 수 있다면 50줄을 쓰지 마세요. 루프가 스트림보다 간단하다면 루프를 사용하세요. 일반 함수가 데코레이터보다 명확하다면 함수를 작성하세요. 단순함은 유지보수 가능한 코드의 주요 특성입니다.
보이스카우트 규칙—“코드를 발견했을 때보다 더 깨끗하게 남겨두라.” 각 편집 시의 작은 개선들도 시간이 지나면 나쁜 코드를 괜찮은 코드로 점진적으로 변화시킵니다. 변수 이름 바꾸기, 큰 함수 분할하기, 테스트 추가하기—어떤 개선이든 중요합니다.
// 나쁜 코드 — 복사-붙여넣기, 매직 넘버, 좋지 않은 이름
function calc(a, b, c) {
let x = a * 0.85;
if (b > 1000) { x = x * 0.9; }
let y = c * 0.85;
if (b > 1000) { y = y * 0.9; }
return x + y;
}
// 깨끗한 코드 — 명확한 이름, DRY, 상수
const DISCOUNT_RATE = 0.85;
const BULK_THRESHOLD = 1000;
const BULK_DISCOUNT = 0.9;
function applyDiscount(amount, quantity) {
let price = amount * DISCOUNT_RATE;
if (quantity > BULK_THRESHOLD) {
price = price * BULK_DISCOUNT;
}
return price;
}
function calculateTotal(items, quantity) {
return items.reduce((sum, item) => {
return sum + applyDiscount(item, quantity);
}, 0);
}
Python의 전형적인 예를 살펴보겠습니다. 함수는 주문을 처리하지만 잘못된 방식으로 합니다: 80줄, 깊은 중첩, 매직 넘버, 중복. 리팩토링 후 코드는 읽기 쉽고, 테스트 가능하며, 유지보수 가능해집니다.
# 나쁜 코드 — 하나의 함수가 모든 것을 함
def process_order(order):
if order.get("type") == "premium":
if order["amount"] > 100:
discount = 0.8
else:
discount = 0.9
else:
discount = 1.0
total = order["amount"] * discount
return total
# 깨끗한 코드 — 추출된 함수와 상수
class OrderProcessor:
PREMIUM_DISCOUNT_HIGH = 0.8
PREMIUM_DISCOUNT_LOW = 0.9
PREMIUM_THRESHOLD = 100
def get_discount(self, order):
if order.type == "premium" and order.amount > self.PREMIUM_THRESHOLD:
return self.PREMIUM_DISCOUNT_HIGH
return self.PREMIUM_DISCOUNT_LOW
def calculate_total(self, order):
return order.amount * self.get_discount(order)
좋은 함수는 한 가지 일을 하고 그것을 잘 수행합니다. 함수가 세 가지 다른 일을 한다면 분할하세요. 함수가 20줄을 넘는다면 아마 분할할 수 있습니다. 함수에 두 단계 이상의 들여쓰기가 있다면 리팩토링이 필요합니다.
정적 코드 분석기는 나쁜 코드에 대한 첫 번째 방어선입니다. ESLint(JavaScript), Pylint(Python), SonarQube(다중 언어), Checkstyle(Java)은 복사-붙여넣기, 매직 넘버, 빈 catch 블록, 지나치게 긴 함수 및 수백 가지의 다른 안티패턴을 자동으로 감지합니다.
코드 스타일과 포매터는 두 번째 보호 수준입니다. Prettier, Black, gofmt는 코드를 자동으로 포맷하여 공백, 들여쓰기, 괄호 문제를 제거합니다. 팀 전체의 일관된 스타일은 누가 작성했는지에 관계없이 코드를 읽기 쉽게 만듭니다. 포맷에 관한 논쟁은 자동화되어야 합니다.
코드 리뷰는 세 번째이자 가장 중요한 수준입니다. 어떤 분석기도 솔루션 아키텍처가 잘못되었거나 개발자가 잘못된 접근 방식을 선택했다는 것을 알아차리는 인간을 대체할 수 없습니다. 효과적인 리뷰는 시간이 걸리지만, 나쁜 코드의 양을 크게 줄임으로써 그 대가를 지불합니다.
자주 묻는 질문
극히 드물게. 프로토타이핑이나 해커톤에서는 속도가 품질보다 중요하지만, 그러한 코드는 임시로 표시되어야 하며 리팩토링 없이 프로덕션에 투입되어서는 안 됩니다. 프로덕션에서는 나쁜 코드에 대한 변명의 여지가 없습니다—지금 절약한 시간은 미래에 몇 배의 손실로 돌아올 것입니다.
초보자의 코드는 경험이 부족하지만 종종 성실하며, 기술의 성장과 함께 개선됩니다. 나쁜 코드는 품질에 대한 의식적이거나 무관심한 경시입니다. 초보자는 차선책이지만 읽을 수 있는 코드를 작성할 수 있습니다. 반면 나쁜 코드는 근본적으로 읽기 어렵습니다—작성자가 다른 사람이 이해하는지 신경 쓰지 않습니다.
재작성은 최후의 수단입니다. 점진적인 리팩토링이 더 안전합니다: 모듈을 분리하고, 테스트로 커버하고, 조금씩 다시 작성합니다. 완전한 재작성은 위험합니다—아무도 문서화하지 않은 엣지 케이스 처리를 포함하여, 이전 코드에 축적된 비즈니스 로직을 잃을 수 있습니다.
메트릭을 사용하세요: SonarQube는 기술 부채를 시간 단위로 보여줍니다. 이전 코드의 버그에 얼마나 많은 시간이 소비되는지 보여주세요. 프로젝트의 “깨끗한” 부분과 “더러운” 부분에서 새 기능 개발 속도를 비교하세요. 비즈니스 언어로 번역하세요: 시간은 돈이고, 나쁜 코드는 돈이 듭니다.
Robert Martin의 《Clean Code》(2008)는 고품질 프로그래밍의 바이블입니다. 명명 원칙, 포맷팅, 오류 처리 및 테스팅을 다룹니다. 추가로: Steve McConnell의 《Code Complete》, Martin Fowler의 《Refactoring》, GoF의 《Design Patterns》. 모든 개발자가 이 책들을 읽어야 합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.