Ayden's journal

context API와 의존성 주입

생각보다 많은 사람들이 context API를 유사 전역상태관리 도구로 여기고 있고, 사실 나 역시도 처음에는 그렇게 알고 있었다. 그러나 잠깐 생각해보면 context API(이하 컨텍스트)의 존재 이유가 전역 상태 관리와는 전혀 상관이 없다는 걸 금방 알 수 있다. 아마 리액트 개발자라면 누구라도 이렇게 대답할 것이다. "컨텍스트를 사용하면 prop drilling을 방지할 수 있다."

그렇다면 어째서 대부분의 사람들 ─ 혹은 리액트 1~3년차들 ─ 은 무의식 중에 컨텍스트를 유사 전역상태관리 도구라 여기고 있는 것일까? 여기에는 크게 두 가지 이유가 있다고 본다. 하나는 컨텍스트를 활용하는 예시가 대체로 state와 setState에 치중되어있기 때문이다. 심지어는 이를 새로운 커스텀 훅으로 감싸 진정한 의미에서 유사 전역 상태 관리 도구로 사용하는 활용법을 제시하기도 한다. 이로 인해 컨텍스트는 전역 상태와 관련되어있다는 일종의 선입견이 심어지게 된다.

다른 하나는 이들이 컨텍스트를 진지하게 고려해본 적이 없기 때문이리라 생각된다. 앞서 언급한 이유로 선입견이 심어진 상태라 컨텍스트를 활용할 방법을 고민하기보다는, 더 나은 전역 상태 도구가 있으니 컨텍스트를 쓸 이유가 없다고 생각하고 넘겨버린다. 내가 만나본 개발자 백이면 아흔 여덟은 대체로 이런 상황이었다.

 

본론으로 돌아와보자. 컨텍스트를 사용하면 prop drilling을 방지할 수 있다. 이 말은 컨텍스트가 "특정 컴포넌트에 필요한 값을 prop이 아닌 방식으로 제공한다"는 의미이다. 필요한 값이란 어떤 상태(state)일 수도 있고, 특정한 문자열이나 숫자일 수도 있으며, 때로는 함수일 수도 있다. 그렇다면 어떤 값을 prop으로 제공해야하고, 어떤 값을 컨텍스트로 제공해야 할까?

나는 여기서 컨텍스트의 의의를 다시 생각해봐야 한다고 생각한다. 물론 컨텍스트를 사용하면 prop drilling을 방지할 수 있다. 그렇지만 이것이 컨텍스트가 존재하는 이유일까? 내가 생각하는 컨텍스트의 존재 이유는 이러하다. "컨텍스트를 사용하면 컴포넌트 외부에서 의존성을 주입할 수 있고, 이를 통해 컴포넌트의 재사용성을 극적으로 끌어올릴 수 있다."

 

간단한 예시를 생각해보자. 독후감 작성/수정 페이지는 똑같은 form 컴포넌트를 사용하며 제목과 본문이 필수라는 validationRule도 동일하다. 다만 독후감 작성은 1) 책의 isbn13을 조회하는 작업을 수행하고 2) 해당결과를 독후감 내용과 함께 post 메소드로 서버에 보내야 하고, 독후감 수정 페이지는 이런 작업 없이 수정된 내용만 patch로 보낸다는 점이 다르다. 요컨데 모든 것이 같지만 mutationFn 하나가 다르다는 것이다.

컨텍스트는 이럴 때 사용하는 것이다. 부모 컴포넌트가 직접 자식 컴포넌트를 제어하지 않고(제어 역전), 자식 컴포넌트는 외부에서 주입받은 mutationFn을 활용함(의존성 주입)으로써 리액트 컴포넌트의 재사용성을 높일 수 있다.

// 독후감 작성
const { mutate } = usePostReportMutation();

<ReportMutationContext.Provider value={(reqData) => { mutate(reqData) }}>
  <ReportForm />
</ReportMutationContext.Provider>

// 독후감 수정
const { mutate } = usePatchReportMutation();

<ReportMutationContext.Provider value={(reqData) => { mutate(reqData) }}>
  <ReportForm />
</ReportMutationContext.Provider>

// ReportForm 컴포넌트 내부
const mutate = useContext(ReportMutationContext);

return <form onSubmit={handleSubmit((data) => { mutate(data) })}>

 

prop은 컴포넌트와 컴포넌트 사이의 결합을 상징하지만, 컨텍스트는 큰 틀에서 완성된 모듈의 재사용성을 끌어올리는 데 집중하고 있다고 나는 생각한다. 이런 관점에서 prop과 컴포넌트를 생각해본다면 코드의 재사용성을 훨씬 더 높일 수 있을 것이다.

블로그의 정보

Ayden's journal

Beard Weard Ayden

활동하기