본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

클래스를 쓰지 않는 편이 나은 순간

~15 min · class, function, module, anti-pattern

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

Python에서는 함수와 모듈로 시작하고 지속되는 상태가 있을 때 클래스로 자라는 편이 자연스러워. 초기화 말고 메서드가 하나뿐이고 인자를 저장했다가 한 번 호출하고 버리는 객체라면 함수일 가능성이 커.

관련 함수의 이름공간이 필요하다는 이유만으로 정적 메서드 클래스를 만들 필요도 없어. Python 모듈 자체가 이름공간이고 os·math·json이 그 모양을 보여줘. 클로저도 작은 상태를 감추는 가벼운 선택지가 될 수 있어.

여러 메서드가 같은 상태의 규칙을 지키거나, 같은 인터페이스의 여러 구현이 필요하거나, 시간 속 정체성을 모델링한다면 클래스가 값을 해. 객체지향을 중요하게 본다고 모든 계산을 클래스로 감싸는 건 아니야. 순수 함수는 객체들이 주고받는 메시지를 더 선명하게 만들 수 있어.

Code

함수면 충분한 클래스·python
# UNPYTHONIC — __init__ 와 메서드 하나만 가진 클래스
class EmailValidator:
    def __init__(self, email):
        self.email = email

    def is_valid(self):
        return "@" in self.email and "." in self.email.split("@")[1]

result = EmailValidator("alice@example.com").is_valid()

# PYTHONIC — 함수
def is_valid_email(email):
    return "@" in email and "." in email.split("@")[1]

result = is_valid_email("alice@example.com")
# 같은 로직, 단순한 호출 사이트, 테스트 쉬움, 재사용 쉬움
모듈을 이름공간으로 쓰기·python
# UNPYTHONIC — 헬퍼 그룹핑 위해 static 메서드만 가진 클래스
class StringHelpers:
    @staticmethod
    def slugify(s):
        return s.lower().replace(" ", "-")
    @staticmethod
    def truncate(s, n):
        return s if len(s) <= n else s[:n-3] + "..."

from my_helpers import StringHelpers
result = StringHelpers.slugify("Hello World")

# PYTHONIC — 모듈 레벨 함수
# string_helpers.py
def slugify(s):
    return s.lower().replace(" ", "-")
def truncate(s, n):
    return s if len(s) <= n else s[:n-3] + "..."

from string_helpers import slugify, truncate
result = slugify("Hello World")
지속 상태가 클래스를 정당화하는 경우·python
# state 공유 메서드 여러 개 가진 stateful 객체 — 클래스가 맞음
class Counter:
    def __init__(self):
        self.count = 0
        self.history = []

    def increment(self):
        self.count += 1
        self.history.append(("increment", self.count))

    def reset(self):
        self.history.append(("reset", self.count))
        self.count = 0

    def report(self):
        return f"count={self.count}, history={len(self.history)} ops"

# 시간 동안 변하는 두 속성 공유하는 세 메서드.
# 함수면 어색 — Counter 가 맞는 모양.
클로저라는 가벼운 대안·python
# state는 필요한데 메서드는 하나뿐이면 closure가 맞아
def make_counter(start=0):
    count = [start]                     # closure 의 변경 위해 list
    def increment():
        count[0] += 1
        return count[0]
    return increment

c = make_counter()
print(c())     # 1
print(c())     # 2
print(c())     # 3

# 또는 nonlocal 로
def make_counter_v2(start=0):
    count = start
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

External links

Exercise

base를 저장하고 build(path) 하나만 제공하는 URLBuilder를 함수로 바꿔. 원래 클래스가 맞을 조건을 논의한 뒤, 지속 상태와 여러 메서드가 실제로 필요하도록 확장해 클래스가 자연스러운 반대 사례도 만들어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.