Python/FastAPI / / 2023. 1. 6. 10:10

FastAPI 알아보기 - 의존성 주입, Dependencies, Dependency Injection

What is Dependency?

 

의존성 주입이라는 것을 많이들 들어봤을 것이다. 그 전에 Dependency, 즉 의존성에 대해서 이야기 해봐야 될 것 같다. 의존성은 두 Class사이에서 나타나는 관계이다. A라는 Class가 있고 B라는 Class가 있으면, A라는 Class가 B라는 Class에 의존하고 있고 B라는 Class는 A에 의존하거나 그렇지 않은 경우를 말한다. 즉, A <-> B이기 때문에, 한 Class의 기능이 바뀌면 다른 Class에도 영향을 주는 것이다.

 

예를 들어보겠다, 다음과 같은 코드가 있다고 하자.

 

import datetime

class Customer:
	customer_id: str = ""
    customer_name: str = ""
    
class Order:
	order_id: str = 0
    order_customer_id: str = ""
    order_date_time: datetime.datetime

	def order(self, customer: Customer):
    	self.order_customer_id = customer.customer_id

위의 코드에서 Customer Class가 있고, Order Class가 있다. 여기서 Order Class가 Customer Class의 instance를 사용한다. 만약 customer_id를 str에서 int로 바꾼다면 Order Class에도 영향을 미치게 된다. 이러한 관계가 바로 의존관계라고 할 수 있다. 

 

이러한 의존 관계는 여러가지 타입이 있다.

  1. Class Dependencies
  2. Interface Dependencies
  3. Method / Field Dependencies

What is Dependency Injection?

먼저 Dependency Injection(이하, DI)에서는 다음과 같이 경고? 아니면 위험성에 대해 이야기하고 있다.

  • DI에서 객체간의 Tight Coupling은 아주 좋지 않다.
  • 의존 Class는 의존 관계를 만들기에 아주 좋지 않다. 

여기서 Tight Coupling은 Class들 간의 관계가 아주 강하게 연결, 의존되어 있을 때를 의미한다. 즉, 서로가 서로에 대해 책임소재를 묻는 관계라고 말할 수 있다. 이와 반대되는 Loose Coupling은 각자에게 책임이 있다는 것을 의미한다. 즉 의존 관계가 느슨하다고 볼 수 있다.

 

FastAPI공식 문서에서는 다음과 같이 DI를 설명하고 있다.

 

"Dependency Injection" means, in programming, that there is a way for your code to declare things that it requires to work and use: "dependencies".

프로그래밍에서 "의존관계 주입"이란, 코드에서 선언한 것들이 "의존관계"를 사용하기 위해 요구되는 것이다.

 

즉, FastAPI시스템에서 의존성주입이란 하나의 객체가 다른 객체의 의존성을 제공하는 테크닉이다. 이것을 좀 더 풀어서 설명해 보겠다.

  • 의존성 : 서비스로 사용할 수 있는 객체, Client가 있다면 어떤 서비스를 사용할 것인지 지정하는 대신, 어떤 서비스를 제공하는지 말해주는 것이다.
  • 주입 : 서비스를, 이것을 사용하려는 객체(Client)에 전달하는 것이다. 

그렇다면 여기서 Dependency Inversion Principle (DIP) 에 대해서 설명하고 넘어가야 겠다. 

 

DIP를 한말로 설명하면, "추상화에 의존한되, 구체화에 의존하면 안된다."라는 것이다. 이것을 좀 더 풀어서 설명하면, "고수준 모듈은 저수준 모듈의 구현에 의존하면 안되며, 저수준 모듈이 고수준 모듈에서 만든 추상 계층에 의존해야 한다는 것이다.

  • 고수준 모듈 : 어떤 의미있는 단일 기능을 제공하는 모듈
  • 저수준 모듈 : 고수준 모듈의 기능 구현에 필요한 하위 기능의 실제 구

위의 그림처럼, 저수준 모듈의 경우 자주 바뀌기 때문에, 추상화 모듈에 의존해야 한다. 이때 고수준 모듈은 아주 핵심 부분이라고 볼 수 있으며, 자주 바뀌면 안되는 부분이다. 이러한 DIP의 한 종류가 바로 IoC이다. 그렇다면 이제 설명이 어느정도 끝났으니 본격적으로 실제 코드를 보면서 DI가 어떻게 이루어지는지, FastAPI에서 어떻게 이루어지는지를 알아보고 가겠다.

 

Simple Example

from fastapi import Depends, FastAPI

app = FastAPI()


async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "limit": limit}


@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons


@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return commons

가장 중요한 Line이 바로 common_parameters를 의미한다. 이것이 위에서 설명한 서비스를 의미한다. 그렇다면 여기서 Client는 무엇이 될까? 바로 read_items와 read_users가 된다. 

 

다음 글에서 좀 더 자세하게 FastAPI에서의 Dependencies Injection에 대해 알아보겠다.

 

 

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유