본문으로 바로가기

Zen of Python에서 배우는 교훈

Zen of Python을 알아보고, 파이썬에서 깔끔하고 우아한 코드를 작성하는 원칙을 살펴보세요.
업데이트됨 2026년 8월 31일  · 12분 읽다

AI로 탐색하기

ChatGPTClaudePerplexity

Zen of Python이란? 

Zen of Python은 파이썬 설계를 이끄는 열아홉 가지 격언 모음입니다. 원래는 스무 가지가 될 예정이었지만, 파이썬의 창시자인 Guido van Rossum이 Tim Peters(파이썬의 선을 만든 인물)가 의도한 마지막 격언을 아직 추가하지 않았습니다. Guido는 누락된 스무 번째 격언이 “Tim Peters의 괴상한 내부 농담”이라고 말했다고 전해집니다.

스무 번째 격언이 없었음에도, Zen of Python은 파이썬 프로그래머들의 개발 방식에 큰 영향을 미쳐 2004년에 PEP 20으로 표준화되었습니다. Zen of Python을 반드시 따라야 하는 것은 아니지만, 알고 마음에 새겨 두는 것을 권장합니다. 혹시 잊었다면 파이썬 인터프리터에서 import this를 실행해 쉽게 기억을 되살릴 수 있습니다. 

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

이 글에서는 각 교훈을 조금 더 자세히 살펴보겠습니다. 

#1 아름다움은 추함보다 낫다 

프로그래머라면 분명 높은 역량을 갖추고 계십니다. 코드를 통해 문제를 해결하는 일은 쉽지 않습니다. 하지만 파이써니스타라면 그 이상이 기대됩니다. 아름다운 코드는 추한 코드보다 낫습니다. 파이썬이 빠르게 각광받게 된 이유 중 하나는 접근성입니다. 파이썬은 단순하고, 읽기 쉽고, 우아합니다. 파이썬 개발자라면 아름다운 코드를 작성해 파이써닉한 기준을 지켜야 할 책임이 있습니다. 

그렇다면 아름다운 코드란 무엇일까요? 주관적일 수밖에 없습니다. 다만 간단한 원칙으로, 다른 개발자도 쉽게 이해할 수 있는 깔끔하고 읽기 쉬운 코드를 작성하는 것을 목표로 삼으세요. 예를 들면: 

"""
Initial code was created by Vishal Sharma
See:  https://towardsdatascience.com/the-zen-of-python-a-guide-to-pythons-design-principles-93f3f76d088a
"""
def collatz(num):
    if num % 2 == 0:
        return num // 2
    else:
        return 3 * num + 1

number = input("Enter a number: ")

while number != 1:
    number = collatz(int(number))
    print(number)

"""
Enter a number: 5
16
8
4
2
1
"""

위 코드는 잘 동작하지만 반드시 아름답지는 않습니다. collatz 함수의 불필요한 else 조건을 다음과 같이 제거할 수 있습니다. 

def collatz(num):
  if num % 2 == 0:
      return num // 2
 
  return 3 * num + 1

따라서 두 가지 모두 동작하는 코드가 있다면, 더 단순하고, 읽기 쉽고, 이해하기 쉬운 것을 선택하세요. 

#2 명시적인 것이 암시적인 것보다 낫다

어떤 격언을 “말 그대로 자명하다”라고 설명하는 건 큰 실수이지만, 여전히 그렇게 말하는 사람을 보게 됩니다. “명시적인 것이 암시적인 것보다 낫다”의 요지는 장황하더라도 간접적인 코드보다 낫다는 뜻입니다. 코드의 기능이 난해한 표현 뒤에 숨지 않도록 최선을 다하세요. 프로그램에 대한 사전 지식이 없는 사람도 코드에서 무슨 일이 일어나는지 이해할 수 있어야 합니다. 

#3 단순함은 복잡함보다 낫다

식사 후 접시를 씻으려고 고압세척기를 꺼내는 친구를 보면 아마 웃게 될 겁니다. 어리석은 해결책일 뿐 아니라 접시가 망가질 가능성도 큽니다. 마찬가지로, 단순한 문제에 지나치게 복잡한 해결책을 적용하는 건 매우 비실용적입니다. 똑똑해 보이려는 마음에 해결책을 과도하게 복잡하게 만들 필요는 없습니다. 오히려 해가 될 수 있으며, 파이썬에서는 환영받지 않습니다. 

문자열을 뒤집는 다음 함수를 보세요: 

def reverse_string(string):
    if len(string) == 1:
        return string
    else:
        return reverse_string(string[1:]) + string[0]


string = "kurtis"

print(reverse_string(string))

"""
sitruk
"""

문제는 해결하지만 불필요하게 복잡합니다. 파이썬에 익숙하다면 인덱싱으로 문자열을 뒤집을 수 있음을 알 것입니다. 

string = "kurtis"

# annonymous function solution
reverse_string = lambda x: x[::-1]

# function solution
def reverse(string):
    return string[::-1]

print(reverse_string(string))
print(reverse(string))

"""
sitruk
sitruk
"""

#4 복잡함은 난해함보다 낫다 

접시를 고압세척기로 씻는 건 비실용적이니 흐르는 수돗물 같은 단순한 방법이 낫습니다. 하지만 4x4 레인지로버를 청소해야 한다면 어떨까요? 앞선 격언과 이번 격언은 하나의 문제를 해결하는 데 단순한 방법과 복잡한 방법 모두가 쓰일 수 있음을 상기시킵니다. 4x4 레인지로버 청소는 단순한 문제가 아니며, 접시를 씻는 방식으로 시도할 수도 있지만 고압세척기를 쓰는 것보다 더 번거롭습니다. 즉, 가능하면 단순함을 선호하되, 단순함이 비실용적인 상황에서는 복잡함을 선택하는 편이 낫습니다. 단순함의 한계를 아세요. 

#5 평평함은 중첩보다 낫다 

프로그래머는 기능을 분리하기 위해 카테고리, 하위 카테고리, 하위 하위 카테고리로 조직화하는 것을 좋아합니다. 정돈되어 보이지만, 이런 방식은 정리보다 혼란을 키울 수 있습니다. 

모든 코드를 하나의 최상위 모듈에 두는 것도 나쁘지 않습니다. 즉, 특정 기능을 사용하기 위해 from spam.foo.bar.john.doe import chicken 처럼 할 필요가 없다는 뜻입니다. 하위 범주가 많아질수록 코드는 더 복잡해집니다. 가능하면 평평한 구조를 유지하도록 하세요.

#6 성김은 빽빽함보다 낫다

프로그래머는 똑똑한 사람으로 여겨집니다. 굳이 과도하게 공들인 해킹 기법으로 지능을 과시할 필요는 없습니다. 흔히 듣는 것이 “한 줄로 [아주 복잡한 작업]을 하는 법”입니다. 때로 원라이너가 타당할 때도 있지만, 모든 기능을 한 줄에 욱여넣느라 가독성을 희생하는 상황은 피하세요. 

예를 들어, 다음 코드를 보세요: 

"""
Code source Al Sweigart
See: https://inventwithpython.com/blog/author/al-sweigart.html0
"""
print('\n'.join("%i bytes = %i bits which has %i possible values." % (j, j*8, 256**j-1) for j in (1 << i for i in range(8))))
"""
1 bytes = 8 bits which has 255 possible values.
2 bytes = 16 bits which has 65535 possible values.
4 bytes = 32 bits which has 4294967295 possible values.
8 bytes = 64 bits which has 18446744073709551615 possible values.
16 bytes = 128 bits which has 340282366920938463463374607431768211455 possible values.
32 bytes = 256 bits which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values.
64 bytes = 512 bits which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values.
128 bytes = 1024 bits which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values.
"""

이 코드는 분명 동작하지만 이해하기가 매우 어렵습니다. 빽빽하고 읽기 힘듭니다. 

같은 코드를 성기게(덜 밀집되게) 작성하면 어떻게 보일까요? 

# Sparse example
bytes_and_bits = {j: j*8 for j in (1 << i for i in range(8))}

for bytes, bits in bytes_and_bits.items():
    print(f"{bytes} bytes = {bits} which has {256**bytes-1} possible values")

"""
1 bytes = 8 which has 255 possible values
2 bytes = 16 which has 65535 possible values
4 bytes = 32 which has 4294967295 possible values
8 bytes = 64 which has 18446744073709551615 possible values
16 bytes = 128 which has 340282366920938463463374607431768211455 possible values
32 bytes = 256 which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values
64 bytes = 512 which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values
128 bytes = 1024 which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values
"""

위 코드는 훨씬 읽기 쉽고, 원라이너와 정확히 같은 일을 합니다.

#7 가독성은 중요하다

이미 눈치채셨겠지만, 파이썬에서 가독성은 매우 중요합니다. 코드는 한 번 작성하면 되지만, 읽히는 건 여러 번일 가능성이 큽니다. 이를 고려하면 변수와 함수 이름에서 모음을 빼는 건 좋은 생각이 아닙니다. 예를 들어 create_lst와 create_list 중에서는 후자를 선택하세요. 

#8 특별한 예외가 규칙을 깨뜨릴 만큼 특별하지는 않다

파이썬[그리고 일반적인 프로그래밍]에는 지켜야 할 모범 사례가 많습니다. 종종 일관성 없고 읽기 어려운 코드로 이어지기 때문에, 자기 방식대로 하려 하기보다 모범 사례를 따르는 편이 낫습니다. 

#9 그러나 실용성은 순수함을 능가한다

아홉 번째 교훈은 여덟 번째의 연장선입니다. 모범 사례를 따르는 것이 좋지만, 규칙을 지키려다 오히려 읽기 어려운 코드가 될 수도 있습니다. 따라서 모든 규칙에는 예외가 있을 수 있습니다. 문제 해결 방식이 더 실용적이고 가독성이 좋으며 이해하기 쉽다면, 확립된 모범 사례에서 벗어나는 편이 더 낫습니다. 

#10 오류는 결코 조용히 지나가서는 안 된다 

조용한 오류란, 예외를 발생시키지 않고 오류 코드나 None을 반환하는 경우를 말합니다. 오류를 숨긴 채 계속 실행하는 것보다 프로그램이 차라리 크래시 나는 편이 낫습니다. 장기적으로 보면 오류를 묵살하면 고치기 훨씬 어려운 버그로 이어질 수 있습니다. 

#11 명시적으로 묵살하는 경우는 예외

열한 번째 교훈은 열 번째의 연장선입니다. 프로그램에서 발생한 오류를 무시하고 싶은 경우가 있을 수 있습니다. 그럴 때는 코드에서 오류를 명시적으로 묵살하는 것이 최선의 방법입니다. 

#12 애매함에 직면했을 때 추측하고 싶은 유혹을 뿌리쳐라

컴퓨터는 우리가 시킨 대로만 합니다. 코드가 의도대로 동작하지 않는다면, 그것은 코드가 여러분이 지시한 대로 동작하고 있기 때문입니다. 무작정 여러 가지 해결책을 시도하다가 하나가 맞는 듯하면 그걸로 끝내는 방식은 좋지 않습니다. 문제를 해결하기보다 가려버릴 수 있기 때문입니다. 유혹을 뿌리치고, 문제의 논리를 곰곰이 따져보고 비판적으로 사고해 적절한 해법을 찾으세요. 

#13 일을 하는 방법은 하나 — 바람직하게는 단 하나 — 가 명백해야 한다 

Perl 언어의 모토는 “한 가지 일을 하는 방법은 여럿 있다!”입니다. 선택지가 너무 많으면 선택 과부하가 생깁니다. 같은 목표를 이루는 코드도 여러 방식이 있을 때 비슷한 일이 벌어집니다. 코드를 작성하는 자유도는 커지지만, 이제 그 코드를 읽으려면 가능한 모든 방식을 알아야 합니다. 모든 경우의 수를 학습해야 하는 추가 작업은 불필요합니다. 

#14 하지만 그 방법은 처음엔 명백하지 않을 수 있다 — 네덜란드인이 아니라면

이 격언은 Tim Peters의 유머 감각을 보여줍니다. 파이썬의 창시자이자 평생 선의의 독재자(BDFL)였던 Guido van Rossum은 네덜란드인입니다. 파이썬의 언어 규칙을 이해하고 기억하는 일은 창시자를 제외한 모두에게 쉽지 않다는 점을 상기시키는 농담입니다. 

#15 지금 하는 것이 결코 안 하는 것보다 낫다

이 격언은 무한 루프에 빠지거나 멈춰버리는 코드가 그렇지 않은 코드보다 더 나쁘다는 뜻을 전합니다. 

#16 하지만 결코가 종종 바로 지금보다 낫다

열여섯 번째 교훈을 잇는 내용입니다. 프로그램이 실행을 마치길 기다리는 편이, 성급히 중단해 잘못된 결과를 얻는 것보다 낫습니다. 

#17 구현을 설명하기 어렵다면 나쁜 아이디어다

자기 구현을 자신만 이해하는 것으로는 충분하지 않습니다. “내가 말하려는 건 알아”로는 부족합니다. 프로그래밍은 팀 활동이며, 구현을 팀원에게 설명할 수 없다면 해결책을 지나치게 복잡하게 만든 가능성이 큽니다. 

#18 구현을 쉽게 설명할 수 있다면 좋은 아이디어일 수 있다

다만 쉽게 설명된다고 해서 반드시 좋은 코드라는 뜻은 아닙니다. 다만 설명이 쉬울수록 올바른 방향에 가까워졌다는 신호일 수 있습니다. 

#19 네임스페이스는 엄청 훌륭한 아이디어다 — 더 많이 활용하자!

네임스페이스는 파이썬에서 프로그램의 객체에 부여된 이름을 조직화하는 추상화입니다. 특정 네임스페이스와 스코프가 주어지면, 파이썬은 심볼릭 이름을 호출했을 때 어떤 객체를 가리키는지 결정할 수 있습니다. 이 격언이 말하는 바는, 파이썬이 내부적으로 심볼 이름을 조직하는 방식이 정말 멋지다는 것입니다. 

맺음말 

이 글에서는 파이썬 프로그래머가 깔끔하고 읽기 쉬운 코드를 작성하도록 이끄는 지침인 Zen of Python을 우리의 해석과 함께 살펴보았습니다. 어떤 이들은 Zen of Python을 매끄러운 코딩을 위한 최종 청사진으로 여기고, 다른 이들은 조금 가볍게 받아들입니다.  스스로의 코드에 이 원칙들을 적용해 보면 작업이 어떻게 개선되는지 직접 확인하실 수 있습니다.  최적화된 코드 작성에 대해 더 알아보고 싶다면 DataCamp의 Writing Efficient Python Code를 확인해 보세요.  

주제
Python
데이터 사이언스

DataCamp의 파이썬 코스 

courses

Python 입문

4
7M
Python을 활용한 데이터 분석 기초를 4시간 만에 마스터해 보세요. Python 인터페이스를 소개하고 많이 사용하는 대표 패키지를 함께 살펴보는 온라인 강의입니다.
자세히 보기Right Arrow
강좌 시작
더 보기Right Arrow