[8편] AI 프로젝트의 품질을 결정짓는 파이썬 객체지향 프로그래밍(OOP) 기초 (클래스 & 상속)
시리즈를 이어오며 리스트 컴프리헨션, 람다, 제너레이터 등 파이썬을 한층 더 '파이썬답게' 만드는 고급 문법들을 다루었습니다. 이제 파이썬 심화 과정의 마지막 관문이자, 수천 줄에 달하는 AI 프로젝트의 뼈대를 만드는 객체지향 프로그래밍(OOP, Object-Oriented Programming)의 세계로 들어섭니다.
처음 AI 코딩을 시작할 때는 수식이나 데이터 전처리 코드를 파일 하나에 순서대로 죽 늘어놓는 '절차적 방식'만으로도 충분해 보입니다. 하지만 모델의 종류가 늘어나고, 전처리 과정이 복잡해지며, 여러 사람과 협업해야 하는 실무 환경에 다다르면 코드가 거대한 '엉킨 실타래'처럼 변해버립니다. 변수 이름 하나를 바꿨을 뿐인데 코드 전체에서 에러가 터지는 비극을 겪게 되는 것입니다.
나 역시 초창기 인공지능 프로젝트를 진행할 때 모든 기능과 수식을 단일 파이썬 파일에 작성했던 경험이 있습니다. 실험을 거듭하며 모델 구조를 수정할 때마다 코드를 처음부터 다시 읽고 복사-붙여넣기를 반복하느라 수많은 밤을 지새웠습니다. 그러다 PyTorch나 Hugging Face 같은 거대 오픈소스 프레임워크의 내부 코드가 모두 깔끔한 '클래스(Class)'와 '상속(Inheritance)' 구조로 설계되어 있다는 점을 깨닫고 OOP를 도입했습니다. 그 결과, 새로운 실험을 추가하는 속도가 수 배 이상 빨라졌습니다. 오늘 8편에서는 AI 개발자가 반드시 알아야 할 클래스와 상속의 핵심 개념을 정리해 드립니다.
1. 붕어빵 틀과 붕어빵: 클래스(Class)와 인스턴스(Instance)
객체지향 프로그래밍을 가장 쉽게 이해하는 비유는 '붕어빵 틀(Class)'과 '붕어빵(Instance)'입니다.
클래스 (Class): 객체를 만들어내기 위한 '설계도' 또는 '틀'입니다. 데이터(변수)와 해당 데이터를 다루는 기능(메서드/함수)을 하나로 묶어 정의합니다.
인스턴스 (Instance): 클래스라는 설계도를 바탕으로 실제 메모리에 생성된 '실체(객체)'입니다. 하나의 클래스로 서로 다른 데이터를 가진 수많은 인스턴스를 만들어낼 수 있습니다.
실무 AI 코드에서의 클래스
AI 분야에서 클래스는 주로 '하나의 독립된 신경망 모델'이나 '특정 데이터 전처리 모듈'을 정의할 때 사용됩니다.
class SimpleDataCleaner:
# 생성자: 객체가 만들어질 때 초기 설정을 담당 (self는 자기 자신을 가리킴)
def __init__(self, target_column):
self.target_column = target_column
# 데이터 정제 메서드
def remove_missing_values(self, df):
print(f"[{self.target_column}] 컬럼의 결측치를 제거합니다.")
return df.dropna(subset=[self.target_column])
# 클래스를 이용해 실제 정제 도구(인스턴스) 생성
cleaner = SimpleDataCleaner(target_column="age")
2. 코드 재사용성의 꽃: 상속 (Inheritance)
상속은 부모 클래스가 가지고 있는 변수와 메서드를 자식 클래스가 그대로 물려받아 사용하는 개념입니다.
왜 상속을 써야 할까?
공통적으로 사용되는 기본 기능(데이터 로딩, 학습 결과 출력 등)은 부모 클래스에 한 번만 작성해 두고, 새로운 모델이나 특수한 기능이 필요할 때 이를 상속받아 자식 클래스에서 필요한 부분만 확장하거나 재정의(Overriding)하면 됩니다. 이렇게 하면 중복 코드가 획기적으로 줄어들고 유지보수가 매우 쉬워집니다.
PyTorch 모델 정의의 핵심 메커니즘
딥러닝 프레임워크인 PyTorch에서 신경망을 만들 때 사용하는 표준 방식이 바로 이 '상속'입니다. PyTorch가 미리 만들어둔 기본 모델 틀(nn.Module)을 상속받아, 나만의 인공지능 모델 구조를 정의합니다.
# PyTorch의 기초가 되는 상속 구조 예시 개념
class BaseNeuralNetwork:
def __init__(self):
self.is_trained = False
def summary(self):
print("이 모델은 기본적인 인공지능 신경망 구조입니다.")
# BaseNeuralNetwork를 상속받는 자식 클래스
class CustomCNNModel(BaseNeuralNetwork):
def __init__(self, num_classes):
super().__init__() # 부모 클래스의 초기화 메서드 호출
self.num_classes = num_classes
# 부모의 summary 메서드를 나만의 방식으로 재정의 (오버라이딩)
def summary(self):
print(f"이 모델은 {self.num_classes}개 클래스를 분류하는 이미지 인식 CNN 모델입니다.")
model = CustomCNNModel(num_classes=10)
model.summary() # "이 모델은 10개 클래스를 분류하는 이미지 인식 CNN 모델입니다." 출력
3. 캡슐화(Encapsulation)로 코드의 안정성 확보하기
객체지향의 또 다른 중요한 특징은 '캡슐화'입니다. 변수나 중요 로직을 클래스 내부에 숨기고 외부에서 함부로 접근하여 값을 수정하지 못하도록 보호하는 기술입니다.
파이썬에서는 변수 이름 앞에 언더스코어 2개(__)를 붙여 클래스 외부에서 데이터가 직접 수정되는 것을 막을 수 있습니다. AI 개발 시 학습률(Learning Rate)이나 가중치(Weight) 값이 사용자의 실수로 외부에 의해 무단으로 변경되어 학습이 망가지는 현상을 예방할 때 유용하게 쓰입니다.
4. 클래스 설계 시 입문자가 자주 범하는 실수 2가지
self키워드 누락 및 오용:파이썬 클래스 내부에서 메서드를 선언할 때는 첫 번째 매개변수로 반드시
self를 적어주어야 합니다. 또한 클래스 내부의 변수에 접근할 때self.variable_name형태가 아닌 일반 변수명만 사용하면 인스턴스 변수로 인식되지 않고 에러가 발생합니다.모든 코드를 클래스로 만들려는 과유불급:
클래스가 무조건 좋은 것은 아닙니다. 단순히 수식 하나를 계산하거나 파일 경로를 변경하는 단발성 작업까지 굳이 클래스로 감싸면 오히려 구조가 복잡해지고 가독성이 떨어집니다. 한 번 쓰이고 버려지는 단순 로직은 일반 함수로 구현하는 것이 바람직합니다.
핵심 요약
클래스(Class)는 데이터와 기능을 하나로 묶는 설계도이며, 이를 바탕으로 실제 사용 가능한 인스턴스(Instance)를 생성합니다.
상속(Inheritance)을 활용하면 기존 코드를 재사용하여 중복을 줄이고, 나만의 인공지능 모델이나 전처리기를 쉽게 확장할 수 있습니다.
PyTorch 등 주요 AI 프레임워크의 코드는 상속과 클래스 구조를 기반으로 설계되어 있으므로, OOP 기초를 이해하는 것이 AI 라이브러리 활용의 필수 조건입니다.
댓글
댓글 쓰기