Python for AI, Embedded/Python: Core & Automation

파이썬(Python) 객체지향 프로그래밍(OOP) 기초: 클래스와 객체 정의부터 상속, 다형성 개념 총정리

임베디드 친구 2025. 7. 1. 19:39
반응형

지난 시간까지 우리는 파이썬의 강력한 내장 고급 함수들과 나만의 함수를 설계하는 심화 테크닉들을 살펴보았습니다. 지금까지 배운 방식이 단순히 명령어를 순서대로 나열하거나 함수를 호출하는 '절차적·기능적 프로그래밍'에 가까웠다면, 이제는 프로그램의 규모가 커져도 끄떡없이 버틸 수 있는 단단한 뼈대를 세울 차례입니다. 현대 소프트웨어 아키텍처의 중심에는 현실 세계의 개념을 코드 안으로 그대로 투영하는 '객체지향 프로그래밍(OOP)' 패러다임이 자리 잡고 있습니다. 데이터를 담는 변수와 그 데이터를 요리하는 함수들을 하나의 독립된 덩어리로 묶어 관리하면, 코드의 재사용성과 유지보수성이 놀라울 정도로 향상됩니다. 파이썬 개발자라면 반드시 거쳐 가야 할 관문인 클래스와 객체의 기초부터 상속, 다형성의 비밀까지 소프트웨어 공장에서 명쾌하게 풀어드리겠습니다.

Generated by Gemini AI.

📌 핵심 요약 3줄

  • 클래스(Class)는 객체를 찍어내기 위한 세상에 단 하나뿐인 설계도(Blueprint)이며, 객체(Object)는 그 설계도를 기반으로 메모리에 실체화된 제품입니다.
  • __init__ 생성자 메서드를 통해 객체의 고유한 속성(Attribute)을 초기화하고, 클래스 내부의 함수인 메서드(Method)로 객체의 행동을 정의합니다.
  • 상속(Inheritance)을 통해 기존 코드를 그대로 물려받아 재사용하고, 다형성(Polymorphism)을 이용해 동일한 인터페이스로 서로 다르게 동작하는 유연한 코드를 구현합니다.

1. 한눈에 보는 객체지향(OOP) 핵심 개념 구조

객체지향 세계관을 관통하는 가장 중요한 핵심 어휘들과 관계성을 표로 정리했습니다.

📊 클래스/객체 및 OOP 핵심 메커니즘 요약

용어 및 개념 비유적 표현 핵심 역할 및 특징 관계성 및 비고
클래스 (Class) 건축 설계도, 붕어빵 틀 데이터 구조(속성)와 행동(메서드)을 정의하는 상위 개념 객체를 생성하는 가이드라인
객체 (Object) 실제 건축물, 붕어빵 클래스를 기반으로 실제 메모리에 할당되어 살아 움직이는 실체 인스턴스(Instance)라고도 부름
상속 (Inheritance) 유산 물려받기, 확장 설계 부모 클래스의 모든 기능을 자식 클래스가 그대로 이어받는 기법 코드 중복을 제거하는 핵심 도구
다형성 (Polymorphism) 하나의 버튼, 다양한 반응 동일한 이름의 메서드가 객체의 종류에 따라 각자 다르게 동작하는 성질 오버라이딩(Method Overriding)으로 구현

2. 클래스 정의와 객체 생성의 실전 메커니즘

파이썬에서 클래스는 class 키워드로 선언하며, 클래스 내부에서 정의된 모든 메서드는 자기가 자기 자신을 가리키는 첫 번째 인자인 self를 반드시 품고 있어야 합니다.

Python
 
# 자동차 설계도(클래스) 작성
class Car:
    # 생성자 메서드: 객체가 태어날 때 속성을 부여함
    def __init__(self, color, model):
        self.color = color  # 인스턴스 속성(변수)
        self.model = model

    # 객체의 행동을 정의하는 메서드
    def drive(self):
        print(f"{self.color} {self.model}가 도로 위를 주행 중입니다.")

# 설계도를 바탕으로 서로 다른 실체(객체) 생성
my_car = Car("빨간색", "소나타")
family_car = Car("흰색", "카니발")

# 각 객체의 메서드 호출
my_car.drive()      # 출력: 빨간색 소나타가 도로 위를 주행 중입니다.
family_car.drive()  # 출력: 흰색 카니발가 도로 위를 주행 중입니다.

3. 상속(Inheritance)과 다형성(Polymorphism) 마스터하기

상속을 이용하면 부모의 기능을 물려받은 뒤 나만의 독창적인 기능을 덧붙이거나(Extends), 부모의 특정 기능을 내 입맛에 맞게 바꾸어 쓰는 재정의(Overriding)가 가능해집니다. 이를 활용하면 자연스럽게 다형성이라는 아름다운 구조가 완성됩니다.

Python
 
# 부모 클래스 (기본 뼈대)
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        print(f"{self.name}이(가) 소리를 냅니다.")

# 자식 클래스 1 (Animal 상속)
class Cat(Animal):
    # 부모의 speak 메서드를 내 방식대로 재정의 (오버라이딩)
    def speak(self):
        print(f"{self.name}이(가) 야옹 하고 소리를 냅니다.")

# 자식 클래스 2 (Animal 상속)
class Dog(Animal):
    def speak(self):
        print(f"{self.name}이(가) 멍멍 짖습니다.")

# 다형성의 실전 활용 시나리오
# 형태는 다르지만 모두 'Animal'이라는 공통 분모를 가진 객체들의 집합
zoo = [Cat("나비"), Dog("바둑이"), Cat("치즈")]

for animal in zoo:
    # 호출하는 명령어(speak)는 단 하나로 똑같지만, 객체의 실체에 따라 결과가 다르게 나타남!
    animal.speak()
# 출력 결과:
# 나비이(가) 야옹 하고 소리를 냅니다.
# 바둑이이(가) 멍멍 짖습니다.
# 치즈이(가) 야옹 하고 소리를 냅니다.

4. 개발을 위한 팁

  • 객체(Object)와 인스턴스(Instance)의 미묘한 뉘앙스 차이 구별하기: 실무에서 혼용해서 쓰이지만 엄밀히 따지면 관점의 차이입니다. my_car는 독립된 하나의 객체입니다. 하지만 클래스와의 관계성을 묶어서 표현할 때는 "my_car는 Car 클래스의 인스턴스다"라고 부릅니다. 즉, 실체 그 자체에 집중하면 객체, 누구로부터 태어났는지 출처에 집중하면 인스턴스라고 이해하시면 명확합니다.
  • 부모의 메서드를 완전히 버리지 않고 일부만 확장할 때는 super()를 소환하세요: 자식 클래스에서 메서드를 오버라이딩할 때, 부모 클래스가 기존에 가지고 있던 로직을 완전히 새로 짜는 것은 비효율적입니다. 부모의 로직을 그대로 실행하면서 내 행동을 한 줄만 추가하고 싶다면 super().speak() 처럼 super() 키워드를 사용하여 부모의 원래 메서드를 원격 호출해 준 뒤 내 코드를 덧붙이는 것이 확장성 측면에서 훨씬 우수합니다.

5. 흔히 하는 실수

  • 메서드 정의 시 단골로 빠뜨리는 self 매개변수 에러: 파이썬 클래스 내부에서 함수를 만들 때 첫 번째 인자로 self를 적지 않으면, 나중에 객체를 만들고 메서드를 실행할 때 TypeError: method() takes 0 positional arguments but 1 was given이라는 에러를 마주하게 됩니다. 파이썬은 객체가 메서드를 호출할 때 자동으로 자기 자신의 주소값을 첫 번째 인자로 밀어 넣기 때문에, 클래스 내부에 정의하는 모든 인스턴스 메서드는 무조건 self를 첫 번째 방에 적어주어야 구조가 뒤틀리지 않습니다.
  • 상속 관계에서 부모 생성자(__init__) 호출을 누락하는 경우: 부모 클래스에도 생성자가 있고 자식 클래스에도 생성자를 따로 만들 때, 자식 생성자 내부에서 부모의 생성자를 명시적으로 실행해 주지 않으면 부모가 정의해 둔 초기 속성값들이 자식 객체에 전해지지 않습니다. 이 상태에서 부모의 변수에 접근하려 하면 AttributeError가 발생하므로, 자식 생성자를 설계할 때는 가장 먼저 super().__init__(arguments)를 호출하여 부모의 방 먼저 깔끔하게 인테리어해 주는 규칙을 지켜야 합니다.
Python
 
# [올바른 자식 클래스 생성자 설계 패턴]
class ElectricCar(Car):
    def __init__(self, color, model, battery_capacity):
        super().__init__(color, model)  # 부모의 속성인 color, model을 먼저 안전하게 등록!
        self.battery_capacity = battery_capacity  # 내 고유 속성 등록

💡 맺음말

이번 포스팅에서는 파이썬의 객체지향 프로그래밍(OOP) 패러다임의 입문 단계인 클래스와 객체의 개념적 원리부터 상속과 다형성을 이용한 코드 재사용 아키텍처까지 꼼꼼하게 마스터해 보았습니다. 데이터를 꽁꽁 싸매고 행동을 부여하는 이 OOP의 매커니즘을 손에 익히면, 거대하고 복잡한 웹 프레임워크나 오픈소스 라이브러리의 내부 코드가 서서히 읽히기 시작하는 놀라운 경험을 하시게 될 것입니다.

파이썬의 구조적 기본기가 한 단계 완벽하게 격상되었습니다!

클래스 인스턴스 생성 중 self 매핑 오류가 나거나 오버라이딩 도중 부모 클래스 참조 에러를 만나셨다면 주저하지 말고 아래 댓글 창에 남겨주세요. 명쾌하게 디버깅해 드리겠습니다. 감사합니다!

반응형