안녕하세요! 지난 시간에는 raise와 사용자 정의 예외를 통해 프로그램의 오류를 더욱 세밀하게 제어하는 방법을 알아보았습니다. 이제 여러분의 프로그램은 예상치 못한 상황에도 더욱 견고하게 대응할 수 있게 되었을 거예요!
이번 시간부터는 파이썬 프로그래밍의 핵심이자 가장 강력한 패러다임 중 하나인 **객체지향 프로그래밍(Object-Oriented Programming, OOP)**에 대해 본격적으로 알아보겠습니다. OOP는 프로그램을 현실 세계의 사물처럼 '객체' 단위로 나누어 설계하고 구현하는 방식입니다.
OOP의 가장 기본적인 두 가지 개념은 바로 **클래스(Class)**와 **객체(Object)**입니다. 이 둘은 OOP의 모든 것을 이해하는 데 필수적인 출발점입니다. 마치 붕어빵 틀(클래스)과 그 틀로 찍어낸 붕어빵(객체)의 관계와 같다고 생각하시면 됩니다.
Part 1: 객체지향 프로그래밍(OOP)이란?
OOP는 데이터를 다루는 함수와 그 데이터 자체를 하나의 묶음(객체)으로 생각하고 프로그램을 설계하는 방식입니다. 이를 통해 코드의 재사용성을 높이고, 유지보수를 쉽게 하며, 복잡한 시스템을 체계적으로 관리할 수 있게 됩니다.
OOP의 주요 특징은 다음과 같습니다 (나중에 더 자세히 배울 것입니다):
- 추상화(Abstraction): 복잡한 것을 단순하게 표현합니다.
- 캡슐화(Encapsulation): 데이터와 기능을 하나로 묶어 보호합니다.
- 상속(Inheritance): 기존 코드를 재사용하여 새로운 기능을 확장합니다.
- 다형성(Polymorphism): 다양한 형태의 객체가 동일한 방식으로 동작할 수 있게 합니다.
이 모든 것의 시작은 바로 클래스와 객체입니다.
Part 2: 클래스(Class) - 객체의 설계도
클래스는 특정 종류의 객체를 만들기 위한 설계도, 틀, 또는 청사진과 같습니다. 클래스 자체는 데이터가 아니며, 단순히 객체가 가져야 할 속성(데이터)과 행동(함수)을 정의해 놓은 것입니다.
1. 클래스 정의하기
파이썬에서 클래스를 정의할 때는 class 키워드를 사용합니다.
기본 형식:
class 클래스이름:
# 클래스 속성 (모든 객체가 공유하는 값)
# 메서드 (객체가 수행할 수 있는 행동)
# 이 부분은 들여쓰기(Indentation) 필수!
- class: 클래스를 정의할 때 사용하는 키워드입니다.
- 클래스이름: 클래스를 식별하는 고유한 이름입니다. 클래스 이름은 보통 각 단어의 첫 글자를 대문자로 작성하는 것이 일반적인 관례입니다. (예: Person, Car, BankAccount)
- : (콜론): 클래스 이름 뒤에는 반드시 콜론을 붙여야 합니다.
- 들여쓰기(Indentation): 클래스 정의 아래의 코드 블록은 반드시 들여쓰기를 해야 합니다. 이 들여쓰기 된 부분까지가 클래스에 속하는 코드입니다.
예시: Car 클래스 정의
# 파일 이름: class_definition.py
# Car 클래스 정의
class Car:
# 이 부분은 나중에 '속성'과 '메서드'로 채워질 것입니다.
# 일단은 아무 내용 없이 pass 키워드를 사용합니다.
pass
# 다른 클래스도 정의할 수 있습니다.
class Dog:
pass
print("Car 클래스가 정의되었습니다.")
print("Dog 클래스가 정의되었습니다.")
[VS Code 터미널 출력]

Part 3: 객체(Object) 또는 인스턴스(Instance) - 설계도로 만든 실제 사물
**객체(Object)**는 클래스라는 설계도를 바탕으로 실제로 만들어진 구체적인 사물입니다. 때로는 **인스턴스(Instance)**라고도 부릅니다. 하나의 클래스에서 여러 개의 객체를 만들 수 있으며, 각 객체는 고유한 데이터를 가질 수 있습니다.
1. 객체(인스턴스) 생성하기
클래스로부터 객체를 생성하는 것을 **인스턴스화(Instantiation)**라고 합니다. 클래스 이름 뒤에 괄호 ()를 붙여서 호출하면 해당 클래스의 새로운 객체가 생성됩니다.
기본 형식:
객체_변수 = 클래스이름()
예시: Car 클래스로 my_car 객체 만들기
# 파일 이름: object_creation.py
class Car:
pass
# Car 클래스로 my_car 객체 생성
my_car = Car()
your_car = Car() # 같은 Car 클래스로 또 다른 객체 생성
print(f"my_car 객체: {my_car}")
print(f"your_car 객체: {your_car}")
print(f"my_car의 타입: {type(my_car)}")
print(f"my_car와 your_car는 같은 객체인가? {my_car is your_car}") # False, 서로 다른 객체
- my_car = Car(): Car 클래스의 새로운 객체를 생성하여 my_car 변수에 할당합니다.
- 출력 결과를 보면 my_car와 your_car는 서로 다른 메모리 주소에 있는 별개의 객체임을 알 수 있습니다.
[VS Code 터미널 출력]

(메모리 주소(0x...)는 실행할 때마다 다를 수 있습니다.)
Part 4: 클래스와 객체의 관계 (정리)
다시 한번 붕어빵 비유를 통해 클래스와 객체의 관계를 정리해봅시다.
- 붕어빵 틀 🥮 (클래스):
- 어떤 모양의 붕어빵을 만들지 정의합니다. (클래스는 객체의 구조와 동작을 정의)
- 틀 자체는 붕어빵이 아니며, 먹을 수도 없습니다. (클래스 자체는 데이터가 아님)
- 하나의 틀로 여러 개의 붕어빵을 만들 수 있습니다. (하나의 클래스로 여러 개의 객체 생성 가능)
- 붕어빵 🍞 (객체/인스턴스):
- 붕어빵 틀로 만들어진 실제 붕어빵입니다. (객체는 클래스의 정의에 따라 만들어진 실제 데이터 덩어리)
- 팥 붕어빵, 슈크림 붕어빵 등 각 붕어빵마다 다른 속성을 가질 수 있습니다. (각 객체는 고유한 데이터를 가질 수 있음)
- 우리가 먹는 것은 붕어빵 틀이 아닌, 실제 만들어진 붕어빵입니다. (프로그램은 객체를 통해 데이터를 다루고 동작을 수행함)
예시: Person 클래스와 객체
# 파일 이름: person_class_object.py
# Person 클래스 (설계도)
class Person:
pass # 일단은 아무 내용 없음
# Person 클래스로 '객체'들을 생성 (인스턴스화)
p1 = Person()
p2 = Person()
p3 = Person()
print(f"p1: {p1}")
print(f"p2: {p2}")
print(f"p3: {p3}")
# 각 객체는 서로 다른 존재입니다.
print(f"p1과 p2는 같은 객체인가? {p1 is p2}") # False
print(f"p1과 p3는 같은 객체인가? {p1 is p3}") # False
[VS Code 터미널 출력]

(메모리 주소는 실행할 때마다 다를 수 있습니다.)
마무리하며
이번 시간에는 객체지향 프로그래밍(OOP)의 가장 기본적인 개념인 **클래스(Class)**와 **객체(Object, 인스턴스)**에 대해 알아보았습니다.
- 클래스: 객체를 만들기 위한 '설계도' 또는 '틀'.
- 객체 (인스턴스): 클래스라는 설계도를 바탕으로 '실제로 만들어진 구체적인 사물'.
지금까지는 클래스를 정의하고 객체를 생성하는 방법까지만 배웠습니다. 아직 객체가 어떤 데이터를 가지고, 어떤 행동을 할 수 있는지는 정의하지 않았죠.
다음 포스팅에서는 클래스로 객체를 만들 때 초기값을 설정하는 특별한 메서드인 **생성자(__init__)**와, 객체 고유의 데이터를 저장하는 인스턴스 변수에 대해 자세히 알아보겠습니다.
궁금한 점이 있다면 언제든지 질문해주세요! 다음 포스팅에서 만나요!