[PY-008][중급] 클래스와 데이터클래스로 자료 묶기
페이지 정보

본문
[이번 수업]
서로 관련된 값과 기능이 늘어나면 여러 변수와 함수만으로 관계를 파악하기 어렵습니다. 이번에는 클래스(class), 즉 데이터와 그 데이터를 다루는 기능을 한 설계도에 묶는 문법을 배웁니다.
[선수지식]
Python의 변수, 리스트, 함수, 조건문을 알고 파일을 실행할 수 있어야 합니다. 예제의 list[str] 표기는 Python 3.9 이상에서 실행됩니다. Windows는 py --version, macOS·Linux는 python3 --version으로 버전을 확인하세요.
[학습목표]
1. 클래스와 인스턴스, 속성과 메서드의 관계를 설명한다.
2. @dataclass가 생성하는 초기화·표현·비교 기능을 활용한다.
3. 타입 힌트와 실행 중 입력 검증의 차이를 구분한다.
[핵심개념]
클래스는 설계도이고, 그 설계도로 만든 실제 값은 인스턴스(instance)입니다. 인스턴스가 가진 title 같은 값은 속성, complete()처럼 상태를 다루는 함수는 메서드입니다. 메서드의 첫 인자 self는 현재 인스턴스를 가리킵니다. 일반 클래스에서는 __init__에 초기화 코드를 직접 쓰지만, @dataclass 장식자(decorator, 클래스에 기능을 덧붙이는 표기)를 붙이면 선언한 필드를 바탕으로 __init__, __repr__, __eq__ 같은 특수 메서드가 자동 생성됩니다.
타입 힌트(type hint)는 title: str이나 -> str처럼 기대하는 자료형을 표시하는 메모입니다. 편집기와 타입 검사기가 실수를 미리 찾는 데 쓰지만 Python 실행기가 자동으로 강제하지는 않습니다. 외부 입력은 별도로 검사해야 합니다. 리스트처럼 바꿀 수 있는 기본값은 field(default_factory=list)를 사용해야 인스턴스마다 새 리스트가 생깁니다.
[따라하기]
아래를 task_demo.py로 저장하세요.
```python
from dataclasses import dataclass, field
@dataclass
class Task:
title: str
done: bool = False
tags: list[str] = field(default_factory=list)
def complete(self) -> None:
self.done = True
def describe(task: Task) -> str:
status = "완료" if task.done else "진행 중"
tags = ", ".join(task.tags) or "없음"
return f"{task.title} | {status} | 태그: {tags}"
first = Task("로그 실습", tags=["python", "tool"])
second = Task("문서 읽기")
first.complete()
second.tags.append("study")
print(describe(first))
print(describe(second))
print(first.tags is second.tags)
```
Windows PowerShell에서는 py task_demo.py, macOS·Linux에서는 python3 task_demo.py를 실행합니다. 추가 패키지는 필요 없습니다.
예상 결과:
```text
로그 실습 | 완료 | 태그: python, tool
문서 읽기 | 진행 중 | 태그: study
False
```
False는 두 Task가 같은 태그 리스트를 공유하지 않는다는 뜻입니다. @dataclass가 생성한 초기화 기능 덕분에 필드 값을 이름으로 전달할 수 있고, complete 메서드는 first의 done만 바꿉니다.
[흔한 실수]
self를 빼거나 task.done 대신 클래스 이름으로 인스턴스 값을 찾으면 의도대로 동작하지 않습니다. tags: list[str] = []처럼 바꿀 수 있는 값을 기본값으로 직접 두면 공유 문제가 생기므로 기본 팩터리를 사용하세요. 모든 자료를 억지로 클래스로 만들 필요도 없습니다. 상태와 그 상태를 다루는 동작이 함께 있고 여러 인스턴스가 필요할 때 선택합니다.
[보안 주의]
타입 힌트는 보안 검사가 아닙니다. 파일·JSON·폼에서 받은 title과 tags는 자료형, 길이, 허용 범위를 실행 중에 검증하세요. 데이터클래스의 자동 표현 문자열에는 필드가 보일 수 있으므로 비밀번호·토큰을 넣지 말고, 꼭 필요한 민감 필드는 field(repr=False)로 출력에서 제외해도 별도 보호가 필요합니다. 출처를 신뢰할 수 없는 pickle 파일은 임의 코드 실행 위험이 있으므로 열지 말고, 교환용 데이터는 검증한 JSON 같은 형식을 사용하세요. 실습은 본인 소유의 로컬 파일에서만 수행합니다.
[직접 해볼 과제]
Task에 priority: int = 1 필드를 추가하고 describe 결과에 우선순위를 표시하세요. 이어서 __post_init__ 메서드에서 빈 제목과 1~5 밖의 우선순위에 ValueError를 발생시키고, 정상 입력과 잘못된 입력을 각각 시험해 보세요.
[확인문제]
1. 클래스와 인스턴스는 어떤 관계인가요?
2. 바꿀 수 있는 리스트의 기본값에 default_factory를 쓰는 이유는 무엇인가요?
3. 타입 힌트만으로 외부 입력 검증이 끝나지 않는 이유는 무엇인가요?
[다음 학습]
JSTS-008에서 제네릭·유니언·타입 좁히기로 JavaScript와 TypeScript의 여러 타입을 안전하게 다루는 방법을 배웁니다.
[공식 참고 자료]
Python 클래스 자습서
https://docs.python.org/3/tutorial/classes.html
Python dataclasses 문서
https://docs.python.org/3/library/dataclasses.html
Python typing 문서
https://docs.python.org/3/library/typing.html
Python pickle 보안 경고
https://docs.python.org/3/library/pickle.html
서로 관련된 값과 기능이 늘어나면 여러 변수와 함수만으로 관계를 파악하기 어렵습니다. 이번에는 클래스(class), 즉 데이터와 그 데이터를 다루는 기능을 한 설계도에 묶는 문법을 배웁니다.
[선수지식]
Python의 변수, 리스트, 함수, 조건문을 알고 파일을 실행할 수 있어야 합니다. 예제의 list[str] 표기는 Python 3.9 이상에서 실행됩니다. Windows는 py --version, macOS·Linux는 python3 --version으로 버전을 확인하세요.
[학습목표]
1. 클래스와 인스턴스, 속성과 메서드의 관계를 설명한다.
2. @dataclass가 생성하는 초기화·표현·비교 기능을 활용한다.
3. 타입 힌트와 실행 중 입력 검증의 차이를 구분한다.
[핵심개념]
클래스는 설계도이고, 그 설계도로 만든 실제 값은 인스턴스(instance)입니다. 인스턴스가 가진 title 같은 값은 속성, complete()처럼 상태를 다루는 함수는 메서드입니다. 메서드의 첫 인자 self는 현재 인스턴스를 가리킵니다. 일반 클래스에서는 __init__에 초기화 코드를 직접 쓰지만, @dataclass 장식자(decorator, 클래스에 기능을 덧붙이는 표기)를 붙이면 선언한 필드를 바탕으로 __init__, __repr__, __eq__ 같은 특수 메서드가 자동 생성됩니다.
타입 힌트(type hint)는 title: str이나 -> str처럼 기대하는 자료형을 표시하는 메모입니다. 편집기와 타입 검사기가 실수를 미리 찾는 데 쓰지만 Python 실행기가 자동으로 강제하지는 않습니다. 외부 입력은 별도로 검사해야 합니다. 리스트처럼 바꿀 수 있는 기본값은 field(default_factory=list)를 사용해야 인스턴스마다 새 리스트가 생깁니다.
[따라하기]
아래를 task_demo.py로 저장하세요.
```python
from dataclasses import dataclass, field
@dataclass
class Task:
title: str
done: bool = False
tags: list[str] = field(default_factory=list)
def complete(self) -> None:
self.done = True
def describe(task: Task) -> str:
status = "완료" if task.done else "진행 중"
tags = ", ".join(task.tags) or "없음"
return f"{task.title} | {status} | 태그: {tags}"
first = Task("로그 실습", tags=["python", "tool"])
second = Task("문서 읽기")
first.complete()
second.tags.append("study")
print(describe(first))
print(describe(second))
print(first.tags is second.tags)
```
Windows PowerShell에서는 py task_demo.py, macOS·Linux에서는 python3 task_demo.py를 실행합니다. 추가 패키지는 필요 없습니다.
예상 결과:
```text
로그 실습 | 완료 | 태그: python, tool
문서 읽기 | 진행 중 | 태그: study
False
```
False는 두 Task가 같은 태그 리스트를 공유하지 않는다는 뜻입니다. @dataclass가 생성한 초기화 기능 덕분에 필드 값을 이름으로 전달할 수 있고, complete 메서드는 first의 done만 바꿉니다.
[흔한 실수]
self를 빼거나 task.done 대신 클래스 이름으로 인스턴스 값을 찾으면 의도대로 동작하지 않습니다. tags: list[str] = []처럼 바꿀 수 있는 값을 기본값으로 직접 두면 공유 문제가 생기므로 기본 팩터리를 사용하세요. 모든 자료를 억지로 클래스로 만들 필요도 없습니다. 상태와 그 상태를 다루는 동작이 함께 있고 여러 인스턴스가 필요할 때 선택합니다.
[보안 주의]
타입 힌트는 보안 검사가 아닙니다. 파일·JSON·폼에서 받은 title과 tags는 자료형, 길이, 허용 범위를 실행 중에 검증하세요. 데이터클래스의 자동 표현 문자열에는 필드가 보일 수 있으므로 비밀번호·토큰을 넣지 말고, 꼭 필요한 민감 필드는 field(repr=False)로 출력에서 제외해도 별도 보호가 필요합니다. 출처를 신뢰할 수 없는 pickle 파일은 임의 코드 실행 위험이 있으므로 열지 말고, 교환용 데이터는 검증한 JSON 같은 형식을 사용하세요. 실습은 본인 소유의 로컬 파일에서만 수행합니다.
[직접 해볼 과제]
Task에 priority: int = 1 필드를 추가하고 describe 결과에 우선순위를 표시하세요. 이어서 __post_init__ 메서드에서 빈 제목과 1~5 밖의 우선순위에 ValueError를 발생시키고, 정상 입력과 잘못된 입력을 각각 시험해 보세요.
[확인문제]
1. 클래스와 인스턴스는 어떤 관계인가요?
2. 바꿀 수 있는 리스트의 기본값에 default_factory를 쓰는 이유는 무엇인가요?
3. 타입 힌트만으로 외부 입력 검증이 끝나지 않는 이유는 무엇인가요?
[다음 학습]
JSTS-008에서 제네릭·유니언·타입 좁히기로 JavaScript와 TypeScript의 여러 타입을 안전하게 다루는 방법을 배웁니다.
[공식 참고 자료]
Python 클래스 자습서
https://docs.python.org/3/tutorial/classes.html
Python dataclasses 문서
https://docs.python.org/3/library/dataclasses.html
Python typing 문서
https://docs.python.org/3/library/typing.html
Python pickle 보안 경고
https://docs.python.org/3/library/pickle.html
- 이전글[JSTS-008][중급] 여러 타입을 안전하게 구분하고 재사용하기 26.09.03
- 다음글[TOOL-008][중급] 로그로 오류를 다시 만들고 원인 찾기 26.09.03
댓글목록
등록된 댓글이 없습니다.
