Frontend Fundamentals 모의고사 후기

김상민·2025년 11월 25일
post-thumbnail

Frontend Fundamentals 모의고사란?

Frontend-fundamentals

Frontend Fundamentals 모의고사는 토스에서 실제로 출제되었던 과제에 참여하면서 토론하고 해설을 들을 수 있는 프로그램이다. 링크드인에서 이런 프로그램을 진행한다는 것을 보고 선착순 50명 안에 들기 위해 알람을 맞춰놓고 기다렸다.

올해 초, Frontend Fundamentals 문서를 읽고 회사에서도 개인 프로젝트에서도 어떤 코드가 더 좋을까에 대해서 많이 고민하고 개선할 수 있었다. 이번 기회로 토스에서 코드를 작성할 때 중요하게 생각하는 부분이 어떤 것인지 더 많이 배우기를 기대하며 모의고사에 참여했다.

느낀점 3줄 요약

먼저 간략하게 느낀점부터 적어보자면,
1. 과제를 풀면서 평소에 고민하던 부분들을 많이 마주할 수 있어서 좋았다.
2. 제출 후에는 다른 참여자들의 코드를 보면서 좋은 구현 아이디어도 얻어가고, 다른 분들은 어떤 걸 중요하게 생각하며 코드를 작성하는지도 엿볼 수 있었다.
3. 라이브 해설강의가 수능 모의고사 풀이 강의를 떠오르게 했는데, 무릎을 탁치게하는 깨달음도 얻고 나도 나름 Frontend-fundamentals에서 배운 점들을 잘 써먹고 있구나 싶은 자신감도 생겼다.

과제 풀어보기

처음 과제를 받았을 때, 요구사항의 기능 구현 난이도가 높지는 않아보였고 확장성을 고려한 설계와 추상화 관점에 집중해달라는 문구가 있었다.
그래서 익숙한 기술들을 사용해서 기능은 빠르게 구현하고, 설계에 고민을 많이 해보자는 마음으로 시작했다.

고민했던 부분

폼 상태 관리, 필터링 로직 가독성 고민 같은 부분도 있었지만 추상화가 주요 고민이었다.
여러 입력 필드들, 탭 전환, 리스트 등 별 생각 없이 구현하다보면 그냥 관성적으로 컴포넌트로 분리할까? 싶은 부분들이 있었다.
하지만 이번 만큼은 이유 없이 추상화 하지 않겠다고 다짐하며 고민 끝에 나름의 기준을 세울 수 있었다. 고민을 하며 세운 정말 나름의 기준이고 정답은 아니다.

  • 단순히 의미상으로 비슷한 것끼리 묶는 컴포넌트를 만들지 말자.
  • UI 라이브러리에서 제공하는 컴포넌트 가공하여 재사용 위한 컴포넌트로 만들지말자.
  • 레이아웃은 페이지에서 책임지고 하위 컴포넌트에 숨기지 말자.
  • 로직을 책임 단위로 보고 컴포넌트를 추상화 하자.

입력 필드를 form으로?

여러 입력 필드들이 있고, 이 입력 필드들은 연관된 상태를 가지기 때문에 하나의 form state로 다루는 상황이었다. 이 필드들을 form이라는 컴포넌트로 추상화할지 고민되었다. 그래서 일단 컴포넌트를 만들어보니 몇가지 문제점이 눈에 보였다.

  1. <Spacing />으로 필드사이 간격을 조정하고 있었는데, 하나의 form으로 묶어보니 페이지 컴포넌트에서 레이아웃이 전혀 보이지 않았다.
  2. 그리고 formContext로 상태를 주입받다보니 props도 없어서 정말 어떤 역할을 하는 컴포넌트인지 전혀 알 수 없었다.
  3. form 안에 여러 필드 입력을 위한 로직들이 전부 혼재한다.

이 3가지 문제점을 보고 필드별로 추상화하기로 결정했다.
여기서 추상화를 안 할순 없었냐하면, 그럴수도 있었지만 입력 필드 로직, 스타일 등이 모두 페이지 컴포넌트에 존재했기 때문에 이 입력 필드 하나만을 위한 코드들은 숨기는게 좋다고 생각해서 추상화는 꼭 필요하다고 생각했다.

탭 전환 기능을 공통화?

탭 전환을 위한 UI 컴포넌트를 탭 내용을 렌더링 하는 기능까지 갖춘 컴포넌트로 추상화할지가 다음 고민이었다.
하지만 이를 추상화 해서 얻는 점은 탭 렌더링 로직을 숨긴다 정도인데 탭 UI는 있으니 상태만 관리하고 조건부 렌더링을 하면 되는 건데 이걸 숨겨야할까? 싶었다.
그리고 UI 컴포넌트의 인터페이스를 변경하지 않고 최대한 활용하는게 일관성 있게 쓸 수 있을 거라 생각하여 페이지 컴포넌트에 탭 렌더링 로직을 드러냈다.

토론

제가 올린 PR에도 언제든 편하게 의견 주시면 좋아요~

모든 분의 PR을 다 보고 싶었지만 게으름 이슈로 다 보지는 못했다.
점심시간에 잠깐 짬을 내서 코드 리뷰도 달아보고 여러 아이디어를 얻어보았다.
기억에 남는 아이디어는 nummeric input을 다루는 hook을 통해 포메팅과 상태 로직을 추상화 한 것이었는데, 그냥 util로 만들어서 상태 변경 때마다 포메팅 하는 것보다 훨씬 좋다고 생각했다.

그리고 "단일 책임" 경계에 대한 discussion도 아주 재미있었다.

해설을 듣고 난 뒤

라이브코딩으로 진행해주신 해설을 통해 요구사항을 분석하고 접근하는 법부터 설계의 관점을 배울 수 있었다.
해설을 통해 배운점, 잘 해왔던 점을 정리해본다.

배운점

  • 추출과 추상화는 다르다. (좋은 코드란?)
  • 요구사항을 보고 인터페이스 위주로 pseudo code를 작성하면 구현하며 흐름을 잃지 않을 수 있다.
  • UI가 드러나게 페이지 컴포넌트를 구성하다보면 추상화할 것과 아닌 것이 명확하게 드러난다.
  • Suspense fallback에 들어가는 컴포넌트를 합성 컴포넌트로 만들어서 의존성이 드러나게 할 수도 있다.
  • 추상화를 할 때에는 엣지케이스를 내부에서 처리하고 내부 컴포넌트의 인터페이스를 유지하자.
  • 책임 단위로 추상화를 하면 재사용성은 따라온다.
  • 컴포넌트 인터페이스를 설계할 때 일반적인 props를 사용하자.
  • useState는 구현의 영역이다. 이것만으로 추상화할 가치가 있다. useState가 아닌 다른 방식으로 구현하게 될 수도 있으니.
// 이렇게 단순한 상태만 관리하는 훅이지만 
// 이 내부 구현이 전역 상태가 될지, storage를 사용할지, reducer를 사용할지, setQueryState를 사용할지 등
// 구현 방식의 선택사항일 뿐, 단순하니 추상화할 가치가 없다고 생각하지말자. 
function useView(...) {
  const [view, setView] = useState<"view1" | "view2>(...)
  
  return [view, setView] as const
}

잘한점

  • 페이지 컴포넌트에서 UI가 드러나게끔 추상화를 했다. 해설을 통해 기준을 더 명확하게 할 수 있었다.
  • 대부분의 컴포넌트 인터페이스에서 의도가 드러나게 해서 사용하는 곳에서 예측이 되도록 했다. 이건 좀 더 연습이 필요하다.

끝으로..

오늘을 계기로 코드를 보는 시각이 달라질 것 같다. 많은 고민과 연습이 필요하겠지만 좋은 코드의 기준들이 체화되도록 노력해야겠다.

좋은 시간 만들어주신 토스 프론트엔드 개발자 분들께 감사드립니다!

profile
성장하는 웹 프론트엔드 개발자 입니다.

0개의 댓글