Python을 사용하다 보면 class라는 문법을 자주 만나게 됩니다.
간단한 프로그램에서는 함수와 기본 자료형만으로도 충분히 코드를 작성할 수 있지만, 프로그램의 규모가 커지면 데이터를 하나로 묶고 그 데이터와 관련된 기능까지 함께 관리해야 하는 경우가 많습니다.
이때 사용하는 것이 클래스(Class)입니다.
클래스는 처음 보면 __init__(), self 같은 문법 때문에 어렵게 느껴질 수 있습니다. 하지만 클래스가 무엇인지부터 차근차근 이해하면 생각보다 구조는 간단합니다.
이번 글에서는 Python 클래스의 기본 개념부터 객체와 인스턴스의 차이, __init__(), self, 인스턴스 변수와 메서드까지 살펴보겠습니다.
클래스(Class)란?
클래스는 쉽게 말하면 객체를 만들기 위한 설계도입니다.
예를 들어 사람을 표현하는 프로그램을 만든다고 생각해보겠습니다.
사람마다 이름과 나이는 다르지만, 기본적으로 다음과 같은 정보를 가지고 있습니다.
사람
├── 이름
├── 나이
└── 자기소개하기
이런 구조를 하나의 클래스로 정의할 수 있습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"{self.name}, {self.age}살입니다.")
여기서 Person이 클래스입니다.
이 클래스는 사람이라는 객체가 어떤 데이터를 가지고 있고 어떤 기능을 수행할 수 있는지를 정의합니다.
하지만 Person이라는 클래스를 정의했다고 해서 실제 사람이 만들어진 것은 아닙니다.
클래스를 이용해서 실제 객체를 생성해야 합니다.
객체(Object) 만들기
클래스로부터 객체를 만드는 방법은 다음과 같습니다.
person1 = Person("철수", 20)
person2 = Person("영희", 25)
이제 person1과 person2라는 두 개의 객체가 만들어졌습니다.
각각의 객체는 서로 다른 데이터를 가지고 있습니다.
print(person1.name)
print(person1.age)
print(person2.name)
print(person2.age)
결과:
철수
20
영희
25
같은 Person 클래스를 사용했지만 각각 독립적인 데이터를 가지고 있습니다.
즉,
Person 클래스
↓
┌───────────┐
↓ ↓
person1 person2
철수, 20 영희, 25
와 같은 구조라고 생각하면 이해하기 쉽습니다.
클래스와 객체의 관계
클래스와 객체의 관계를 간단하게 표현하면 다음과 같습니다.
클래스
↓
객체 생성
↓
객체 1
객체 2
객체 3
...
클래스가 설계도라면 객체는 그 설계도를 사용해서 만들어진 실제 결과물이라고 생각할 수 있습니다.
예를 들어:
class Person:
pass
라는 클래스를 만들었다면,
person1 = Person()
person2 = Person()
처럼 여러 개의 객체를 만들 수 있습니다.
각 객체는 서로 독립적으로 존재합니다.
인스턴스(Instance)란?
클래스를 공부하다 보면 객체와 함께 인스턴스(Instance)라는 단어도 자주 등장합니다.
예를 들어:
person = Person()
이라고 하면 person은 Person 클래스의 인스턴스라고 표현할 수 있습니다.
쉽게 말하면 클래스와 객체의 관계를 조금 더 구체적으로 표현한 것이 인스턴스입니다.
Person 클래스
↓
Person()을 통해 생성
↓
person 인스턴스
따라서 일반적으로 다음과 같이 이해하면 됩니다.
- 클래스: 객체를 만들기 위한 설계도
- 객체: 클래스를 통해 만들어진 대상
- 인스턴스: 특정 클래스에서 만들어진 객체
실제로 Python에서는 객체와 인스턴스를 비슷한 의미로 사용하는 경우가 많습니다.
다만 “어떤 클래스의 인스턴스인가?”라는 관계를 강조할 때 인스턴스라는 표현을 사용합니다.
__init__()이란?
클래스를 정의할 때 다음과 같은 메서드를 자주 사용합니다.
def __init__(self, name, age):
self.name = name
self.age = age
__init__()은 객체가 생성될 때 초기화 작업을 수행하는 특수 메서드입니다.
예를 들어 다음 코드를 실행하면:
person = Person("철수", 20)
Python은 객체를 생성하면서 __init__()을 호출합니다.
전달한 "철수"와 20은 각각 name, age에 전달됩니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
따라서 다음과 같이 객체가 초기화됩니다.
person
├── name → "철수"
└── age → 20
이처럼 __init__()은 객체가 처음 만들어질 때 필요한 값을 설정하는 데 주로 사용합니다.
self는 무엇일까?
Python 클래스를 처음 배울 때 가장 헷갈리는 부분 중 하나가 self입니다.
다음 코드를 보겠습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
여기서 self는 현재 만들어지고 있는 객체 자신을 가리키는 참조라고 이해하면 됩니다.
예를 들어:
person1 = Person("철수", 20)
라고 하면 self는 person1 객체를 가리키게 됩니다.
그리고:
self.name = name
은 결국 다음과 같은 의미가 됩니다.
person1.name = "철수"
다시:
person2 = Person("영희", 25)
를 실행하면 이번에는 self가 person2를 가리킵니다.
person2.name = "영희"
그래서 같은 클래스에서 만들어진 객체라도 서로 다른 값을 가질 수 있습니다.
인스턴스 변수란?
다음과 같은 코드를 살펴보겠습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
여기서:
self.name
self.age
를 인스턴스 변수라고 합니다.
각 객체가 독립적으로 가지고 있는 데이터이기 때문입니다.
예를 들어:
person1 = Person("철수", 20)
person2 = Person("영희", 25)
라면,
person1
├── name → 철수
└── age → 20
person2
├── name → 영희
└── age → 25
처럼 각각 다른 값을 저장합니다.
따라서 다음과 같이 값을 변경할 수도 있습니다.
person1.age = 21
print(person1.age)
print(person2.age)
결과:
21
25
person1의 값만 변경되고 person2에는 영향을 주지 않습니다.
인스턴스 메서드란?
클래스 안에 정의된 함수는 일반적으로 메서드(Method)라고 부릅니다.
예를 들어:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"{self.name}, {self.age}살입니다.")
여기서:
def introduce(self):
가 메서드입니다.
객체를 만든 다음 호출할 수 있습니다.
person = Person("철수", 20)
person.introduce()
결과:
철수, 20살입니다.
메서드 내부에서 self.name과 self.age를 사용할 수 있는 이유는 self가 현재 객체를 가리키고 있기 때문입니다.
self는 직접 전달해야 할까?
다음 코드에서 조금 이상한 부분이 있을 수 있습니다.
person.introduce()
introduce()에는 self가 필요한데 호출할 때 전달하지 않았습니다.
그런데 실제로는 문제가 없습니다.
Python이 메서드를 호출할 때 현재 객체를 자동으로 전달하기 때문입니다.
개념적으로 다음과 비슷하게 이해할 수 있습니다.
person.introduce()
↓
Person.introduce(person)
즉 self는 메서드가 어떤 객체에 대해 동작해야 하는지 알려주는 역할을 합니다.
클래스 안에서 여러 메서드 만들기
하나의 클래스에는 여러 개의 메서드를 만들 수 있습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"이름: {self.name}")
print(f"나이: {self.age}")
def increase_age(self):
self.age += 1
사용하면:
person = Person("철수", 20)
person.introduce()
person.increase_age()
print(person.age)
결과:
이름: 철수
나이: 20
21
이처럼 클래스는 데이터와 그 데이터를 처리하는 기능을 하나로 묶어서 관리할 수 있습니다.
함수로 작성하는 것과 무엇이 다를까?
간단한 프로그램이라면 클래스를 사용하지 않고 함수만으로도 충분히 작성할 수 있습니다.
예를 들어:
name = "철수"
age = 20
def introduce(name, age):
print(f"{name}, {age}살입니다.")
하지만 관리해야 하는 사람이 많아지면 데이터와 함수가 따로 흩어질 수 있습니다.
클래스를 사용하면 관련된 데이터와 기능을 하나로 묶을 수 있습니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"{self.name}, {self.age}살입니다.")
그리고 각 객체가 자신의 데이터를 관리하도록 만들 수 있습니다.
person1 = Person("철수", 20)
person2 = Person("영희", 25)
person1.introduce()
person2.introduce()
이런 방식은 프로그램의 규모가 커질수록 관리하기 편해집니다.
클래스는 왜 사용하는가?
클래스를 사용하는 가장 큰 이유 중 하나는 관련된 데이터와 기능을 하나의 단위로 묶어서 관리하기 위해서입니다.
예를 들어 자동차를 프로그램으로 표현한다고 생각해보겠습니다.
자동차에는 다음과 같은 데이터가 있을 수 있습니다.
자동차
├── 브랜드
├── 색상
├── 속도
└── 연식
그리고 다음과 같은 기능도 있을 수 있습니다.
시동 걸기
가속하기
감속하기
정지하기
이것을 하나의 클래스로 표현할 수 있습니다.
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
self.speed = 0
def accelerate(self):
self.speed += 10
def brake(self):
self.speed -= 10
객체를 만들면:
car = Car("Hyundai", "black")
이제 car 객체가 자신의 브랜드, 색상, 속도와 관련된 기능을 함께 관리하게 됩니다.
car.accelerate()
car.accelerate()
print(car.speed)
결과:
20
이처럼 클래스는 현실 세계의 대상을 프로그램 안에서 표현하거나, 서로 관련된 데이터와 기능을 하나의 구조로 관리할 때 유용합니다.
클래스 기본 구조 정리
지금까지 배운 내용을 가장 기본적인 형태로 정리하면 다음과 같습니다.
class 클래스이름:
def __init__(self, 값):
self.변수 = 값
def 메서드이름(self):
# 기능
pass
그리고 객체를 생성합니다.
객체 = 클래스이름(값)
객체의 변수에 접근할 때는:
객체.변수
메서드를 호출할 때는:
객체.메서드()
를 사용합니다.
전체적인 관계는 다음과 같습니다.
클래스
│
┌──────┴──────┐
↓ ↓
객체 1 객체 2
│ │
┌────┴────┐ ┌────┴────┐
이름 나이 이름 나이
철수 20 영희 25
마무리
Python의 클래스는 처음에는 self와 __init__() 때문에 조금 낯설 수 있습니다.
하지만 기본적인 구조는 생각보다 단순합니다.
클래스는 객체를 만들기 위한 구조를 정의하고, 객체는 그 클래스를 이용해 실제로 만들어진 대상입니다.
그리고 객체는 자신의 데이터를 인스턴스 변수로 가지고 있으며, 클래스 내부의 메서드를 통해 그 데이터를 처리할 수 있습니다.
이번 글에서 기억해야 할 핵심은 다음과 같습니다.
class는 객체를 만들기 위한 구조를 정의한다.- 클래스에서 만들어진 객체를 인스턴스라고 부른다.
__init__()은 객체가 생성될 때 초기화 작업을 수행한다.self는 현재 객체를 가리킨다.self.name,self.age와 같은 값은 인스턴스 변수다.- 클래스 안에 정의한 함수는 메서드라고 한다.
- 클래스는 관련된 데이터와 기능을 하나로 묶어 관리할 수 있다.
다음 글에서는 클래스에서 사용할 수 있는 인스턴스 메서드, 클래스 메서드, 정적 메서드를 비교하면서 각각 self, cls, @staticmethod가 어떤 차이를 가지고 있는지 살펴보겠습니다.