토스 Frontend Fundamentals 모의고사 2회차 후기
예측 가능한 코드를 배우고 내 코드 다시 보기토스분들이 코드를 바라보는 시각에 대해 배우고 싶어 이번 토스 모의고사에 참여하게 되었다.
많은 시간을 할애하고 고민해보지 못해서 아쉬움이 남지만, 모의고사 해설 방송 이후에 그 개념을 가지고 계속해서 지금 내 코드에는 어떻게 반영하면 좋을지 고민해보는 시간들이 생기는 것 같아 참여하길 잘했다는 생각이 든다.
해설 강의에서 크게 2가지를 더 깊이 생각해볼 수 있었다.
- 예측이 가능한 코드 (올바른 props 설계)
- UI와 코드의 1:1 대응
1. 예측이 불가능한 코드 — setMessage props
이 한 줄만 보면 "예약 목록" 컴포넌트가 왜 메시지를 세팅하는지 예측할 수 없다.
실제로 메시지는 리스트 위에 보이는 배너인데, 이 메시지의 출처는 예약 카드에서 취소를 성공/실패했을 때의 결과다. 처음에는 전역 상태로 관리할까 고민하다가, 일단 setMessage를 props로 넘기고 마무리했었다.
역시나 이 부분이 문제였다.
props 흐름을 따라가보면
MyReservationList는 메시지와 아무 관련이 없는데, 단지 중간 다리 역할로 setMessage를 받고 있다. 이 컴포넌트의 props 시그니처만 보면 "이 컴포넌트가 메시지를 설정한다"고 읽히지만, 실제로는 자식인 ReservationCard가 호출하는 것이다.
setState를 그대로 props로 넘기는 문제
해설 강의에서 DateSelector에 setDate를 넘기는 대신 onChange를 쓰라고 했던 것과 같은 맥락이다.
setMessage라는 이름은 부모의 내부 구현(상태 setter)을 자식에게 그대로 드러낸다. 자식 입장에서는 "나는 취소 결과를 알려줄 뿐"인데, 부모가 그걸 어떻게 처리하는지(상태에 저장하는지, 토스트로 띄우는지)까지 알 필요가 없다.
현재 메시지 배너가 리스트 바깥 위쪽에 위치하는 UI 구조를 유지하려면, 카드에서 발생한 취소 결과를 어떻게든 바깥으로 올려보내야 한다. 이를 개선하는 방향은 크게 두 가지가 있을 것 같다.
방향 1: 콜백 구조로 변경
setMessage라는 상태 setter 대신 onCancelSuccess/onCancelError라는 의미 기반 콜백으로 바꾸면, props만 보고도 "이 컴포넌트에서 취소가 일어나고, 그 결과를 알려주는구나"가 예측 가능해진다. 부모가 그 결과를 메시지 배너로 보여줄지, 다른 방식으로 처리할지는 부모의 몫이 된다.
방향 2: 전역 상태로 메시지 관리
전역 상태를 사용하면 prop drilling 자체가 사라진다. 카드는 취소 결과를 전역 store에 저장하고, 부모는 그걸 구독해서 기존 배너 UI 그대로 보여주면 된다. 메시지를 누가 만드는지 추적할 필요 없이, store만 보면 된다.
2. UI와 코드의 1:1 대응
해당 코드는 토이 프로젝트의 코드인데 어쩌면 이런 부분이 강의에서 말했던 일대일 대응이 아닐까 생각이 든다. (아닐지도 ㅎㅎ)

화면에서 보이는 순서 그대로 — 캘린더, 투두 리스트, 추천 배너 — 코드에서도 같은 순서로 컴포넌트가 나열되어 있다. 코드만 읽어도 화면이 어떻게 생겼을지 예측할 수 있고, 반대로 화면을 보고도 어떤 컴포넌트를 수정해야 할지 바로 찾을 수 있다.
돌아보며
모의고사 해설을 듣기 전에도 setMessage를 props로 넘기는 게 찝찝하긴 했다. 해설에서 예측 가능한 코드와 UI-코드 1:1 대응이라는 프레임을 배우고 나니, 그 찝찝함이 왜 찝찝했는지를 말로 설명할 수 있게 되었다.
좋은 코드 설계에 정답은 없을지라도, 내가 왜 이렇게 했는지에 대한 명확한 근거를 설명할 수 있어야 한다는 것이 중요하다는 것을 모의고사를 통해 깨닫게 되었다.
앞으로 이런 기준을 가지고 적용해보면서 3회차가 오기 전까지 더 연습을 해봐야할 것 같다.