
파이썬은 전통적으로 '덕 타이핑(Duck Typing)'의 언어였습니다. "오리처럼 걷고 오리처럼 운다면 그것은 오리다"라는 철학은 유연한 개발을 가능하게 했지만, 대규모 프로젝트에서는 정적 분석의 어려움이라는 문제를 야기했습니다. 이를 해결하기 위해 등장한 것이 바로 PEP 544의 Protocol입니다. 본 글에서는 전문가의 시각에서 구조적 타이핑(Structural Typing)을 구현하는 구체적인 방법과 기존 추상 베이스 클래스(ABC)와의 결정적 차이를 분석합니다.
1. 구조적 타이핑(Structural Typing)이란 무엇인가?
일반적인 자바나 C#의 인터페이스는 '명시적 타이핑(Nominal Typing)'을 따릅니다. 즉, 클래스가 특정 인터페이스를 구현한다고 선언해야만 해당 타입으로 인정받습니다. 반면, 파이썬의 typing.Protocol은 클래스가 특정 메서드나 속성을 가지고 있기만 하면 별도의 상속 선언 없이도 해당 타입으로 간주합니다.
이 방식은 코드 간의 결합도를 낮추면서도 mypy와 같은 정적 검사 도구를 통해 타입 안정성을 확보할 수 있는 '해결'책이 됩니다.
2. Protocol vs ABC: 구현 방식의 3가지 핵심 차이
많은 개발자가 abc.ABC와 typing.Protocol 사이에서 혼란을 겪습니다. 두 방식의 기술적 차이를 명확히 이해하는 것이 중요합니다.
| 비교 항목 | 명시적 타이핑 (ABC) | 구조적 타이핑 (Protocol) |
|---|---|---|
| 상속 관계 | 반드시 부모 클래스를 상속해야 함 | 상속 없이 메서드 일치만으로 성립 |
| 런타임 체크 | isinstance() 체크 시 상속 계층 확인 | @runtime_checkable 사용 시 속성 확인 |
| 유연성 | 서드파티 라이브러리 수정이 어려움 | 외부 라이브러리 객체에도 즉시 적용 가능 |
| 정적 분석 | 상속 관계를 기반으로 검사 | 메서드 시그니처 일치 여부로 검사 |
3. 실전 Sample Example: Protocol 구현 방법
다음은 현대적인 파이썬 환경에서 Protocol을 사용하여 다양한 형태의 저장소 객체를 동일한 타입으로 처리하는 해결 방법 예제입니다.
from typing import Protocol, runtime_checkable
@runtime_checkable
class Document(Protocol):
"""문서 객체가 갖춰야 할 구조 정의"""
title: str
def save(self) -> str:
...
class PDFFile:
def __init__(self, title: str):
self.title = title
def save(self) -> str:
return f"PDF '{self.title}' 저장 완료"
class WordFile:
def __init__(self, title: str):
self.title = title
def save(self) -> str:
return f"Word '{self.title}' 저장 완료"
def process_document(doc: Document):
"""Document 프로토콜을 준수하는 어떤 객체든 수용 가능"""
print(doc.save())
# 사용 예시
pdf = PDFFile("Python_Guide")
word = WordFile("Note_2026")
process_document(pdf) # 상속 관계가 없어도 정상 작동
process_document(word) # Duck Typing의 정적 버전
위 코드에서 PDFFile과 WordFile은 Document를 상속받지 않았음에도 불구하고, save 메서드와 title 속성을 가졌기에 Document 타입으로 인정받습니다.
4. @runtime_checkable을 통한 런타임 문제 해결
기본적으로 Protocol은 정적 검사 시에만 유효합니다. 하지만 isinstance()를 통해 실행 시점에도 해당 타입을 검증하고 싶다면 @runtime_checkable 데코레이터를 사용해야 합니다. 이는 런타임에 객체의 메서드 존재 여부를 검사하는 로직을 자동으로 주입하여 안정성을 높여줍니다.
5. 결론: 왜 Protocol을 사용해야 하는가?
PEP 544의 도입은 파이썬을 진정한 '점진적 타이핑(Gradual Typing)' 언어로 완성시켰습니다. 클래스 계층 구조를 복잡하게 설계하지 않고도 필요한 기능을 인터페이스화할 수 있는 Protocol은 특히 대규모 시스템의 리팩토링과 테스트 코드 작성 시 강력한 힘을 발휘합니다. 코드의 유연성과 안정성이라는 두 마리 토끼를 잡고 싶다면 지금 즉시 Protocol 기반의 설계를 도입해 보시기 바랍니다.
'Artificial Intelligence > 60. Python' 카테고리의 다른 글
| [PYTHON] 메모리 효율을 극대화하는 제너레이터와 이터레이터의 3가지 핵심 프로토콜 차이와 활용 방법 (0) | 2026.03.02 |
|---|---|
| [PYTHON] yield from 구문이 재귀적 제너레이터 구조에서 해결하는 3가지 복잡성 문제와 최적화 방법 (0) | 2026.03.02 |
| [PYTHON] nonlocal 키워드와 global 키워드의 3가지 스코프 제어 차이와 변수 오염 해결 방법 (0) | 2026.03.02 |
| [PYTHON] 익명 lambda 함수가 일반 함수 객체로 처리되는 3가지 내부 메커니즘과 차이점 해결 방법 (0) | 2026.03.02 |
| [PYTHON] 내부 동작의 핵심 : Frame Object와 실행 컨텍스트의 3가지 밀접한 관계와 구조적 차이 해결 (0) | 2026.03.01 |