[Python] classmethod는 언제 사용해?
Python @classmethod 실습 중심 가이드
이 글은 Python의 @classmethod를 인스턴스 메서드, 정적 메서드와 비교하면서, 실습 위주로 이해할 수 있도록 정리한 가이드입니다.
1. 메서드 3종류 큰 그림
Python 클래스에서 자주 사용하는 메서드는 세 가지입니다.
- 인스턴스 메서드
@classmethod가 붙은 클래스 메서드@staticmethod가 붙은 정적 메서드
class Demo:
def instance_method(self):
print("인스턴스 메서드, self =", self)
@classmethod
def class_method(cls):
print("클래스 메서드, cls =", cls)
@staticmethod
def static_method():
print("정적 메서드, self/cls 없음")
obj = Demo()
obj.instance_method()
Demo.class_method()
Demo.static_method()
- 인스턴스 메서드: 첫 인자
self, 개별 객체 상태를 다룸 - 클래스 메서드: 첫 인자
cls, 클래스 자체를 다룸 - 정적 메서드: 첫 인자 없음, 클래스/인스턴스와 무관한 순수 함수
2. @classmethod 한 줄 정의
@classmethod는
“첫 번째 인자로 클래스 객체(cls)를 받는 메서드”입니다.
실무에서는 주로 “대체 생성자(Alternative Constructor)”를 만들 때 자주 사용합니다.
3. 기본 예제 – 문자열로부터 인스턴스 생성
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_string(cls, text):
name, age = text.split(",")
return cls(name, int(age))
p1 = Person("Alice", 30)
p2 = Person.from_string("Bob,25")
print(p1.name, p1.age)
print(p2.name, p2.age)
from_string은 문자열을 파싱해서 cls(...)를 호출하고,
새 인스턴스를 만들어 반환하는 “대체 생성자”입니다.
4. 왜 cls가 중요한가?
단순히 Person(...)를 직접 호출해도 동작은 하지만,
상속을 고려하면 문제가 생길 수 있습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_string(cls, text):
name, age = text.split(",")
return cls(name, int(age))
class Employee(Person):
def __init__(self, name, age, company):
super().__init__(name, age)
self.company = company
이제 다음을 호출한다고 가정해봅시다.
e = Employee.from_string("Carol,40")
from_string은Person에 정의되어 있지만,cls에는 실제로Employee클래스가 전달됩니다.- 따라서
return cls(...)는Employee(...)를 호출하게 됩니다.
Person(...) 대신 cls(...)로 작성하는 것이 훨씬 안전하고 확장성이 좋습니다.
5. @staticmethod와 비교하기
클래스 메서드와 정적 메서드는 특히 헷갈리기 쉬우므로, 예제를 통해 비교해 봅니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def is_adult(age):
return age >= 18
@classmethod
def from_string(cls, text):
name, age = text.split(",")
return cls(name, int(age))
p = Person.from_string("Alice,30")
print(Person.is_adult(p.age))
is_adult: 나이 숫자만 보고 판단 → 클래스/인스턴스 상태와 무관 →@staticmethod적합from_string: 새 인스턴스를 돌려주는 대체 생성자 →cls필요 →@classmethod적합
6. 동작 원리 – classmethod() 함수
@classmethod도 데코레이터 문법의 축약형입니다.
class Person:
@classmethod
def from_string(cls, text):
...
위 코드는 다음과 동등합니다.
class Person:
def from_string(cls, text):
...
from_string = classmethod(from_string)
classmethod() 빌트인 함수는 해당 함수를
“첫 번째 인자로 인스턴스가 아니라 클래스(cls)를 받는 메서드”로 감싸 줍니다.
7. 실습 1 – 다양한 생성 경로 만들기
class MyDate:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, text):
# "2025-12-31"
year, month, day = text.split("-")
return cls(int(year), int(month), int(day))
@classmethod
def today(cls):
# 예시: 실제로는 datetime 등을 사용할 수 있음
return cls(2025, 1, 1)
d1 = MyDate(2025, 12, 31)
d2 = MyDate.from_string("2025-12-31")
d3 = MyDate.today()
print(d1.year, d1.month, d1.day)
print(d2.year, d2.month, d2.day)
print(d3.year, d3.month, d3.day)
이렇게 여러 생성 방식(생성자 스타일)을 한 클래스 안에 모아두는 것이
@classmethod 사용의 대표적인 패턴입니다.
8. 실습 2 – 상속 + @classmethod
class Shape:
def __init__(self, name):
self.name = name
@classmethod
def from_config(cls, config):
return cls(config["name"])
class Circle(Shape):
def __init__(self, name, radius):
super().__init__(name)
self.radius = radius
@classmethod
def from_config(cls, config):
obj = super().from_config(config) # 여기서도 cls는 Circle
obj.radius = config["radius"]
return obj
c = Circle.from_config({"name": "my-circle", "radius": 10})
print(c.name, c.radius)
부모 클래스의 @classmethod를 재사용하면서,
자식 클래스에서 필요한 정보를 추가로 설정할 수 있습니다.
9. 언제 @classmethod를 쓰면 좋은가?
- 문자열, 딕셔너리, 파일, 환경 변수 등 다양한 입력으로 인스턴스를 만들고 싶을 때
- 상속 구조에서 공통 생성 로직을 부모 클래스에 두고 재사용하고 싶을 때
- 클래스 단위로 관리되는 설정/리소스를 생성/초기화하는 팩토리를 만들 때
@staticmethod가 더 어울리며,
인스턴스 상태를 다루는 로직은 일반 인스턴스 메서드가 더 적합합니다.
10. 정리 – 세 가지 메서드 비교
- 인스턴스 메서드:
self, 개별 객체 상태를 다룸 - 클래스 메서드 (@classmethod):
cls, 대체 생성자 / 클래스 단위 로직 / 상속 고려 - 정적 메서드 (@staticmethod): 인스턴스/클래스 모두와 무관한 순수 함수
11. 연습 문제
연습 1 – User.from_string
User 클래스를 만들고 다음을 구현해 보세요.
__init__(self, name, age)@classmethod from_string(cls, text)–"이름:나이"형식 문자열로부터 인스턴스 생성
연습 2 – Config.from_dict / Config.default
Config 클래스를 만들고:
@classmethod from_dict(cls, d)– 딕셔너리 기반 생성@classmethod default(cls)– 기본값을 가진 설정 인스턴스 생성
나중에 AppConfig 같은 서브클래스를 만들어,
부모의 @classmethod를 재사용해 보는 것도 좋은 연습입니다.