코드숨 React 5기 - 6주차 회고
6주차 주간 회고
Facts
- 코드숨 6주차 과제 수행
- 레스토랑 상세 페이지 구현하기
Feelings
상세 페이지 구현 시, tdd를 하는데도 불구하고 여러 단계의 작업을 한번에 한다는 피드백을 받았다. 역시 쉽지 않다. 아직까지도 “짧은 주기로 피드백”에서 짧은 주기가 불편하고, 그림이 잘 그려지지 않는다. 왜 그런가를 생각해봤을 때, 컴포넌트에 대해서 짧은 주기에 어떤 피드백을 보고싶은지를 모르기 때문이라는 생각이 들었다. 그래서 리액트 컴포넌트에서 나는 무엇을 확인해야 하는지를 다시 되짚어 봤다.
우선 리액트의 전략은 상태 값(state)의 변화가 렌더링의 트리거가 되도록 하는 것이다. 그렇다면 리액트에서 우리가 확인해야 하는 것도 명확하다. 해당 컴포넌트에 상태 값이 주어졌을 때(input) 어떤 화면을 그리는가?(output). 좀 더 rtl(react testing library)의 접근 방식에 따라서 말하면 해당 컴포넌트에 어떤 화면 요소가 표시되어야 하는가?를 확인해야 한다.
여기서 테스트에 대해서 좀 더 생각을 해보면 테스트의 대상이 되는 함수는 결정적이고(deterministic) 부수 효과(side effect)가 없는 순수 함수이어야 한다. 같은 세팅(입력, 환경)에 대한 결과 값이 그 때 그 때 다른 함수라면, 해당 테스트가 주는 피드백은 의미가 없어지기 때문에 테스트하기 어려운 함수(비결정적이고 부수효과가 있는 함수)에 대해서는 테스트를 작성하지 않는다.(작성하지 않는다기 보다는 해당 테스트 결과를 독립적으로, 결정적으로 만들기 위해 다른 도구의 도움을 받아서 작성한다.) 이 관점에서 컴포넌트 또한 순수함수로 작성되어야 한다. 즉, 앞에서 말한 리액트가 화면을 그리는 방식을 생각해봤을 때, 해당 컴포넌트는 주어진 상태 값에 따라서 그려지는 화면 요소가 결정적이고 부수효과가 없어야 한다.
그런데 많은 경우 이런 제약이 깨진다. 컴포넌트 내부에서 상태 값을 결정하기 위한 도구로 useSelector를 사용하는 경우에는 해당 컴포넌트가 비결정적이게 되고, useEffect를 사용하는 경우에는 부수효과가 발생한다. 이런 경우 mock의 도움을 받아서 useSelctor가 반환하는 상태 값, 혹은 useEffect를 통해 제공되는 상태 값을 고정적으로 제공하는 방식으로 독립적인 컴포넌트를 구성한 후 테스트한다. 결국 테스트 하기 어려운 컴포넌트들도 mock의 도움을 받는다면 “해당 컴포넌트에 상태 값이 주어졌을 때(input), 해당 컴포넌트에 어떤 화면 요소가 표시되어야 하는가?”를 확인하는 방식으로 해당 컴포넌트가 제대로 구현되었는지에 대한 피드백을 제공받을 수 있다.
여기서 내가 한 단위의 작업의 크기가 혼동하는 지점이 발생되었다. 화면 요소를 표시하기 위해 어떤 상태 값이 제공되어야 하는지, 더 정확하게는 해당 상태 값이 어떤 방식으로 제공되어야 하는지?는 해당 컴포넌트 인터페이스 설계에 해당하는데, 이 설계는 리팩터링의 바운더리가 되기 때문에 인터페이스 설계는 테스트 이전에 결정되어야 한다. 그런데 컴포넌트를 분리하는 과정에서 컴포넌트의 설계가 변경되는 지점이 발생하고 이 과정에서 한 단위의 작업의 크기가 불분명한 지점이 있었다. 해당 지점은 컴포넌트에서 useSelector나 useEffect를 사용하여 상태 값을 제공받도록 변경하는 지점이다. 맨 처음 컴포넌트를 분리할 때는 props로 상태 값을 부모에서 받아서 그리도록 인터페이스가 설계된 컴포넌트가 상태 값을 부모에게 받지 않고 useSelector를 통해서 redux store에서 값을 받아오도록 할 때, 이 경우에는 설계가 변경되는 것이지 리팩터링이 일어나는 것이 아니다. 기존에 하나의 컴포넌트였던 부분을 redux 값을 받아오는 container와 받은 값을 그리기만 하는 component로 분리하는 과정에서, 기존에 작성된 테스트는 설계가 변경되었기 때문에 무의미한 테스트가 되어버리지만 red 피드백을 계속 보낸다. 당장 나에게 필요한 피드백은 무엇일까? 우선 무의미한 피드백을 계속해서 전달하는 기존의 테스트를 다 삭제를 하는 것이 먼저일까? 잘 모르겠다 container에 대한 테스트와 component에 대한 테스트 중에서는 무엇을 먼저 작성하는 것이 좋을까? 결국 설계의 변경으로 인해 발생한 모든 작업이 하나의 작업으로 묶여서 진행되었고 커밋되었다.
이 작업은 나에게 왜 혼동을 주는 것인가? 생각을 해보면 컴포넌트를 분리하는 과정에서 어떤 피드백을 먼저 받아야 하는가?를 혼동했던 것 같다. 맨 처음 말했던 대로 어떤 화면 요소가 표시되어야 하는가?가 가장 중요한 피드백이기 때문에 component에 대한 테스트가 먼저 작성되어야 할 것 같다. componenet가 구현된 후에 덜 중요한 피드백인 container에 대한 피드백을 받으면 될 것 같다. 앞으로는 나에게 당장 가장 중요한 피드백이 무엇일까?를 생각하고 작성 우선 순위를 정하면 될 것 같다.
위의 잡소리를 다 제거하고, 아샬님이 5기 슬랙 방에 올려주신 기사글과 동영상의 내용을 정리해보면 결국 인출을 해낼 수 있어야 한다. 휴가 기간 동안 라우팅을 나누고 페이지를 tdd로 작성하는 과정을 인출해봤는데 생각에 의존하기 보다 기억에 더 의존하게 되는 것을 발견했다. 그래도 인출의 과정을 거치는 것 자체가 의미가 있었다. 회사에서 하는 작업에서도 어떻게 적용할 수 있을까 고민인데, 대부분의 작업은 회사에서의 작업이기 때문에, 회사에서 하는 작업물을 tdd를 사용하여 더 신뢰할 수 있도록 할 수 있는 것과 동시에 더 자주 인출을 할 수 있는 장점이 있다. 단점은 회사에서의 작업들은 맥락이 다르기 때문에 내가 한 인출에 대해서 적절한 피드백을 스스로 주기가 어렵고 다른 동료에게 받기는 더 어렵다는 것. 그래서 오히려 잘못된 습관을 반복시킬 수도 있을 것 같아서 우선 코드숨에서나 잘 하고 나중에 조금씩 쉬운 작업물부터 시작을 해봐야 겠다고 생각했다.
멘토님이 피드백에서 mock할 상태 값을 지연 평가할 수 있는 given2라는 라이브러리를 소개해주셨다. 각 테스트에서 mock된 데이터가 무엇인지 더 명확하게 표현되는 것 같았다. 나도 필요한 라이브러리를 적절하게 평가하고 선택하는 능력을 잘 갖추었으면 좋겠다고 생각했다.
Findings
나에게 당장 가장 필요한 피드백이 무엇인지 생각하고 작성 우선 순위를 정해야 한다.
학습에는 인출이 중요하다. 인출을 통해 현재까지의 학습 정도를 확인하도록 하자.
필요한 라이브러리를 적절하게 평가하는 선택하는 능력의 필요성.
Affirmation
나에게 당장 가장 필요한 피드백이 무엇인지 생각하고 작성 우선 순위를 정해서 구현하기.
내가 제대로 학습했는지는 인출이 가능한지를 통해 확인해보기.(여태까지 진행되었던 내용을 다시 진행해보기)