Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬에서 문자열을 클래스 객체로 변환하는 방법 완벽 정리


파이썬 함수에 사용자 입력으로 문자열이 주어졌을 때, 현재 정의된 네임스페이스에 해당 이름을 가진 클래스가 존한다면 그 문자열로부터 실제 클래스 객체를 얻어야 하는 경우가 있습니다. 이 글에서는 문자열을 파이썬 클래스 객체로 변환하는 여러 가지 방법과 각 방법의 장단점을 예제와 함께 살펴봅니다.

방법 1: eval() 함수 사용하기

가장 간단한 방법은 내장 함수 eval()을 사용하는 것입니다. eval()은 문자열을 파이썬 표현식으로 평가하여 그 결과를 반환합니다.

예제

class Foobar:
    pass

print(eval("Foobar"))
print(type(Foobar))

출력 결과

<class '__main__.Foobar'>
<class 'type'>

문자열 "Foobar"가 평가되어 Foobar 클래스 객체가 반환되는 것을 확인할 수 있습니다. 즉, 문자열 이름만으로도 해당 클래스에 접근할 수 있게 됩니다.

주의: eval()은 임의의 파이썬 코드를 실행할 수 있기 때문에 심각한 보안 위험을 초래할 수 있습니다. 사용자 입력을 그대로 eval()에 전달하면 악성 코드 실행으로 이어질 수 있으므로, 신뢰할 수 없는 입력에는 절대 사용해서는 안 됩니다.

방법 2: getattr()과 sys.modules 활용하기 (권장)

더 안전하고 권장되는 방법은 getattr()sys.modules를 조합하는 것입니다. 현재 모듈의 네임스페이스에서 문자열과 일치하는 이름의 클래스를 안전하게 조회할 수 있습니다.

예제

import sys

class Foobar:
    pass

def str_to_class(class_name):
    return getattr(sys.modules[__name__], class_name)

print(str_to_class("Foobar"))
print(type(Foobar))

출력 결과

<class '__main__.Foobar'>
<class 'type'>

sys.modules[__name__]는 현재 실행 중인 모듈 객체를 참조합니다. 여기에 getattr()을 적용하면 문자열로 지정한 이름의 클래스를 모듈에서 찾아 반환합니다. eval()과 달리 임의의 코드를 실행하지 않으므로 훨씬 안전합니다.

방법 3: globals()를 활용하기

현재 모듈의 전역 네임스페이스에서만 클래스를 찾으면 된다면 globals()를 사용하는 것도 간단한 대안입니다.

def str_to_class(name):
    return globals().get(name)

class Foobar:
    pass

class_obj = str_to_class("Foobar")
if class_obj is not None:
    instance = class_obj()
    print(instance)  # <__main__.Foobar object at 0x...>

globals().get()은 이름이 존재하지 않을 경우 예외를 발생시키지 않고 None을 반환하므로, 안전하게 처리할 수 있다는 장점이 있습니다.

실무에서 유용한 안전한 구현 팁

실제 프로젝트에서는 존재하지 않는 이름이나, 클래스가 아닌 함수·변수가 조회되는 상황까지 고려해야 합니다. 다음과 같이 검증 로직을 추가하면 더욱 견고한 코드를 작성할 수 있습니다.

import sys

def str_to_class(name):
    try:
        obj = getattr(sys.modules[__name__], name)
        if isinstance(obj, type):
            return obj
        raise ValueError(f"'{name}'은(는) 클래스가 아닙니다.")
    except AttributeError:
        raise ValueError(f"클래스 '{name}'을(를) 찾을 수 없습니다.")

또한 사용자 입력을 직접 받는 경우에는 화이트리스트 방식으로 허용된 클래스 이름인지 먼저 확인한 후 변환하는 것이 좋습니다.

정리

  • eval("클래스명"): 한 줄로 간단하지만 보안 위험이 커서 신뢰할 수 있는 환경에서만 사용해야 합니다.
  • getattr(sys.modules[__name__], "클래스명"): 안전하고 범용적이며 가장 권장되는 방법입니다.
  • globals().get("클래스명"): 현재 모듈의 전역 범위에서 간편하게 조회하며, 없는 이름도 안전하게 처리할 수 있습니다.

상황에 맞는 방법을 선택하되, 외부 입력을 다룰 때는 반드시 적절한 검증 절차를 거쳐 안전성을 확보하세요.