
무엇을 해야하는지에 대해 집중어떻게 해야하는지에 대해 집중import psycopg2
class UserService:
def find_user_by_email(self, email: str):
conn = psycopg2.connect(database="mydb", user="admin")
cursor = conn.cursor()
cursor.execute("SELECT id, email FROM users WHERE email = %s", (email,))
result = cursor.fetchone()
return {"id": result[0], "email": result[1]}
# interfaces.py
from abc import ABC, abstractmethod
class UserRepository(ABC):
@abstractmethod
def find_by_email(self, email: str) -> dict:
pass
class EventPublisher(ABC):
"""이벤트 발행자 추상 인터페이스"""
@abstractmethod
def publish(self, event: Event) -> None:
pass
# postgres_user_repository.py
import psycopg2
from interfaces import UserRepository
class PostgresUserRepository(UserRepository):
def find_by_email(self, email: str) -> dict:
conn = psycopg2.connect(database="mydb", user="admin")
cursor = conn.cursor()
cursor.execute("SELECT id, email FROM users WHERE email = %s", (email,))
result = cursor.fetchone()
return {"id": result[0], "email": result[1]}
# mysql_user_repository.py
import mysql_opg
from interfaces import UserRepository
class MySqlUserRepository(UserRepository):
def find_by_email(self, email: str) -> dict:
conn = mysql_opg.connect(database="mydb", user="admin")
cursor = conn.cursor()
cursor.execute("SELECT id, email FROM users WHERE email = %s", (email,))
result = cursor.fetchone()
return {"id": result[0], "email": result[1]}
# kafka_event_publisher.py
from event_interfaces import EventPublisher, Event
class KafkaEventPublisher(EventPublisher):
"""Kafka를 사용한 이벤트 발행 구현체"""
def publish(self, event: Event) -> None:
pass
# rabbitmq_event_publisher.py
from event_interfaces import EventPublisher, Event
class RabbitMQEventPublisher(EventPublisher):
def publish(self, event: Event) -> None:
...
# user_service.py
class UserService:
def __init__(self, repo: UserRepository, event_publisher: EventPublisher): # 런타임 의존성 발생
self.repo = repo
self.event_publisher = event_publisher
def find_user_by_email(self, email: str):
self.event_publisher.publish(event)
return self.repo.find_by_email(email)
즉 비즈니스 로직이 인프라(DB, 써드파티 등) 에 의존하면 안된다
완전 초기 시작 부터 또는 정말 규모가 큰 경우layered architercutre 의 가장 큰 문제점: 사고의 흐름을 강제함
사용자
User table
일반 사용자 / vip 사용자 가 있음
디렉토리 구조는 벌써 사용자(User) 로 만들어짐
├── User/
│ ├── service/
│ │ ├── normal_user_service.py
│ │ └── vip_user_service.py
│ ├── repository/
│ │ └── user_respository.py
최악) 이제 “사용자” 를 사용하는 모든 user_case 에서 저 service 혹은 repository 를 조회하게 됨

런타임 의존성 = 개발할때는 뭐가 의존되는지 모름
class UserService:
def __init__(self, repo: UserRepository, event_publisher: EventPublisher): # 런타임 의존성 발생
self.repo = repo
self.event_publisher = event_publisher
def find_user_by_email(self, email: str):
self.event_publisher.publish(event)
return self.repo.find_by_email(email)
find_by_email 등에 대해서 명확한 예외 처리가 되어있지 않으면 문제 발생시 일일히 찾아가줘야함