인공지능에 대한 관심이 커지면서 파이썬 사용이 늘어났다. 그러면서 많이 들었던 말 중 하나로 '파이썬은 객체 지향 언어'가 있다. 파이썬 외에도 Java, C++ 등도 객체 지향 언어이고, 웹 개발에 많이 쓰이는 JavaScript도 객체 지향 언어이다. 그런데 파이썬, Java, C++과 JS은 완전히 같은 객체 지향 언어는 아니다.
먼저 JS는 프로토타입 기반이고 파이썬, Java, C++은 클래스 기반 객체 지향 언어(Object-Oriented Programming, OOP)이다.
01 객체 지향 프로그래밍 (OOP) vs. 절차 지향 프로그래밍 (Procedural Programming)
객체 지향 프로그래밍은 프로그램이 해결해야할 문제를 작은 부분들로 나누고, 각 부분을 데이터(속성)와 그 데이터와 관련된 기능(메서드)을 가진 '객체'로 만든다. 즉 현실 세계의 객체를 모델링해서 프로그램을 구성한다.
절차 지향 프로그래밍은 레시피를 따르는 것처럼 여러 개의 순서대로 진행되는 절차(함수나 명령)들로 이루어진 프로그램을 만든다. 즉 프로그램을 명령의 순서와 절차로 본다.
모두의 연구소의 예제를 살펴보면 비교가 쉽다.
절차 지향 프로그래밍 예제
# 절차 지향 프로그래밍 예제
# 계좌 잔액
account_balance = 0
# 잔액 확인 함수
def check_balance():
global account_balance
print(f"현재 잔액은 {account_balance}원 입니다.")
# 입금 함수
def deposit(amount):
global account_balance
account_balance += amount
print(f"{amount}원을 입금했습니다.")
# 출금 함수
def withdraw(amount):
global account_balance
if account_balance >= amount:
account_balance -= amount
print(f"{amount}원을 출금했습니다.")
else:
print("잔액이 부족합니다.")
# 함수 사용 예시
check_balance() # 현재 잔액은 0 원 입니다.
deposit(50000) # 50000 원을 입금했습니다.
check_balance() # 현재 잔액은 50000 원 입니다.
withdraw(20000) # 20000 원을 출금했습니다.
check_balance() # 현재 잔액은 30000 원입니다.
객체 지향 프로그래밍 예제
# 객체 지향 프로그래밍 예제
class BankAccount:
def __init__(self):
self.balance = 0 # 계좌의 초기 잔액을 0으로 설정
def check_balance(self):
print(f"현재 잔액은 {self.balance}원 입니다.")
def deposit(self, amount):
self.balance += amount
print(f"{amount}원을 입금했습니다.")
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
print(f"{amount}원을 출금했습니다.")
else:
print("잔액이 부족합니다.")
# 객체 사용 예시
account = BankAccount() # 객체 생성
account.check_balance() # 현재 잔액은 0 원 입니다.
account.deposit(50000) # 50000 원을 입금했습니다.
account.check_balance() # 현재 잔액은 50000 원 입니다.
account.withdraw(20000) # 20000 원을 출금했습니다.
account.check_balance() # 현재 잔액은 30000 원입니다.
두 예제를 살펴볼 때 가장 큰 차이점은 다음과 같다.
절차 지향 코드는 기능 중심으로 구성되어 있고, 객체 지향 코드는 상태와 행위를 하나의 단위로 묶어 관리한다.
따라서 객체 지향 프로그래밍은 여러 개체가 서로 다른 행동을 해야 할 때, 코드의 재사용성과 확정성을 크게 향상시킬 수 있다는 장점이 있다.
02 클래스 기반 vs. 프로토타입 기반
그러면 클래스 기반과 프로토타입 기반 객체 지향 언어는 어떤 차이점이 있을까?
02-1 클래스 기반 객체 지향 언어
클래스 기반 객체 지향 언어는 객체를 정의하기 위해 `class`라는 구조를 사용한다. 클래스를 통해 객체의 속성(attribute, property)과 행위(method)를 정의하고, 이를 기반으로 인스턴스(instance)를 생성한다. 쉽게 이야기하면 `class`는 객체의 구조와 기능에 대한 청사진 역할을 한다고 볼 수 있다.
클래스 상속을 통해 다른 클래스의 속성와 메서드를 재사용하거나 확장할 수 있으며 오버라이딩도 가능하다. 클래스 내부 데이터와 메서드를 캡슐화하겨 객체의 상태를 보호하며, 기본적으로 동적으로 속성이나 메서드를 추가하는 것은 불가능하다. (가능하지만 권장하지 않는다.)
`class`는 계급이라는 뜻 그대로, 상속을 통해 계층 구조를 쉽게 파악할 수 있는 장점이 있다.
02-2 프로토타입 기반 객체 지향 언어
프로토타입 객체 지향 언어는 객체에 `prototype`이라는 속성이 존재해, 프로토타입 체인을 통해 다른 객체의 속성과 메서드를 상속받는다. 클래스 기반 언어처럼 다른 프로토타입의 속성과 메서드를 재사용하거나 확장할 수 있고 오버라이딩도 가능하다. 하지만 프로토타입을 잘 이해하지 못하거나 체계적으로 구조화되지 않으면 혼란스러울 수 있다.
JS에서는 기본적으로 함수를 통해 객체를 생성하며 `prototype`이라는 속성을 통해 다른 프로토타입 객체와 연결된다. JS에서는 ES6부터 `class`가 추가됐지만, 프로토타입 기반으로 동작하며 클래스 기반 언어 사용자들 위해 추가되었다. 클래스 기반 언어와 달리 동적으로 기존 객체에 속성이나 메서드를 추가할 수 있다.
`prototype`이라는 단어 그대로, 해당 객체의 원형, 원조, 기원을 의미한다고 생각하면 좋을 것 같다.
02-3 표로 비교하기
클래스 기반 언어와 프로토타입 기반 언어를 표로 비교해보면 아래와 같다.
특징 | 프로토타입 기반(JS) | 클래스 기반 |
유연성 | 동적이고 유연한 설계. 제한 없이 수정 및 확장 가능. | 제한적이며 명확성 중심. 설계도를 따르는 구조. |
상속 | 프로토타입 체인을 통한 동적 상속. | 클래스 기반 명시적 상속. |
런타임 조작 | 자유롭게 가능. | 가능하지만 지양. |
코드 가독성 | 자유도는 높지만 구조화되지 않으면 혼란스러울 수 있음. | 읽기 쉽고 구조화된 설계를 기본으로 함. |
철학 | 개발자가 원하는 대로 할 수 있다. | 명확성과 안정성이 우선이다. |
참고 문서
'Frontend > Today I Learned' 카테고리의 다른 글
[JS] 프로토타입 Prototype (0) | 2024.12.17 |
---|---|
[JS] 클로저(closure) (1) | 2024.12.10 |
[JS] this (0) | 2024.12.02 |
[Next.js] Zustand 사용하기 (2) | 2024.11.28 |
[React] TanStack Query로 custom hook 만들기 (0) | 2024.10.31 |