코드 리뷰에서 “조기 최적화는 만악의 근원”이라는 말, 한 번쯤 들어보셨을 거예요.
그런데 원문을 찾아 읽어보면 이야기가 좀 달라집니다. 도널드 크누스가 진짜 하려던 말은 “최적화하지 마라”가 절대 아니었거든요.
결론부터 말씀드릴게요. 크누스는 “97%의 사소한 최적화는 잊되, 정말 중요한 3%는 절대 놓치지 말라”고 했습니다. 흔히 인용되는 반쪽짜리 문장에는 이 뒷부분이 통째로 잘려 있어요.
오늘은 이 문장의 진짜 맥락, 그리고 코드에서 언제 최적화를 해야 하는지 정리해봤어요.
진짜 원문은 이랬습니다
이 문장의 출처는 도널드 크누스가 1974년에 쓴 논문이에요. 제목은 “Structured Programming with go to Statements”, ACM Computing Surveys(미국컴퓨터학회 학술지)에 실렸습니다.
원문을 그대로 옮기면 이래요.
“우리는 사소한 효율을, 말하자면 97% 정도는 잊어야 한다. 조기 최적화는 만악의 근원이다. 하지만 그 결정적인 3%에서 기회를 놓쳐서는 안 된다.”
보이시죠? 우리가 아는 문장은 딱 가운데 토막만 잘라온 셈이에요.
앞에는 “97%는 잊어라”가 있고, 뒤에는 “3%는 놓치지 마라”가 붙어 있어요. 이 세 문장이 한 세트입니다.
크누스는 최적화를 하지 말라고 한 게 아니에요. 어디에 힘을 쏟을지 고르라는 얘기였죠.
“97%는 잊고 3%에 집중하라”, 이게 핵심입니다
크누스가 같은 논문에서 함께 지적한 게 있어요.
프로그래머들이 프로그램에서 중요하지도 않은 부분의 속도를 걱정하느라 엄청난 시간을 낭비한다는 거였어요.
그렇게 미리 손댄 최적화가 오히려 디버깅과 유지보수를 더 어렵게 만든다고요.
즉 문제는 최적화 자체가 아니라 타이밍과 위치예요. 아직 병목이 어딘지도 모르는 상태에서 아무 데나 손대는 게 화근이죠.
최적화하지 말라는 게 아니라, 근거 없이 아무 데나 최적화하지 말라는 뜻입니다.
그럼 대체 언제 최적화해야 하나요?
가장 자주 나오는 질문이죠. 답은 단순해요. 측정하고 나서 하세요.
크누스가 말한 그 결정적인 3%를 찾는 방법은 감이 아니라 측정이에요. 프로파일러를 돌려서 실제로 시간을 잡아먹는 지점을 찾은 다음, 거기를 손대면 됩니다.
Swift라면 이렇게 간단히 병목부터 확인할 수 있어요.
// 실제로 어느 코드가 시간을 잡아먹는지 측정
let clock = ContinuousClock()
let elapsed = clock.measure {
slowFunction()
}
print(elapsed) // 소요 시간이 큰 구간이 바로 그 '3%'
측정 결과를 보면 대부분 우리 예상이 빗나가요. “여기가 느릴 거야” 했던 곳은 멀쩡하고, 생각도 안 한 반복문 하나가 전체를 잡아먹고 있는 경우가 많아요.
조기 최적화와 정당한 최적화를 이렇게 구분하면 편해요.
| 구분 | 조기 최적화 | 정당한 최적화 |
|---|---|---|
| 시점 | 측정 전, 감으로 | 측정 후, 데이터로 |
| 대상 | 눈에 띄는 아무 곳 | 병목으로 확인된 3% |
| 결과 | 코드만 복잡해짐 | 실제 성능 개선 |
하나 더, 이 말은 사실 크누스 것이 아닐 수도 있어요
재미있는 뒷이야기가 있어요.
이 문장은 흔히 토니 호어(C. A. R. Hoare)의 말로도 인용돼요. 널리 쓰이는 인용 사이트에도 호어의 명언으로 올라와 있죠.
그런데 정작 크누스 본인은 1989년 글 “The Errors of TeX”에서 이걸 “호어의 격언(Hoare’s Dictum)“이라고 불렀어요.
호어는 또 자기가 한 말이 아니라 크누스가 한 말이라고 했고요.
두 대가가 서로 “네 말”이라고 미룬 셈인데, 문헌상 근거로는 1974년 논문에 처음 등장한 크누스의 표현으로 보는 게 정설이에요.
누가 먼저 했든, 중요한 건 원래 뜻이 반쪽으로 잘려 오해받고 있다는 점이에요.
자주 묻는 질문
Q. 그럼 처음부터 성능 신경 안 써도 되나요?
아니에요. 알고리즘 선택처럼 구조를 결정하는 판단은 처음부터 신경 써야 해요. 크누스가 잊으라고 한 건 ‘사소한’ 효율이지, 설계 수준의 결정이 아니에요.
Q. 측정은 언제 하나요?
동작하는 코드를 먼저 만든 다음이에요. 일단 돌아가게 만들고, 느리면 그때 프로파일러로 병목을 찾아 그 지점만 고치는 순서예요.
이 문장을 다시 만나면 이제 뒷부분까지 떠올려 보세요. 97%는 잊되, 3%는 놓치지 말라는 것.
측정 없이 손대는 최적화를 경계하되, 진짜 병목 앞에서는 물러서지 않는 것. 크누스가 진짜 하려던 말은 그거였어요.
오늘 코드에서 “왠지 느려 보여서” 손대려던 부분이 있다면, 프로파일러부터 한 번 돌려보시길 권해요.
