아래 글에 포함하려다 따로 떼내어 적습니다.
https://itchallenger.tistory.com/771
리액트의 모든 컴포넌트 인터페이스는 다음과 같이 추상화 할 수 있습니다.
<T=any>(props:React.ChildrenWithProps<T>)=>React.ReactNode
하지만 보통 구체적인 구현체인 평션 컴포넌트를 임포트해서 리턴값에서 사용하죠.
nest.js나 스프링의 경우 인터페이스 <-> 구체 클래스 매핑 정보를 리플렉션(애노테이션, 데코레이터)을 통해 IOC 컨테이너가 알고 있습니다.
리액트는 IOC 컨테이너가 없으니 컨텍스트 API가 없으면 인터페이스 기반으로만 프로그래밍 할 수 없죠.
그렇다면 리액트는 어떻게 구현체(Impl)를 바꿔가며 테스트할까요?
사실 함수가 순수하다면 DI를 굳이 사용할 필요가 없습니다.
컨트롤러의 인터페이스를 굳이 안만드는 것과 비슷하죠
하지만 부수효과를 포함한 순수하지 않은 컴포넌트의 경우 DI를 해주는 것이 좋습니다.
이를 위한 도구가 컨테이너 컴포넌트 + Context API 입니다.
컨테이너 컴포넌트는 프롭으로 주입받는 대신,
내부에서 하위 프레젠테이션 컴포넌트를 위한 의존성을 처리하는 역할을 합니다.
즉, 프리젠테이셔널 컴포넌트에 데이터와 콜백을 제공하는 역할을 수행하죠.
(데이터 + 메서드 = 뷰모델?)
(리액트-리덕스도 안정적인 참조를 컨텍스트 API를 통해 전달합니다.)
프리젠테이셔널 컴포넌트는 렌더링 로직과 스타일을 처리합니다.
즉 관심사의 분리가 잘 일어난거죠.
물론 요새는 두 개를 분리할 필요가 없다는 분들도 많습니다만,
이에 대한 내용을 아주 잘 설명하는 영상이 있으니, 참고하시기 바랍니다.
(제목 : 주객전도 아키텍처 / 프로그래밍)
https://www.youtube.com/watch?v=TW4cOAmRTFY
개인적으로 저는 컨테이너 / 프리젠테이셔널 컴포넌트는 유닛 테스트를 위한 아키텍처를 넘어,
렌더링, 스타일, 마크업 구조와 데이터, 콜백 인터페이스의 관심사의 분리를 위해 반드시 필요하다 생각합니다.
그래서 어떻게 구현하나요?
위 영상을 보고오셨셨다면...
1. 저는 컨테이너, 프리젠테이셔널 컴포넌트 분리가 필요 없다 생각해요
아래 링크를 참조하시면 됩니다.
친절하게 위 영상의 핵심을 정리해드리자면,
꼭 유닛 테스트를 위해 설정을 바꾸는게, 자바 엔지니어들의 주장처럼 DI를 통해서만 이루어질 필요가 없다는 것입니다.
이는 때때로 불필요한 추상화와 인터페이스를 도입합니다.
런타임은 런타임이고, 테스트는 런타임의 문제를 해결하기 위한 수단입니다.
테스트가 런타임 아키텍처에 영향을 준다면 주객전도 입니다.
https://kentcdodds.com/blog/stop-mocking-fetch
참고로 위 방법은 아래 2번 방법을 쓰지 않을 것이라면, 컨테이너, 프리젠테이셔널 컴포넌트 패턴에서도 그대로 쓸 수 있습니다.
2. 저는 컨테이너, 프리젠테이셔널 컴포넌트 구조로 짜고 싶고, 프레임워크, 라이브러리없이 유닛테스트 하고 싶어요!
아래 링크를 참조하시면 됩니다.
부수효과를 포함한 컨테이너 컴포넌트 자체의 구현을 바꿔 테스트 하는 방식입니다.
https://itchallenger.tistory.com/716
2.1 컨테이너 컴포넌트 구조 잘 만드는 방법 알려주세요.
아래 예제를 참고하시면 됩니다.
2.2 프리젠테이셔널 컴포넌트 구조 잘 만드는 방법 알려주세요.
이는 다음 글의 주제가 될 것 같습니다.
참고
https://wit.nts-corp.com/2021/08/11/6461
'FrontEnd' 카테고리의 다른 글
[Remix] 풀 스택 컴포넌트(Full Stack Components) (0) | 2022.11.03 |
---|---|
Critical Rendering Path 최적화하기 (0) | 2022.10.31 |
소프트웨어 엔지니어링 관점에서 바라본 CSS-in-js vs Tailwind CSS (0) | 2022.10.29 |
CSR 성능 최적화를 위한 PRPL 패턴 with React (0) | 2022.10.29 |
개발자 관점에서 Next13 간단히 살펴보기 (6) | 2022.10.28 |