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

Java 본능 vs Python 본능

Java 에서 오면 본능이 "모든 거 클래스에 wrap". Python 문화는 반대로 밀어 — 함수와 모듈 먼저, 진짜 state 있을 때 클래스. __init__ 외 메서드 하나, 말할 만한 인스턴스 속성 X, 메서드 호출 위해서만 인스턴스화 — 함수여야.

클래스 안 필요한 신호

(1) __init__ 외 메서드 하나만. (2) __init__ 이 변환 없이 인자 그냥 저장. (3) 클래스가 인스턴스화, 메서드 호출, 인스턴스 폐기. (4) 클래스에 state 변경 메서드 X. 넷 다 — 함수 짜. 4 중 3 — 아마 함수.

모듈이 네임스페이스

Java 에서 관련 함수 그룹핑 위해 static method 가진 클래스 사용 가능. Python 에선 모듈 자체가 네임스페이스. my_module.py 에 관련 함수 그룹핑, caller 가 from my_module import f, g. 클래스 불필요. Python stdlib 의 os, math, json 모듈이 정확히 이거.

클래스가 *맞는* 답일 때

공유 state 에 작동하는 메서드 여러 개 가진 stateful 객체. 다형성 원할 때 (같은 인터페이스 여러 구현). 시간 동안 identity 가진 거 모델링 (연결, 세션, stateful 처리기). 클래스가 여기 맞는 도구 — 근데 각 조건이 진짜, 가정 X.

원칙: 함수로 시작. 함수가 지속 state, state 공유 메서드 여러 개, 또는 다형 동작 발달할 때만 클래스로 승격. 클래스에서 함수로 강등이 반대보다 어려움 — 단순하게 시작 + 단순한 형태가 진짜 안 맞을 때만 자라.

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")
클래스가 값어치 할 때 — 진짜 state·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 가 맞는 모양.
Closure — 가끔 가벼운 대안·python
# state 필요한데 메서드 여러 개 X? 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

URLBuilder 클래스 — __init__(self, base)base 저장 + 메서드 build(path: str) -> strf"{base}/{path}" 반환. 함수로 변환. 클래스 형태가 맞는 선택일 때 (있다면) 논의. 그 다음 이 클래스를 다른 극단으로 — 클래스 형태가 명확히 맞을 때까지 state + 메서드 여러 개로 확장.

Progress

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

댓글 0

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

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