티스토리 뷰

배경

현재 업무에서는 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
링크
«   2026/05   »
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
글 보관함