Python/기초

파이썬 객체지향 프로그래밍 핵심 개념 정리(클래스와 메서드)

sdesign416 2026. 5. 28. 17:42

프로그래밍 방법론이란,
컴퓨터가 이해하고 실행할 수 있는 소프트웨어를
효율적으로 생산, 관리, 유지보수 하기 위해서 
개발 과정과 절차를 체계화하고 표준화한 접근 방식이다.
 
프로젝트의 규모, 요구사항, 개발팀의 특성에 따라
적합한 방법론이 달라지기 때문에 각 방법론에 대해 특징과 장단점을 이해하고 있는것이 중요하다.


1. 절차적 프로그래밍 (Procedural Programming)

절차적 프로그래밍은 말 그대로 절차를 중시하는 방식으로,
실행될 순서대로 명령어들을 순차적으로 처리하는 방식이다.
 
이는 여태 우리가 사용해왔던 방식으로
위에서 아래로 물흐르듯이 실행되는 방식이라 순서가 중요한반면 이해하기엔 쉽다.
하지만 데이터와 함수가 분리되어있어 규모가 커지면 관리가 어렵다.
 

2. 객체지향 프로그래밍 (Object-Oriented Programming, OOP)

객체지향 프로그래밍은 데이터를 객체(Object) 단위로 묶어 처리하는 방식이다.
여기서 객체는 데이터(속성)와 함수(메서드)를 하나의 단위로 캡슐화하여 묶은것을 말하며
이는 코드의 재사용성을 높이고 유지보수가 편리하도록 해준다.
 
ex) 자동차를 만든다면?
자동차를 구성하는 부품들을 독립적으로 만든 후 조립하는 방식이다.

  • 바퀴(객체1)
    • 속성(데이터) : 바퀴크기, 타이어 종류, 공기압력 등
    • 메서드(기능) : 바퀴는 굴러간다, 멈춘다.
  • 창문(객체2)
    • 속성(데이터) : 유리의 색상, 두께, 투명도 등
    • 메서드(기능) : 창문은 열린다, 닫힌다.

 

3. 함수형 프로그래밍 (Functional Programming)

함수형 프로그래밍은 수학적 함수들의 조합으로 프로그램을 작성한 방식으로
코드가 간결하고 직관적이다.
이는 데이터 변경을 최소화하여 버그를 줄일 수 있고, 복잡한 코드 처리에 유용하게 사용된다.
 
예를 들어 map, filter, reduce등의 함수나 재귀를 사용해 데이터를 간결하게 수행할 수 있다.

※ 특정 함수를 실행하고 나온 return결과를 다른 함수에 집어넣고 또 그 return결과를 다른 함수에 집어넣고...
 
 

이 중에서 현재 가장 널리 사용되는 방식은 객체지향 프로그래밍이다.
이유는 코드 재사용성과 확장성이 좋기 때문이다.


1. 클래스(Class)

클래스는 객체를 만드는 설계도,
즉 객체를 찍어내는 틀이라고 생각하면 쉽다.

위 이미지를 참고하여 보면

  • 클래스 = 붕어빵 틀 : 붕어빵을 만들기 위한 모양과 구조를 정의하는 틀이다.
  • 객체/인스턴스 = 실제 붕어빵 : 붕어빵 틀에 반죽과 팥을 넣고 찍어내어 실제로 존재하는 붕어빵이다. 
  • 속성(데이터) = 붕어빵의 내용물(팥, 슈크림, 피자), 굽기정도, 가격 등
  • 메서드(기능) = 붕어빵이 식어간다, 겉바속촉해진다.

이렇게 붕어빵 틀(클래스)은 하나만 만들어 두면
그 틀을 이용해 여러가지 다양한 붕어빵(인스턴스들)을 
원하는만큼 무한대로 찍어낼 수 있다.
 
그래서 객체지향 프로그래밍이 코드 재사용성에 좋다고 하는 이유이기도 하다.


클래스 기본 사용구조

class 클래스이름:
    # 클래스 속성(멤버 변수) 정의
    속성1 = 초기값1
    속성2 = 초기값2

    # 생성자 메서드 (생략 가능)
    def __init__(self, 매개변수1, 매개변수2, ...):
        # 인스턴스 속성 초기화
        self.속성1 = 매개변수1
        self.속성2 = 매개변수2

    # 메서드(멤버 함수) 정의
    def 메서드1(self, 매개변수1, 매개변수2, ...):
        # 메서드 동작 정의
        pass
  • self → 만들어진 객체 자신을 의미한다.
  • __init__ → 객체가 생성될 때 자동으로 실행되는 초기화 함수이다.

2. 객체(인스턴스) 생성

클래스는 사실 정의일 뿐이고
실제로 사용하기 위해선 객체를 만들어주어야 한다.
 
즉, 붕어빵 틀만 있다고 붕어빵을 만들 수 있는것이 아니라
틀에 재료룰 넣고 붕어빵을 구워내야 붕어빵이 만들어 진다라고 이해하면 쉽다.

 

💡 객체와 인스턴스의 차이!

객체와 인스턴스는 거의 같은 의미로 사용되지만,
관점에 따라 구분될때가 있다.
 

객체(Object)

메모리에 존재하는 모든 실체를 뜻하는 넓은 개념이다.
즉, 파이썬에서는 리스트, 함수, 클래스 등 메모리에 올라간 모든 값이 객체에 해당한다.
 

인스턴스(Instance)

특정 클래스로부터 생성된 객체를 부르는 관계 중심적 용어
대상이 어떤 클래스로부터 태어났는지에 대한 연관성을 강조할때 사용한다.
 
즉, 모든 인스턴스는 객체이지만
모든 객체가 특정 클래스의 인스턴스는 아니다.


3. 생성자와 인스턴스 변수

3_1) 생성자

생성자는 클래스의 인스턴스가 생성될 때 자동으로 생성되는 특별한 메서드이다.
 
Python에서 생성자 메서드는 __init__ 으로 사용하며,
속성을 self를 사용하여 접근하고 설정할 수 있다.

class 클래스이름:
    # 생성자
    def __init__(self, 매개변수1, 매개변수2):
        self.속성1 = 매개변수1
        self.속성2 = 매개변수2

 

💡생성자 메서드는 메모리에 어떻게 저장될까?

우리가 객체를 만들때마다
내부에 있는 메서드(함수)도 매번 Heap메모리에 새로 생성되는것은 아니다!
 
속성(값)은 객체마다 달라지므로 Heap영역에 각각 독립적으로 존재하지만
메서드(행동)는 코드가 실행되는것이지 자체적으로 값이 바뀌는것은 아니다.
 
그렇기 때문에 객체와 함께 Heap에 저장되는것이 아닌
메소드 영역에 따로 올라가 저장된다.

그래서,
객체는 여러개지만
메서드는 딱 1개만 올려두고 공용으로 사용하는효율적인 구조이다.


3_2) 인스턴스 변수

인스턴스 변수는 각 인스턴스마다 별도로 생성되는 변수이다.
객체를 만들 때마다 self 키워드를 사용해 생성자에 정의되며
각 객체(인스턴스)가 가지는 고유한 값을 따로 저장한다.
 
즉, 인스턴스 변수는 객체마다 따로 존재하는 데이터라고 생각하면 된다.
 
쉽게 말해 각 객체가 가지는 자신만의 개인 수첩인것이다.
apple 수첩에 적힌 내용을 바꾼다고 해서
banana 수첩에 적힌 내용이 바뀌지 않는 것 처럼
완전히 독립된 공간인것이다.

※ 생성자에 매개변수가 생겼을 땐, apple = Fruit() 처럼 빈 괄호로 만들면 TypeError발생!


4. 메서드(Method)

메서드는 클래스 내부에 정의된 함수로,
객체가 수행하는 행동이다.
 
메서드는 단순한 함수들과는 달리
특정 객체나 클래스와 연결되어 동작하며,
객체의 상태(속성)를 읽거나 변경하는 역할을 하고있다.

위 코드 이미지의 실행 흐름은 아래와 같다.

  • apple = Fruit("사과", 10)
    • 객체 생성 : 힙(Heap) 메모리에 Fruit클래스로 만든 apple객체 생성
    • 변수 할당 : 스택(Stack)의 apple 변수가 힙 주소를 가리킴
  • apple.print_info()
    • 메서드 호출 : apple이 가진 힙 주소를 self에 넣어 데이터 출력
  • apple.add_quantity(5)
    • 값 변경 : 힙 주소를 찾아가 내부 수량을 10에서 15로 변경
  • apple.print_info()
    • 메서드 호출(확인) : 힙 메모리에 바뀐 데이터(수량)을 다시 찾아가 출력

5. 클래스 변수

앞에서 배운 인스턴스 변수는 객체마다 독립된 데이터를 가진다고 설명했다.
이번엔 이와 대비되는 클래스변를 알아보자.

 

클래스 변수는 클래스 내부 공간(메서드 밖)에 선언되는 변수로,
이 클래스로부터 생성된 모든 객체(인스턴스)들이 공유하는 변수이다.
 
클래스 변수는 클래스이름.변수명 또는 인스턴스.변수명 으로 접근할 수 있다.
 

5_1) 클래스 변수와 인스턴스 변수 정의

 

5_2) 객체생성 및 기본 출력

사과와 바나나 객체를 각각 만들어 출력하면
이름과 수량은 매개변수를 넣은대로 출력이 되지만
원산지는 '한국'으로 공통 클래스 변수를 통해 출력이 된다.

 

5_3) 클래스 변수 변경

Fruit.origin = '필리핀' 을 사용해 클래스 자체의 값을 바꿔주면
사과, 바나나 원산지가 모두 동시에 변경된다.
이게 바로 모든 객체가 메모리를 공유한다는 클래스 변수의 특징이다.

 

5_4) 인스턴스 변수로 독립적인 값 부여(덮어쓰기)

 

💡왜 이런 결과가 나올까?

파이썬은 변수를 찾을 때 무조건 우선순위를 따지며 찾는다.

  1. 인스턴스 변수 먼저 탐색(내 수첩에 있는지?)
  2. 없다면 클래스 변수 탐색(공용 게시판으로 올라가 확인)

이때 apple.origin의 경우 apple.origin = '미국' 이라는 코드를 사용하여
사과 객체 전용 인스턴스 변수를 만들어 미국이 출력되고
 
반면에 banana는 내부에 따로 origin변수가 없기때문에
클래스 변수 영역에 있는 필리핀이 출력된다.


6. 클래스 메서드와 정적 메서드

변수의 종류를 목적에 따라 구분하듯이
메서드도 무엇을 제어하느냐에 따라 종류를 나눌 수 있다.
함수 앞에 골뱅이(@)를 붙여 데코레이터를 사용해 작성할 수 있다.


5_1) 클래스 메서드

클래스 메서드는 인스턴스(객체)가 아닌 클래스 객체를 대상으로 동작하는 메서드이다.
클래스 메서드는 인스턴스 자신을 가리키는 self가 아닌
클래스 자신을 가리키는 cls 키워드를 사용한다.
 

6_2) 정적 메서드

정적 메서드는 별도의 참조없이 독립적으로 동작하는 메서드이다.
즉, 다른 인스턴스 변수나 클래스 변수를 전혀 사용하지 않고
단순히 나에게 매개변수로 들어온 값만 가지고 계산하는 독립적인 메서드이다.


7. 데코레이터 (Decorator)

앞서 설명한 클래스 메서드와 정적 메서드를 만들 때
함수 앞에 붙인 골뱅이(@)기호가 바로 데코레이터이다.
 
데코레이터는 말 그대로 장식을 해주는것을 의미한다.
 
프로그래밍을 하다보면 이미 잘 만들어진 함수나 메서드가 있을 때,
기존 코드를 전혀 수정하지 않고 기능을 추가하고싶을 때
공통 기능을 쉽게 재사용할 수 있도록 해준다.
 

💡 데코레이터의 내부 동작 원리

데코레이터는 내부적으로 함수를 인자로 받아,
기능을 덧붙여 새로운 함수로 만들어 반환하는 구조이다.
 
즉, 함수를 리턴하는 방식인데
이것은 이전글에서 배운 외부함수의 변수를 기억하였다가 사용하는 클로저형태로 구현되어 있는것이다.


마무리

객체지향 프로그래밍의 핵심은 결국 이 3가지다.

  • 클래스 → 구조 설계
  • 객체 → 실제 데이터
  • 메서드 → 행동 정의