티스토리 뷰
배경
현재 업무에서는 import_module 을 통해 다양한 플러그인들을 동적으로 import 하여, 사용자의 입력을 검증하는 부분이 존재한다.
이때 구체적으로는 각 플러그인 별 validate 함수를 호출하는 방식으로 처리된다.
이러한 validate 함수는 사용자가 어떤 요청을 "생성" 하는 시점에 호출되며 [중복됨, 입력 불충분, ] 과 같은 응답을 제공한다.
문제 사항
과거에 validate 는 사용자가 특정 요청을 "생성" 하는 경우에만 필요했다.
기획 변경에 의해 "생성", "수정", "재생성"의 시점 모두에서 validate 를 필요로 하게 되었다.
따라서, action_type 이라는 optional parameter가 전달 -> 각 플러그인 단에서 validate 로직을 재작성 할 필요가 생겼다.
그러나, 일부 케이스들에 대해서는 "수정", "재생성" 자체가 막혀있다.
요약하자면
1. 사용자의 요청 -> 서비스 layer 측에서 plugin 을 import, validate 함수 실행
2. validate 함수에 optional parameter 가 추가되어야 하는 상황. 그러나 모든 validate 에서 이를 필요로 하는 상황은 아님
3. optional param 추가를 위해 모든 validate 함수들을 다 고쳐야 하는가? 라는 의문 발생
기존에는 validate_plugin 측에서 validate를 바로 호출하는 방식이었는데, 이 경우 다음과 같은 문제가 있음.
1. 지금 처럼 optional param 이 해당 함수 측에 전달이 되어야 할 경우 한계가 있음
2. 아예 모든 plugin 들에 대해 optional param 으로 쓰지도 않을 값을 전달하거나
3. 애매하게 dict 전달로 퉁치거나
문제 해결
결론 부터 말하자면 다음과 같이 해결했다.
1. action_type 을 필요로 하는 플러그인들의 validate 만을 수정 (다른 plugin 들은 수정 안함)
2. 사용자의 입력으로부터 import_module 을 호출하는 측에서 param 전달을 제어
3. 구체적으로는, inspect.signature 를 사용해 매개변수 정보를 미리 파악해서, 정말 필요한 값만 전달하여 invoke 한다
코드를 보자 (어느정도 각색됨)
class Service:
@staticmethod
def validate_plugin(client_id: int, plugin: Plugin, data: dict) -> str:
try:
validation_func: Optional[Callable] = getattr(
import_module(f"plugins.connectors.{plugin.code}"), "validate", None
)
except ModuleNotFoundError:
raise NotImplementedDatasourceError()
action_type = data.get("action_type", "create")
action_type = ActionType(action_type)
val_key = Service._safe_validator_invoke(
validation_func,
plugin,
..., # 기존의 param 목록들
action_type=action_type,
)
return val_key
@staticmethod
def _safe_validator_invoke(func: Callable[..., R], /, *args: Any, **kwargs: Any) -> R:
signature = inspect.signature(func)
accepted = {}
for name, _ in signature.parameters.items():
if name in kwargs:
accepted[name] = kwargs[name]
return func(*args, **accepted)
이렇게 하면 validation_func 호출하는 단에서 매개변수를 안전하게 제어해서 처리할 수 있다.
결론
1.우선, import_module, getattr을 쓰는 것 자체가 안티패턴에 가까우므로 장기적으로 대체해야겠다
2. 항상 pyhton 기본 package 들의 기능을 숙지하고 적재적소에 사용할 수 있도록 한다
'연습' 카테고리의 다른 글
| IDLE한 상태에서 배운 점 (1) | 2025.11.26 |
|---|---|
| Batch 메시징 설계기 (2) | 2025.11.16 |
| Batch/Event + Messaging (0) | 2025.09.13 |
| 기술 스택 정리 (0) | 2025.02.26 |
| Python requests와 HTTP Streaming 문제 해결 (0) | 2025.02.11 |
- Total
- Today
- Yesterday
- 회고
- 이것도모르면바보
- 그리디
- SQL
- 우선순위큐
- BOJ
- 코딩테스트
- Remote
- PREFECT
- 삽질
- 힙
- Til
- vscode
- jwt
- 파이썬
- docker-compose update
- 스택
- Javascript
- SSL
- 최대한 간략화하기
- 위상정렬
- kafka쓰고싶어요
- cipher suite
- 불필요한 값 무시하기
- Python
- 프로그래머스
- requests
- django testcase
- endl을절대쓰지마
- 백준
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |