반응형

가상환경 생성

기본적으로 .venv 디렉토리에 가상환경이 생성된다.

uv venv

 

특정 이름이나 경로로 가상환경을 생성하려면 다음과 같이 실행한다.

uv venv my-env

 

특정 Python 버전을 지정하여 가상환경을 생성할 수도 있다.

uv venv --python 3.11

이 명령어는 지정한 버전의 Python을 설치하고 해당 버전으로 가상환경을 생성


가상환경 활성화

생성된 가상환경을 활성화하려면 아래의 명령어를 사용

  • macOS/Linux
source .venv/bin/activate

 

  • Windows
.venv\Scripts\activate

 


가상환경 내에서 패키지 설치

가상환경이 활성화된 상태에서 패키지를 설치하려면 uv pip 명령어를 사용한다.

uv pip install requests

 

또는 uv add 명령어를 사용하여 의존성을 추가할 수 있다.

uv add requests

 

이렇게 하면 pyproject.toml 파일에 의존성이 추가되고, 가상환경에 해당 패키지가 설치된다.


uv 가상환경 관리 장점

  • 속도: uv venvpyhton -m venv보다 최대 80배, virtualenv보다 7배 빠르게 가상환경을 생성한다.
  • 통합 관리: 가상환경 생성, 패키지 설치, Python 버전 관리 등을 하나의 도구로 통합하여 관리할 수 있다.​
  • 자동 감지: uv run, uv sync 등의 명령어를 사용할 때, .venv 디렉토리가 존재하면 자동으로 해당 가상환경을 사용한다.​

추가 팁: VSCode에서 사용하기

VSCode에서 uv로 생성한 가상환경을 사용하려면 다음과 같이 설정할 수 있다.

  1. VSCode의 명령 팔레트를 열고 (Ctrl+Shift+P), Python: 인터프리터 선택
  2. 목록에서 .venv 디렉토리의 Python 인터프리터를 선택한다.​
  3. 만약 목록에 나타나지 않는다면, 인터프리터 경로 입력을 선택하고 .venv/bin/python (Windows의 경우 .venv\Scripts\python.exe) 경로를 직접 입력한다.

 

 

 

반응형
반응형

각 도구의 특징 요약

pip

  • 장점: python 기본 포함, 간단한 사용법
  • 단점: 의존성 관리 및 가상환경 설정 수동 필요

Poetry

  • 장점: Pipfile을 통한 의존성 관리, 가상환경 자동 생성
  • 단점: 속도가 느리고, 일부 기능이 불안정할 수 있음​

pyenv

  • 장점: 여러 Python 버전 관리에 특화
  • 단점: 패키지 관리 기능 없음, 다른 도구와 함께 사용 필요​

uv

  • 장점: Rust로 개발되어 매우 빠른 속도, 패키지 설치, 의존성 관리, 가상환경 및 Python 버전 관리, 패키지 배포 등 통합 기능 제공
  • 단점: 상대적으로 새로운 도구로, 커뮤니티 지원이 제한적일 수 있음​

 


도구 선택

  • 간단한 프로젝트: pip과 venv 조합이 충분
  • 복잡한 의존성 관리 및 배포 필요: Poetry 추천
  • Python 버전 관리 중심: pyenv 활용
  • 속도와 통합 관리 중시: uv 고려

*uv 관련해서는 아래의 글 참고

 

Python 개발자라면 - uv로 패키지 관리하기

uv는 Rust로 개발된 초고속 Python 패키지 및 프로젝트 관리자이다.기존의 pip, virtualenv, poetry, pyenv 등을 통합하여 하나의 도구로 대체할 수 있으며, 속도와 효율성 면에서 큰 장점을 제공한다. 주요

ryu-earth.tistory.com

 


정리 내용

*아래의 정리 내용은 GPT에서 생성했습니다.

기능 / 도구 pip Poetry Pipenv pyenv uv
패키지 설치 ✅ 기본 기능 ✅ 내장 ✅ 내장 ✅ 매우 빠름
의존성 관리 ❌ 수동 관리 ✅ 자동 관리 ✅ 자동 관리 ✅ 자동 관리
가상환경 관리 ❌ 수동 설정 ✅ 내장 ✅ 내장 ✅ 자동 생성
Python 버전 관리 ❌ 외부 도구 필요 ❌ 외부 도구 필요 ❌ 외부 도구 필요 ✅ 핵심 기능 ✅ 내장
속도 보통 느림 느림 보통 🚀 매우 빠름
구성 파일 requirements.txt pyproject.toml Pipfile .python-version pyproject.toml
잠금 파일 지원 ❌ 없음 ✅ poetry.lock ✅ Pipfile.lock ✅ 자동 생성
CLI 명령어 직관성 단순 명확 다소 복잡 단순 직관적
패키지 배포 지원 ❌ 외부 도구 필요 ✅ 내장 ❌ 외부 도구 필요 ✅ 내장
설치 방식 Python 기본 포함 별도 설치 필요 별도 설치 필요 별도 설치 필요 단일 바이너리 설치 가능

 

반응형
반응형

uv는 Rust로 개발된 초고속 Python 패키지 및 프로젝트 관리자이다.

기존의 pip, virtualenv, poetry, pyenv 등을 통합하여 하나의 도구로 대체할 수 있으며, 속도와 효율성 면에서 큰 장점을 제공한다.

 

 

주요 특징 및 장점

  • 속도: uv는 pip 대비 10~100배 빠른 성능을 자랑함.
  • 통합 도구: 패키지 설치, 의존성 관리, 가상환경 생성, Python 버전 관리 등을 하나의 도구로 처리할 수 있다.
  • Rust 기반: Rust로 작성되어 안정성과 성능이 뛰어난다.
  • 간편한 설치: 단일 바이너리로 제공되어 설치가 간편하다.

종속성을 해결(왼쪽)하고 설치(오른쪽)

 


설치 방법

# macOS 및 Linux에서 설치
curl -LsSf https://astral.sh/uv/install.sh | sh

# Homebrew를 이용한 설치 (macOS)
brew install uv

# pip를 이용한 설치
pip install uv

 

설치 후, 터미널에서 설치가 완료되었는지 확인

uv --version

 

 


기본 사용법

프로젝트 초기화

uv init my-project

 

--app 또는 --lib 옵션을 사용하여 애플리케이션 또는 라이브러리 프로젝트로 초기화 할 수 있다.

 

uv에서 "프로젝트 초기화"는 새로운 Python 프로젝트의 기본 구조를 자동으로 생성하는 과정이다.
이는 개발자가 코드를 작성하기 전에 필요한 설정과 파일을 미리 구성하여, 개발을 빠르고 효율적으로 시작할 수 있도록 도와준다.

 

uv init 명령어로 생성되는 프로젝트 구성

  • pyproject.toml: 프로젝트의 메타데이터와 의존성 정보를 담은 설정 파일
  • main.py: 간단한 "Hello, World!" 예제가 포함된 Python 스크립트
  • README.md: 프로젝트에 대한 설명을 작성할 수 있는 문서
  • .python-version: 사용할 Python 버전을 명시하는 파일

패키지 추가 및 동기화

 
uv add requests
uv sync

 

uv add로 패키지를 추가하고, uv sync로 의존성을 동기화

 


가상환경 실행

uv python list
uv python install 3.12

 

uv run을 사용하여 가상환경에서 스크립트를 실행할 수 있다.

 


Python 버전 관리

uv python list
uv python install 3.12

 

uv python 명령어로 다양한 Python 버전을 관리 가능

 


참고자료

 

 

uv

An extremely fast Python package and project manager, written in Rust. Installing Trio's dependencies with a warm cache. 🚀 A single tool to replace pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv, and more. ⚡️ 10-100x faster than pip. 🗂️

docs.astral.sh

 

uv: Python packaging in Rust

uv is an extremely fast Python package installer and resolver, designed as a drop-in alternative to pip and pip-tools.

astral.sh

 

 

 

반응형
반응형

https://ryu-earth.tistory.com/entry/Python-JS-WebRTC-%EC%98%88%EC%A0%9C-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%98%88%EC%8B%9C

 

[Python & JS] WebRTC 예제 & 시나리오 예시

WebRTC가 궁금하면 여기에 참고 https://ryu-earth.tistory.com/entry/WebRTC-vs-WebSocket WebRTC vs WebSocketWebRTC와 WebSocket은 둘 다 브라우저 간 실시간 데이터 전송을 가능하게 해주지만, 목적과 동작 방식이 다르다

ryu-earth.tistory.com

  • 브라우저 또는 앱 간 P2P 실시간 통신 기술
  • 영상, 음성, 데이터 스트림 전송 가능
  • Python에서는 aiortc 라이브러리로 구현 가능

 


Python WebRTC 개발 구조

  1. PeerConnection 생성
  2. DataChannel or MediaTrack 설정
  3. off/answer 교환 (시그널링 필요)
  4. P2P 통신 실행


설치

pip install aiortc websockets

 

https://github.com/aiortc/aiortc

 

GitHub - aiortc/aiortc: WebRTC and ORTC implementation for Python using asyncio

WebRTC and ORTC implementation for Python using asyncio - aiortc/aiortc

github.com

 


Python WebRTC DataChannel P2P 예제

peer_a.py (initiator)

import asyncio
from aiortc import RTCPeerConnection, RTCSessionDescription

async def run_offer():
    pc = RTCPeerConnection()
    channel = pc.createDataChannel("chat")

    @channel.on("open")
    def on_open():
        print("DataChannel open!")
        channel.send("Hello from A!")

    @channel.on("message")
    def on_message(message):
        print(f"Received: {message}")

    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)
    print("=== Offer ===")
    print(pc.localDescription.sdp)

    sdp = input("Paste answer SDP:\n")
    await pc.setRemoteDescription(RTCSessionDescription(sdp, type="answer"))

    await asyncio.sleep(10)

asyncio.run(run_offer())

 

peer_b.py (receiver)

import asyncio
from aiortc import RTCPeerConnection, RTCSessionDescription

async def run_answer():
    pc = RTCPeerConnection()

    @pc.on("datachannel")
    def on_datachannel(channel):
        @channel.on("message")
        def on_message(message):
            print(f"Received: {message}")
            channel.send("Hello from B!")

    sdp = input("Paste offer SDP:\n")
    await pc.setRemoteDescription(RTCSessionDescription(sdp, type="offer"))

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    print("=== Answer ===")
    print(pc.localDescription.sdp)

    await asyncio.sleep(10)

asyncio.run(run_answer())

 

  • pc = RTCPeerConnection()개발구조 1번
  • createDataChannel() 또는 @pc.on("datachannel") 개발구조 2번
  • createOffer(), setLocalDescription(), setRemoteDescription()개발구조 3번
  • DataChannel의 open/메시지 주고받기 → 개발구조 4번
개발구조 단계 코드 위치
1. PeerConnection 생성 pc = RTCPeerConnection()
2. DataChannel 설정 createDataChannel() & @pc.on("datachannel")
3. offer/answer 교환 createOffer(), setLocalDescription(), setRemoteDescription()
4. 통신 실행 DataChannel on_open, on_message 핸들러

 


Python WebSocket 시그널링 서버 예제

import asyncio
import websockets

clients = set()

async def signaling_handler(websocket, path):
    clients.add(websocket)
    try:
        async for message in websocket:
            await asyncio.wait([ws.send(message) for ws in clients if ws != websocket])
    finally:
        clients.remove(websocket)

start_server = websockets.serve(signaling_handler, "localhost", 9999)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

 

 


개발 시 주의사항

이슈 원인 해결
P2P 연결 안 됨 STUN 서버 미설정, NAT 환경 STUN 서버 추가 설정
시그널링 기능 없음 aiortc에는 기본 시그널링 서버 없음 WebSocket 서버 직접 구현
DataChannel 연결 안 됨 offer/answer 교환 전 DataChannel 생성 문제 생성 순서 및 이벤트 핸들러 확인
영상 전송 시 지연/버벅임 프레임 크기, 캡처 성능 이슈 비동기 처리 최적화, 프레임 크기 조절

STUN 서버 등록 예시

*STUN 서버: NAT 환경에서 클라이언트가 공인 IP 주소와 포트를 확인하여 다른 피어와 직접 통신하도록 돕는 서버
 
pc = RTCPeerConnection(configuration={"iceServers": [{"urls": "stun:stun.l.google.com:19302"}]})

 


WebRTC 특징 정리

  • WebRTC API가 브라우저처럼 내장되어 있지 않음
  • aiortc 라이브러리로 P2P 실시간 통신 가능
  • 시그널링 서버, STUN/TURN 서버 직접 구성 필요
  • 영상, 음성, 데이터 전송 모두 구현 가능
  • 데스크탑, 서버, IoT 환경에 적합

 

용도 구현 방식
데이터 전송 DataChannel 사용
영상/음성 스트림 MediaStreamTrack 상속 & 커스텀 구현
시그널링 서버 Python WebSocket 직접 구현
NAT 통과 STUN/TURN 서버 설정
반응형
반응형

WebRTC가 궁금하면 여기에 참고

 

https://ryu-earth.tistory.com/entry/WebRTC-vs-WebSocket

 

WebRTC vs WebSocket

WebRTC와 WebSocket은 둘 다 브라우저 간 실시간 데이터 전송을 가능하게 해주지만, 목적과 동작 방식이 다르다. WebRTC란?Web Real-Time Communication의 약자브라우저 간 P2P(Peer-to-Peer) 실시간 오디오, 비디오,

ryu-earth.tistory.com

 

 

  • 브라우저 간 P2P 실시간 통신 가능
  • 영상, 음성, 데이터 스트림 전송 가능
  • WebSocket 같은 서버를 통해 시그널링(초기 연결 설정 정보 교환) 필요

 


WebRTC 시나리오 & 코드

실시간 영상/음성 통화

  • 브라우저끼리 실시간 비디오/오디오 스트림 주고받기

Peer A

// 브라우저 JavaScript 

const peerA = new RTCPeerConnection();
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
  .then(stream => {
    stream.getTracks().forEach(track => peerA.addTrack(track, stream));
  });

peerA.createOffer().then(offer => {
  peerA.setLocalDescription(offer);
  // 시그널링 서버로 offer 전송
});

 

 

Peer B

const peerB = new RTCPeerConnection();
peerB.ontrack = event => {
  const video = document.querySelector("#remoteVideo");
  video.srcObject = event.streams[0];
};
// 시그널링 서버로부터 offer 받고 answer 생성

 


P2P 데이터 전송 (DataChannel)

  • 브라우저 간 텍스트/파일 전송

Peer A

const peerA = new RTCPeerConnection();
const dataChannel = peerA.createDataChannel("chat");

dataChannel.onopen = () => {
  dataChannel.send("Hello from A!");
};

peerA.createOffer().then(offer => peerA.setLocalDescription(offer));

 

Peer B

const peerB = new RTCPeerConnection();
peerB.ondatachannel = event => {
  const receiveChannel = event.channel;
  receiveChannel.onmessage = e => console.log("Received:", e.data);
};

 

 


시그널링 서버 구축 (Python WebSocket)

  • WebRTC 연결을 위해 Off/answer/ICE candidate 정보를 중개하는 서버

python WebSocket 시그너링 서버

 

import asyncio
import websockets

clients = set()

async def signaling_handler(websocket, path):
    clients.add(websocket)
    try:
        async for message in websocket:
            await asyncio.wait([ws.send(message) for ws in clients if ws != websocket])
    finally:
        clients.remove(websocket)

start_server = websockets.serve(signaling_handler, "localhost", 9999)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

 

→ WebRTC offer/answer/ICE 정보를 이 서버로 전달하고 상대 peer에게 중계

 

 


+ python에서도 aiotc 라이브러리를 통해 WebRTC peer를 구현할 수 있다.

(다음 글에)

반응형
반응형

Pydantic이란 무엇인가?

Pydnatic은 Python에서 데이터 검증, 설정 및 직렬화/역직렬화 작업을 간편하게 처맇라 수 있도록 돕는 라이브러리이다. Pydantic의 주요 목적은 정확하고 안전하게 데이터를 다룰 수 있도록 해주는 것으로, 주로 JSON, Dict, Model 형태의 데이터를 효율적으로 처리하고 검증하는데 사용된다.

 

Pydantic은 BaseModel을 통해 명시적인 데이터 모델을 정의하고, 해당 모델의 필드가 특정 조건을 충족하는지 자동으로 검증해준다. 예를 들어, str, int, float, datetime과 같은 데이터 타입에 맞는 값을 설정하고, 타입이 맞지 않거나 필수 값이 빠졌을 경우 자동으로 에러를 발생시킨다.


비공개 속성이 필요한 이유

python에서 클래스의 속성은 기본적으로 공개되어, 외부에서 접근하고 수정할 수 있다. 그러나 클래스 외부에서 접근하거나 수정하지 말아야 할 데이터가 필요하고 이러한 데이터는 내부 로직을 처리하는 데만 사용되며, 외부와의 데이터 교환에서 제외되어야 한다.

 

비공개 속성의 필요성

1. 보안

  • 민감한 데이터(예: 비밀번호,  API키, 토큰 등)는 외부에 노출 되지 않아야 하고, 이를 보호하기 위해 해당 데이터를 비공개 속성으로 관리해야한다.
from pydantic import BaseModel, PrivateAttr

class User(BaseModel):
    username: str
    password: str
    _session_token: str = PrivateAttr()  # 세션 토큰, 외부에 노출될 필요 없음

    def authenticate(self, token: str):
        # 세션 토큰 검증 로직
        if self._session_token == token:
            return True
        return False

    def generate_token(self):
        # 임의의 세션 토큰 생성 로직
        self._session_token = "secret_session_token"
        return self._session_token

 

2. 내부 로직 캡슐화

  • 특정 속성은 외부에서 수정될 필요가 없고, 낸부적인 계산이나 상태 추적을 위해 사용될 수 있다. 예를들어, _internal_value와 같은 속성은 외부와의 상호작용에 필요하지 않지만 클래스 내부에서 중요한 역할을 할 수 있다.
  • 데이터 은닉(Encapsulation)은 객체 지향 프로그래밍에서 중요한 개념으로, 클래스 외부에서 불필요한 접근을 제한하고 내부 구현을 캡슐화하는데 사용된다.
from pydantic import BaseModel, PrivateAttr

class MyModel(BaseModel):
    name: str
    _internal_value: int = PrivateAttr(42)  # 기본값을 PrivateAttr로 설정

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._internal_value += 1  # 내부값을 초기화하면서 변경

# 사용 예
model = MyModel(name="Test")
print(model.name)  # 'Test' (직렬화가 되므로 name은 접근 가능)
print(model._internal_value)  # '42' (직접 접근할 수 있지만, 일반적으로 권장되지 않음)

 

3. 데이터 무결성 유지

  • 일부 속성은 클래스 외부에서 잘못 수정되면 프로그램의 로직이 깨질 수 있는 중요한 데이터일 수 있다. 이러한 솏어은 외부에서 수정되지 않도록 보호하고, 내부에서만 제어될 필요가 있다.
from pydantic import BaseModel, PrivateAttr

class Product(BaseModel):
    name: str
    price: float
    _price_history: list[float] = PrivateAttr(default_factory=list)

    def apply_discount(self, discount_percentage: float):
        # 할인율을 적용한 가격을 계산하여 가격 변경
        self._price_history.append(self.price)
        self.price = self.price * (1 - discount_percentage / 100)

    def revert_price(self):
        # 이전 가격으로 되돌리기
        if self._price_history:
            self.price = self._price_history.pop()

# 사용 예시
product = Product(name="Laptop", price=1000)
product.apply_discount(10)
print(product.price)  # 900.0
product.revert_price()
print(product.price)  # 1000.0
print(product.dict())  # {'name': 'Laptop', 'price': 1000.0}
print(product._price_history)  # 접근 불가, 직렬화에서 제외됨

 

4. 상속 관계에서의 속성 관리

  • 상속을 사용할 때, 부모 클래스에서 정의된 속성이 자식 클래스에서 사용되거나 수정되지 않도록 비공개 속성으로 관리할 수 있다. 자식 클래스에서 부모 클래스의 속성에 직접 접근할 수 없게 되므로, 상속 구조에서의 안정성을 높여준다.
from pydantic import BaseModel, PrivateAttr

class Vehicle(BaseModel):
    brand: str
    _engine_status: str = PrivateAttr("OFF")  # 부모 클래스에서 비공개로 처리

    def start_engine(self):
        self._engine_status = "ON"

    def stop_engine(self):
        self._engine_status = "OFF"

class Car(Vehicle):
    model: str

    def get_engine_status(self):
        return self._engine_status

# 사용 예시
car = Car(brand="Toyota", model="Corolla")
car.start_engine()
print(car.get_engine_status())  # "ON"
print(car.dict())  # {'brand': 'Toyota', 'model': 'Corolla'}
print(car._engine_status)  # 접근 불가, 직렬화에서 제외됨

 


PrivateAttr의 필요성과 목적 설명

Pydantic의 PrivateAttr은 비공개 속성을 정의하기 위한 기능이다. PrivateAttr을 사용하면 Pydantic 모델에서 직렬화 및 외부 접근에서 제외되는 속성을 설정할 수 있다. PrivateAttr은 단순히 속성을 숨기거나 보호하는 목적 외에도, 모델 내에서 중요한 데이터를 안전하게 관리하고, 외부와의 데이터 처리에서 발생할 수 있는 실수를 방지하는 역할을 한다.

 

PrivateAttr의 목적

1. 직렬화에서 제외

  • PrivateAttr로 정의된 속성은 모델을 dict()나 json()으로 직렬화할 때 자동으로 제외된다. 이는 외부 API나 데이터베이스에 불필요한 정보를 노출하지 않게 해준다.
from pydantic import BaseModel, PrivateAttr

class SensitiveData(BaseModel):
    username: str
    _password_hash: str = PrivateAttr()  # 비밀번호 해시, 직렬화에서 제외됨

    def set_password(self, password: str):
        self._password_hash = hash(password)  # 비밀번호를 해시로 저장

# 사용 예시
user = SensitiveData(username="alice", _password_hash="hashed_password")
print(user.dict())  # {'username': 'alice'}
# _password_hash는 dict에 포함되지 않음

 

2. 내부 상태 관리

  • 모델의 외부 인터페이스에 포함되지 않지만, 모델의 내부 상태를 추적하거나, 비즈니스 로직을 구현하는데 필요한 데이터를 저장하는데 사용된다. 
  • 예를 들어, 모델이 특정 값을 계산하거나, 일시적인 데이털르 추절해야 할 때 유용
from pydantic import BaseModel, PrivateAttr

class Order(BaseModel):
    order_id: str
    total_amount: float
    _processing_status: str = PrivateAttr("pending")  # 주문 처리 상태, 외부에서 수정되지 않음

    def process_order(self):
        self._processing_status = "processed"  # 상태 변경

    def get_processing_status(self):
        return self._processing_status

# 사용 예시
order = Order(order_id="ORD123", total_amount=100)
order.process_order()
print(order.get_processing_status())  # "processed"
print(order.dict())  # {'order_id': 'ORD123', 'total_amount': 100}

 

3. 객체 불변성 유지

  • PrivateAttr을 사용하여 외부에서 속성 값을 수정할 수 없게 만들어, 객체의 불변성을 유지할 수 있다. 이는 특히 클래스 내부에서만 사용되며 외부와는 관련 없는 속성을 다룰 때 중요하다.
from pydantic import BaseModel, PrivateAttr

class Rectangle(BaseModel):
    width: float
    height: float
    _area: float = PrivateAttr()

    def __init__(self, width: float, height: float):
        super().__init__(width=width, height=height)
        self._area = self.calculate_area()

    def calculate_area(self) -> float:
        return self.width * self.height

    @property
    def area(self):
        return self._area

# 사용 예시
rect = Rectangle(width=10, height=5)
print(rect.area)  # 50
# 외부에서 _area를 수정하려고 할 수 없고, 직렬화 시에도 제외됨

 

4. 보안성 강화

  • 민감함 데이터나 외부에 노출되지 않아야 하는 값들(예: 비밀번호, 인증 키 등)을 PrivateAttr로 설정하면 보안을 강화할 수 있다. 이렇게 설정된 값은 외부에 노출되지 않으며, 클래스 외부에서 접근할 수 없다.
from pydantic import BaseModel, PrivateAttr

class APIClient(BaseModel):
    client_id: str
    _api_key: str = PrivateAttr()  # API 키, 외부에서 접근할 수 없음

    def set_api_key(self, api_key: str):
        self._api_key = api_key

    def get_api_key(self) -> str:
        return self._api_key

# 사용 예시
client = APIClient(client_id="my_client_id")
client.set_api_key("my_secret_api_key")
print(client.get_api_key())  # "my_secret_api_key"
print(client.dict())  # {'client_id': 'my_client_id'}
# _api_key는 직렬화에서 제외됨

 


결론

  • Pydnatic은 데이터 모델링 및 검증을 위한 도구로, 데이터의 유효성 검사와 직렬화/역직렬화를 쉽게 처리할 수 있게 해준다. 이를 통해 안전하고 효율적인 데이터 관리가 가능하다.
    (직렬화: 데이터를 저장하거나 전송하기 위해 객체를 특정 형식 (Json, XML)으로 변환하는 과정)
    (역직렬화: 직렬화된 데이터를 다시 원래 객체나 데이터 구조로 복원하는 과정)
  • 비공개 속성은 보안과 내부 로직 캡슐화, 데이터 무결성 유지 등의 이유로 필요하다. 특히, 클래스 내부에서마 사용되며 외부에 노출될 필요가 없는 데이터를 다룰 때 유용하다.
  • PrivateAttr은 비공개 속성을 모델 내에서 정의하고 관리할 수 있도록 도와주는 기능으로, 직렬화에서 제외되고 외부에서 접근 불가능한 속성을 안전하게 관리할 수 있게 해준다.
반응형

+ Recent posts