우선 개조식으로 작성했고, 추후 업데이트하도록 하겠음.
서버 만들면서 제일!! 많이 공부가된?? 공부를한?! 부분인데 메모장에만 있다가 모아서 정리함.
들어가며…
C/Java 같은 언어 → 변수 = 값을 담는 상자 개념 → b = a 값이 복사된다고 이해하는 게 자연스러움
파이썬 → 변수는 상자가 아니라 객체에 붙는 이름표(label)
Q1) a = 1; b = a; a = 2 에서 왜 b는 그대로일까?
Q2) 리스트/딕셔너리를 복사했는데 왜 같이 바뀔까?
→ 불변 vs 가변 객체 차이를 알아보자.
1. 불변 객체 (Immutable)
- 예: int, float, str, tuple
- 특징: 새로운 값을 할당하면 새 객체 생성, 기존 참조와 끊김, 값이 복사된 것처럼 동작
a = 1
b = a
a = 2
print(a) # 2
print(b) # 1
2. 가변 객체 (Mutable)
- 예: list, dict, set, 사용자 정의 객체
- 특징: 같은 객체를 바라보고 있으면 수정이 공유됨, 참조에 의한 할당 → 한쪽 변경이 다른 쪽에 반영
config = {"mode": "debug"}
alias = config # 같은 객체를 참조
config["mode"] = "release"
print(alias["mode"]) # release
3. 클래스 속성에서의 참조 vs 값 복사
- 참조 저장 → 원본 변경 시 같이 반영
- 값 복사 → 원본과 무관하게 독립 유지
# settings.py
class Settings:
def __init__(self, options: dict):
self.options = options # 참조 저장
self.mode = options["mode"] # 값 복사
# main.py
from settings import Settings
options = {"mode": "debug"}
app_settings = Settings(options)
print("초기 상태:")
print("options['mode']:", options["mode"]) # debug
print("app_settings.options['mode']:", app_settings.options["mode"]) # debug
print("app_settings.mode:", app_settings.mode) # debug
# 원본 options 변경
options["mode"] = "release"
print("\n변경 후:")
print("options['mode']:", options["mode"]) # release
print("app_settings.options['mode']:", app_settings.options["mode"]) # release
print("app_settings.mode:", app_settings.mode) # debug
----------------------------결과----------------------------
초기 상태:
options['mode']: debug
app_settings.options['mode']: debug
app_settings.mode: debug
변경 후:
options['mode']: release
app_settings.options['mode']: release
app_settings.mode: debug
결과: options["mode"] 변경 시 → self.options["mode"]는 같이 바뀜, self.mode는 그대로 유지
4. 가비지 컬렉션 (GC: Garbage Collection)
- 기본 원리: 파이썬은 참조 카운트(reference count) 방식으로 메모리를 관리
- 객체의 참조 카운트가 0이 되는 순간 → 즉시 해제 대상
a = [1, 2, 3]
b = a
a = None
b = None
# 리스트 [1,2,3]을 더 이상 참조하는 변수가 없으므로 GC 대상
- 파이썬은 순환 참조(list 안에 자기 자신 포함 등)를 처리하기 위해 주기적으로 GC 모듈이 동작
- 하지만 대부분의 경우 → 단순 참조 해제 시점에서 바로 객체 정리됨
5. 응용: DI 컨테이너 구조
- 원리: 딕셔너리 같은 가변 객체에 서비스 객체 등록/공유
- 클라이언트는 컨테이너에서 꺼내 쓰기만 하면 됨
from abc import ABC, abstractmethod
# 공통 인터페이스
class BaseService(ABC):
@abstractmethod
def run(self, x, y): ...
class AddService(BaseService):
def run(self, x, y):
return x + y
class SubService(BaseService):
def run(self, x, y):
return x - y
# DI 컨테이너
class Container:
def __init__(self):
self.services = {}
def register(self, name, service):
self.services[name] = service
def resolve(self, name):
return self.services.get(name)
# 사용
c = Container()
c.register("add", AddService())
c.register("sub", SubService())
print(c.resolve("add").run(5, 3)) # 8
print(c.resolve("sub").run(10, 4)) # 6
- Container 클래스 → register()로 등록, resolve()로 꺼냄
- AddService, SubService 같은 서비스 객체 저장/실행
- 참조 공유 원리를 이용해 “중앙 관리” 구현 가능
'Tips' 카테고리의 다른 글
| 파이썬 환경 구성 (0) | 2025.08.30 |
|---|---|
| MySQL GENERATED 칼럼 사용법 (3) | 2025.08.16 |
| FastAPI 실행 및 문서 접근 가이드 (0) | 2025.06.21 |
| [Rabbitmq] ERROR: could not bind to distribution port (0) | 2025.06.06 |
| pm2로 python 데몬화 (0) | 2025.05.31 |