PythonPython 기초강의 10개 중 7번째난이도 입문

클래스와 객체 — 데이터와 기능을 하나로 묶기

발행 읽는 시간 약 1 분

  • Python
  • 클래스
  • 객체
  • OOP
  • Pydantic

강의 소개

클래스로 자신만의 자료형을 만들고, 속성과 메서드를 정의하는 방법을 배웁니다. LLM API 코드에서 자주 보이는 Pydantic 모델의 기반 개념도 함께 익힙니다.

왜 클래스가 필요한가?#

사용자 정보를 딕셔너리로 관리하면:

Python
user = {"name": "철수", "age": 25, "email": "kim@example.com"}

# 나이를 업데이트하는 함수를 별도로 관리해야 함
def update_age(user, new_age):
    if new_age < 0:
        raise ValueError("나이는 0 이상")
    user["age"] = new_age

클래스를 쓰면 데이터와 관련 기능을 하나로 묶을 수 있습니다.


클래스 기본 구조#

Python
class User:
    # __init__: 객체 생성 시 자동 실행
    def __init__(self, name: str, age: int, email: str):
        self.name = name      # 인스턴스 속성
        self.age = age
        self.email = email
    
    # 메서드: 클래스에 속한 함수
    def greet(self):
        return f"안녕하세요, {self.name}입니다!"
    
    def update_age(self, new_age: int):
        if new_age < 0:
            raise ValueError("나이는 0 이상이어야 합니다.")
        self.age = new_age
    
    def __str__(self):  # print() 할 때 출력되는 문자열
        return f"User(name={self.name}, age={self.age})"

# 객체 생성
user1 = User("철수", 25, "kim@example.com")
user2 = User("영희", 30, "lee@example.com")

print(user1.greet())    # 안녕하세요, 철수입니다!
print(user2.name)       # 영희
user1.update_age(26)
print(user1)            # User(name=철수, age=26)

클래스 vs 인스턴스#

Diagram · Mermaid

클래스 변수 vs 인스턴스 변수#

Python
class Counter:
    total_created = 0   # 클래스 변수: 모든 인스턴스 공유
    
    def __init__(self, name: str):
        self.name = name    # 인스턴스 변수: 각 객체마다 별도
        Counter.total_created += 1
    
    @classmethod
    def get_total(cls) -> int:
        return cls.total_created

c1 = Counter("A")
c2 = Counter("B")
print(Counter.get_total())   # 2

상속: 기존 클래스를 확장하기#

Python
class Animal:
    def __init__(self, name: str):
        self.name = name
    
    def speak(self) -> str:
        return "..."
    
    def __str__(self):
        return f"{self.__class__.__name__}({self.name})"

class Dog(Animal):           # Animal을 상속
    def speak(self) -> str:  # 메서드 오버라이드
        return "멍멍!"
    
    def fetch(self):
        return f"{self.name}이(가) 공을 가져왔습니다!"

class Cat(Animal):
    def speak(self) -> str:
        return "야옹~"

dog = Dog("바둑이")
cat = Cat("나비")

print(dog.speak())   # 멍멍!
print(cat.speak())   # 야옹~
print(dog.fetch())   # 바둑이이(가) 공을 가져왔습니다!
print(dog)           # Dog(바둑이)

실전: LLM 대화 관리 클래스#

Python
from datetime import datetime
from openai import OpenAI

class Conversation:
    def __init__(self, system_prompt: str = "당신은 친절한 어시스턴트입니다."):
        self.client = OpenAI()
        self.messages = [{"role": "system", "content": system_prompt}]
        self.created_at = datetime.now()
        self.turn_count = 0
    
    def chat(self, user_message: str) -> str:
        self.messages.append({"role": "user", "content": user_message})
        
        response = self.client.chat.completions.create(
            model="gpt-4o-mini",
            messages=self.messages
        )
        
        assistant_message = response.choices[0].message.content
        self.messages.append({"role": "assistant", "content": assistant_message})
        self.turn_count += 1
        
        return assistant_message
    
    def clear(self):
        system = self.messages[0]  # 시스템 프롬프트 유지
        self.messages = [system]
        self.turn_count = 0
    
    def get_history(self) -> list:
        return [m for m in self.messages if m["role"] != "system"]
    
    def __len__(self):
        return self.turn_count
    
    def __str__(self):
        return f"Conversation({self.turn_count}턴, {self.created_at.strftime('%H:%M')}시작)"

# 사용
conv = Conversation("당신은 파이썬 튜터입니다.")
print(conv.chat("리스트 컴프리헨션이 뭔가요?"))
print(conv.chat("예시 코드 보여주세요."))
print(f"현재 대화: {conv}")  # Conversation(2턴, 14:30시작)
print(f"대화 수: {len(conv)}")  # 2

Pydantic: 데이터 검증 클래스#

LLM API 개발에서 자주 쓰이는 Pydantic을 이해하려면 클래스 개념이 필요합니다.

Python
from pydantic import BaseModel, Field, validator
from typing import Optional, List

class UserProfile(BaseModel):
    name: str
    age: int = Field(ge=0, le=150)      # 0 이상 150 이하
    email: str
    skills: List[str] = []              # 기본값 빈 리스트
    bio: Optional[str] = None
    
    @validator("email")
    def validate_email(cls, v):
        if "@" not in v:
            raise ValueError("유효한 이메일 주소를 입력하세요.")
        return v.lower()

# 유효한 데이터
user = UserProfile(name="철수", age=25, email="Kim@Example.COM")
print(user.email)    # kim@example.com (자동 소문자)
print(user.skills)   # []

# 잘못된 데이터
try:
    bad_user = UserProfile(name="영희", age=-1, email="invalid")
except Exception as e:
    print(e)

매직 메서드 (Dunder Methods)#

Python
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):   # v1 + v2
        return Vector(self.x + other.x, self.y + other.y)
    
    def __str__(self):          # print(v)
        return f"Vector({self.x}, {self.y})"
    
    def __len__(self):          # len(v)
        return 2
    
    def __eq__(self, other):    # v1 == v2
        return self.x == other.x and self.y == other.y

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)   # Vector(4, 6)
print(len(v1))   # 2

정리#

개념설명
class자료형 설계도 정의
__init__객체 생성 시 자동 실행 초기화 메서드
self현재 인스턴스를 가리키는 참조
상속class Child(Parent)로 기능 확장
@classmethod인스턴스 없이 호출 가능한 메서드
Pydantic클래스 기반 데이터 검증 라이브러리

다음 편에서는 외부 패키지와 가상환경 — pip로 패키지를 설치하고 프로젝트별 환경을 격리하는 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.