있습니다. 보라색의 Presentation Layer는 오직 context의 service만 알게되는 형태이고 갈색의 services에서 각 서비스는 Repository들을 주입받습니다. context의 services안에 있는 Repositories는 파란색의 data영역의 Repository들을 모아둔 것입니다. Repository는 core에서 interface영역을 정의하고 data에 실제 구현체 부분이 있습니다 사실 이렇게만 설명드리면, 기존 구조가 어떠한 흐름이었는지 설명드리기에 충분하지 않을 것 같습니다.
ࣻ णפ. ਃೠ ੋ ৻ࠗ ܻࣗझח Ӓ ޖب աఋա ঋणפ. ࠗ࠙ ,߸ೡ ࣻ ח ਃࣗ۽ࠗఠ ܻ࠙दఃӝ ਤೣੑפ. -FHBDZ"SDIJUFDUVSF - .. view가 부르게 되는 각 서비스는 이렇게 interface형태로 된 Repository를 주입받습니다. 이 코드를 보면 Service가 주입받는 repo는 하단에 interface형태로 된, 실제 구현체가 아닙니다. catch와 call은 사용자의 useCase, 즉 행동으로 볼 수 있고 이 단계에서는 필요한 직접적인 외부 리소스가 명시되어 있지 않습니다.
충분히 말씀드리지 못했고, 아마 이해가 잘 안되실것 같다고도 생각됩니다. 하지만 오늘 중점적으로 다룰 부분은 이 구조에 대해서가 아니라, 이사 과정에 대한 이야기 입니다. 그럼에도 불구하고, 혹시 이 구조에 대해서 더 알고싶은 분이 계시다면 위 발표자료를 참고하시면 좋을것 같습니다.
localState view helper render VIEW 마지막으로, view에 render외에 너무 많은 정보가 관리되고 있었습니다. api response, fetchState 그리고 렌더링에 필요한 local state, 데이터를 가공하기 위한 helper function등이 제대로 분리되어 있지 않았습니다.
core/service data/http/mapper data/Repository view Before After 두번째 개선은 첫번째 내용과 겹치는 부분도 있습니다. 수정사항이 생겼을 때 변경해야하는 파일의 양이 너무 많았었습니다. 구조를 간단하게하고, 역할을 명확히 함으로서 수정이 두렵지 않도록 했습니다.
역할로 사용했습니다. api호출과 관련된 처리는 미들웨어에 모두 위임하였습니다. view에서는 직접 api 호출과 관련된 로직을 관리하지 않고 오직 dispatch와 Store의 state만 바라보면 되는 구조로 변경하였습니다. Dispatch를 담당하는 곳을 한 레벨로 지정하는것까지 적용하여 각 요소의 역할을 나누었습니다.
. dispatch : dispatch ! ( : entry/view , : entry/container) ( hook react-redux 6.x) 중반까지라고 말씀드린 이유는, 끝날쯤에는 놓친부분들이 많이 보였기 때문입니다. 당시에는 react-redux 6버전을 사용하고 있었는데요, 해당 버전을 쓰신 분들이라면 아실 mapStateToProps와 mapDispatchToProps 즉 store와 connect되는 부분을 어디로 잡을지에 대한 고민이 있었습니다. 그리고, 이 고민을 썩 잘 해결하지 못했습니다. dispatch는 상태를 변화시킬 수 있으니까 가급적 한 곳에서만 이루어져야 한다고 생각했고 이 위치가 route의 바로 하위 레벨인 entry의 view폴더에서 이루어져야 한다고 생각했습니다.
. mapDispatchToProps Route View . dispatch Drilling ⚓, Component : dispatch ! ( : entry/view , : entry/container) ❓ 이렇게 생각했던 것은 끊임없는 Driling과 재사용 불가능한 Component를 만들었습니다. redux를 사용했던 목적이 Driliing해결은 아니었지만 실제 필요한 컴포넌트에게 전달되기까지 몇단계를 거치는 구조는 다소 고통스러웠습니다. 그리고 dispatch의 기준이 기본은 entry이고 필요하면 container라는 러프한 룰을 적용하다보니 더이상 기준이 아니게 되었고, props가 강제된 컴포넌트는 재사용이 불가능해졌습니다.
이전 구조에서 view와 data가 너무 심하게 바인딩 되어 있었다는 점에 포커스를 맞추다 보니 다른 부분들을 많이 놓쳤습니다. 하나의 프로젝트는 data와 view만으로 구성되지 않습니다. view, data외에도 api, util, view를 위한 helper function등이 프로젝트의 구성요소가 될 수 있습니다.
Props . interface Props { name: string; value: string; } component는 무조건 primitive 타입의 props만 가집니다. 개발자가 따로 정의한 entity를 props로 가질 수 없는 부분입니다. entity를 가지게 되면 도메인을 알게되고, 이렇게 되면 다른곳에서 재사용을 하지 못할 확률이 높아지기 때문입니다.
, Entity Type Props . interface Props { poke: Pokemon; count: number; } 예시를 들자면, 이렇게 개발자가 정의한 custom entity인 Pokemon을 props로 가질 수 있습니다. 여기 예시 코드를 보면 custom entity인 Pokemon과 primitive type인 count를 props로 가지고 있습니다.
, Entity Type Props . , dispatch + ) tmi: react-redux 7.1 도메인을 알게되는 부분이기 때문에 자연스럽게 dispatch는 컨테이너 레벨에서 이루어지게 됩니다. 그리고, eact-redux 7.1 버전의 useSelector와 useDispatch를 사용하게 되면서 코드량이 확 줄었습니다. connect와 mapdispatchToProps등을 정의할 필요가 없어져서 훨씬 간결하게 사용할 수 있으니 이 문법을 사용해보시는 것을 추천드립니다.
리듀서, 미들웨어를 정의하는데있어 비슷한 코드를 매번 적어주어야 한다는 불편함이 있었는데요, 생각해보니 redux는 잘못이 없고 제가 조금 잘못사용하고 있지 않나.. 라는 생각이 들었습니다. 오른쪽 사진이 리덕스 새집증후군을 해결하기 위한 actionUtil 함수인데요,
대해서 누구나 쉽고 간단하게 검증해볼 수 있습니다. 저희 팀에서 관리하는 대부분의 프로젝트는 api response를 이용하여 이를 가공하는 형태의 프로젝트 이기 때문이죠. 덤으로, 스캐폴딩도구도 만들 수있으니 서비스별로 저장소를 분리한 저희팀에 유용한 방식이 아닌가.. 하고 생각하고 있습니다.