EziLog

카카오테크캠퍼스 3기 2단계 회고

홈으로 돌아가기

지금의 나를 만든 경험 중 하나는 카카오테크캠퍼스였다.
카테캠 3기를 진행하며 노션에 남겨두었던 회고를 정리하며, 당시 어떤 배움을 얻었는지 블로그에 기록으로 남기려 한다.

2단계는 정말 소중한 시간이었는데 커리큘럼과 멘토진분들이 엄청 대단해서 그저 시키는것만 잘했을 뿐인데 하루의 반은 코딩으로 보냈던것 같다. 실력을 키워준 핵심 4가지는 아래와 같다.

  • 멘토님들의 4단계 코드 리뷰
  • FE강사님의 실시간 라이브 강의
  • 멘토님의 팀 단위 기술 멘토링
  • 카테캠 2기 과정도 포함한 특강들

글이 길어서 내용을 한 문장씩 압축해 보았다.

  • Mission 1

    카테캠에 들어온 이유를 다시 깨닫게 되었고, AI보단 내 생각을 담은 코드를 만들고 내 생각을 정리해두는 습관을 얻게 되었다. Atomic Design Pattern을 접했고, 컴포넌트 설계할 때 이를 사용해 보려고 노력했다.

  • Mission 2

    실무적인 능력과 디테일한 부분에 대한 실력이 크게 상승했다. 기존 코드를 Atomic하게 migration했고, 디테일에 신경을 쓰게 되었으며 FSD와 리팩토링에 대한 부분에 눈을 뜨게 된 기간이다.

  • Mission 3

    Git에 대한 개념을 잡고, 멘토님께 코드의 이유를 설명드리며 내 코드를 설명할 수 있는 수준이 된 시기였다. 전체 구조를 FSD아키텍처로 migration한 기간이기도 하다.

  • Mission 4

    프로젝트를 정돈하는 시기였다. 로직과 UI를 분리하고, 성능을 최적화하고, 로딩과 에러의 범위를 고민하고 테스트 코드의 시나리오를 고민하는 등의 시간을 보냈다. 멘토님께서 나의 생각을 많이 물어봐 주셔서 좋았다.


2단계 클론 코딩에 대한 다짐

카테캠 2단계 난이도?

사실 이번 카카오 선물하기 클론 코딩을 진행하며, 기능 구현 자체가 크게 어렵다고 느껴지지는 않았다.
카테캠에 참여하기 전부터 프론트엔드 개발자의 길을 걷고 있었고, React, Next.js, TypeScript를 활용한 개인 프로젝트와 팀 프로젝트를 이미 여러 차례 경험해 보았기 때문이다.

하지만 이번 2단계는 단순히 “구현 난이도”라는 기준으로 평가할 수 있는 과정은 아니었다.
기능을 만들어 내는 것보다, 어떻게 구현해야 하는지에 대한 기준을 다시 세우는 과정에 더 가까웠다고 생각한다.

클론 코딩 자체는 비교적 수월하게 진행할 수 있었지만, 멘토님의 코드 리뷰와 팀 단위 기술 멘토링을 통해 오히려 내가 그동안 놓치고 있던 부분들을 명확하게 마주하게 되었다.
특히 코드의 가독성, 유지보수성, 그리고 설계 방식에 대해 깊이 고민하게 된 것이 이번 과정에서 가장 큰 어려움이자 배움이었다.

나는 AI를 단순히 보조도구로써 이용하고 싶었다.

카카오테크캠퍼스에 지원한 이유는 크게 두 가지였고, 이번 2단계를 통해 그중 하나에 대한 방향을 잡을 수 있었다.

나는 그동안 여러 개인 프로젝트와 서비스를 구축해 왔다. 하지만 돌아보면 프로젝트의 상당 부분을 AI에 의존하며 개발했던 경험이 많았다. 가독성이나 구조 설계보다는 빠르게 동작하는 결과물에 집중했고, 코드의 대부분을 AI 도움으로 작성했던 적도 있었다. 이것이 카테캠에 지원한 첫 번째 이유였다.

나는 AI 활용에 익숙한 편이다. 새로운 AI Agent나 기술 트렌드를 빠르게 접하고, AWS, Vercel, Cloudflare, Supabase, Firebase, GCP 등 다양한 클라우드 환경에서 서비스를 구축해 본 경험도 있었다. 덕분에 원하는 결과를 얻기 위한 프롬프트 작성이나 아키텍처 이해도는 어느 정도 갖추고 있었다.

그래서 겉으로 보이는 UI와 기능을 구현하는 데에는 큰 어려움이 없었다.
하지만 AI에 의존적인 개발에는 분명한 한계가 있었다.

AI를 사용하다 보니 사소한 작업까지 의존하게 되었고, 과도한 방어 코드가 늘어나며 코드 구조를 스스로 판단하기 어려워졌다. 또한 빠른 구현에 집중하면서 유지보수성과 가독성을 놓치게 되었고, CSS 중복이나 비효율적인 컴포넌트 구조 문제도 자주 발생했다.

무엇보다 가장 큰 문제는 성장의 정체감이었다.
완성된 서비스를 만들었다는 성취감과 달리, 구현 과정을 스스로 완전히 이해하지 못한다는 느낌이 반복되며 번아웃을 경험하기도 했다.

그래서 나는 AI에게 개발을 맡기는 개발자가 아니라,
내 설계를 기반으로 직접 구현하고 AI를 보조 도구로 활용하는 개발자가 되고 싶었다.

이 목표가 카카오테크캠퍼스에 지원하게 된 가장 큰 이유였고, 2단계 과정은 그 방향성을 다시 정립할 수 있었던 의미 있는 시간이었다.

 

2. Mission1 부터 Mission 4까지의 모든 과정

post8-1-step2-curriculum.png

 

1. Mission 1 - 홈과 로그인

미션 1은 카카오테크 캠퍼스 2단계가 시작되는 첫 주였다. 그리고 솔직히 말하면, 나는 여전히 AI에 크게 의존하고 있는 상태였다. 나의 생각이 충분히 반영된 코드를 작성하기보다는, 과제 해결 그 자체에 집중하며 구현 과정의 대부분을 AI에게 맡겨버렸다.

물론 과제 예시 페이지의 폰트 크기, 색상, 데이터 흐름 등은 최대한 동일하게 구현하려고 노력했다.

“컴포넌트를 어떻게 분리할까?”라는 세부적인 고민보다는, 먼저 홈페이지를 5개의 섹션으로 나누어 구현하겠다는 큰 틀만 잡았다. 이후 실제 구현 단계에서는 AI가 대부분의 코드를 작성했고, 스타일과 레이아웃 역시 과제 예시 페이지를 개발자 모드로 하나하나 확인해가며 AI의 도움을 받아 완성했다. 그렇게 과제는 가장 먼저 제출할 수 있었다.

리뷰를 기다리며 다른 수강생들의 결과물도 살펴보았다. 프론트엔드 개발자는 디자이너와의 협업이 필요하고, 웹페이지의 유저 플로우와 디자인 레이아웃을 단순히 “비슷하게”가 아니라, 가능한 한 1px의 오차도 없이 구현해내는 것이 중요하다고 생각한다. 모두를 확인해보지는 못했지만, 전체 페이지를 이 정도 수준으로 완성한 사례는 많지 않아 보였고, 그 덕분에 나름의 뿌듯함을 느낄 수 있었다. 동시에 멘토님이 어떤 피드백을 남겨주실지에 대한 기대와 긴장감도 함께 커져갔다.

아래 이미지처럼, 페이지는 총 5개의 섹션으로 구분해 구현해둔 상태였다. 지금 다시 보아도 예시 페이지와 차이를 느끼기 어려울 정도로 구현했다고 생각한다.

post8-2-mission1-homepage.png

다음날 멘토님의 리뷰를 들었다. 사실 이번 2단계에서 가장 기억에 남는 리뷰지 않았나 싶다.

post8-3-mission1-code-review.png

나의 단점을 관통하는 멘토님의 통찰에 감탄을 했었던것 같다. 어떻게 이렇게 잘 아시지? 라는 생각이 들정도로 뼈를 맞은 기분이 들었다. 사실 멘토님의 이 리뷰가 아니었다면 나는 카테캠이 끝날때까지 내 생각이 아닌 AI의 생각으로 코드를 작성하게 되었을지도 모르겠다.

이때부터! 나는 정신차리고 AI를 사용하지 않고, 나의 생각을 반영한 코드를 짜야겠다는 생각이 들었다.

나는 나의 생각을 코드에 담기 시작했고, 물론 아직까진 AI의 도움을 좀 받았었다. 그 생각을 TIL에 정리하기 시작했다. 기존의 지저분한 코드를 리팩토링하고, 새로운 컴포넌트를 만들때는 가독성 좋은 코드를 만드려고 많은 노력을 했다. 또, 질문을 아끼지 않았다. 궁금한 실무나 코드분리같은 질문도 계속 드렸던것 같다.

post8-4-mission1-code-review-atomic-design-pattern.png

두번째로 중요한 분기점이었던 것 같은데, 멘토님께서 Atomic Design Pattern을 알려주셔서 이에 대해 공부해보고, 정말 컴포넌트를 설계할때 좋은 디자인패턴이라고 생각했다. 그렇게 나는 공식문서부터 다른사람의 블로그글, 또 카카오 테크 블로그의 글을 보며 이 디자인패턴을 어떻게 사용해야 좋을지 등을 연구했었다.

Mission1의 step3를 구현하며 바로 이 Atomic design pattern을 적용해보았다.

post8-5-mission1-loginform-atomic-design-pattern.png

Mission 1에서 얻은 가장 큰 교훈은 단순히 과제를 완성하는 것이 아니라, 나의 생각이 반영된 코드, 가독성이 좋은 코드, 그리고 코드 설계 관점에서의 접근이 중요하다는 점이었다. 그 과정에서 Atomic Design Pattern이라는 디자인 패턴을 새롭게 학습할 수 있었다.

또한 멘토님이 남겨주시는 코드 리뷰를 단순한 피드백이 아닌, 반드시 공부하고 반영해야 할 성장의 기회로 받아들이게 되었다. 하나의 멘트도 놓치지 않겠다는 마음으로 리뷰를 꼼꼼히 살펴보았고, 그 흐름은 자연스럽게 다른 수강생들이 받은 멘토님들의 코드 리뷰까지 찾아보게 만드는 계기가 되었다.

결과적으로 Mission 1은, 코드를 작성하는 태도와 학습하는 방향성을 다시 정리해 주는 하나의 길잡이 같은 미션이었다.

 

2. Mission 2 - 주문 폼

미션 2의 멘토님께 한가지 죄송스러운 부분은 내 의욕이 너무 불타던 시기여서 너무 번거롭게 해드린것 같은 생각이 들었던 것이다.

  • 기존 컴포넌트들을 Atomic Design Pattern으로 리팩토링하던 시기
  • 구현에 대한 생각과 질문을 PR본문이나 TIL까지 드리며 내 생각을 전달 드렸다.

다행히도 미션2 멘토님은 오히려 이런 수강생을 좋아해주셔서 정말 잘 만났다고 생각했던것 같다. 설마 속마음은 얘 너무 귀찮은데? 라고 하신건 아니겠지?

우선 미션2는 시작하자마자 기분이 너무 좋았다. 기본적으로 멘토님들에 대해 파악하고 있으면 좋겠다 싶어서 멘토님들의 github계정이나 다른 수강생들의 리뷰를 확인하며 파악했었다. 예를들면 어떤 멘토님은 리뷰를 바로바로 해주시고, 어떤 멘토님이 중요하게 생각하시는 부분은 시간을 가장 잘 지키는사람인 것 같고, 또 다른분은 본인의 생각을 중요시하셔서 생각을 들려주는것을 좋아하시는 경우 등이 있었다.

나는 이런 사전조사? 를 통해 몇몇 코드리뷰를 받아보고 싶은 멘토님들이 있었는데 Mission2의 멘토님이 그중 한분이셨다.

step1을 준비하며 가장 먼저 든 생각은 이 수강생은 어떤 생각을 갖고 코드를 만드는지와 지금까지의 코드에 대한 설계 이유 등에 대해 알려드리고 싶었다. 그래서 PR본문에 설명을 많이 썼고, TIL도 같이 보내드렸다.

post8-6-mission2-first-pull-request.png

PR본문의 내용이 좀 짤렸는데, 전 단계에서 생각했던 부분들을 모두 보내드렸던것 같다. 먼저 필수에 대한 구현을 처음 커밋 4개로 나누고, 리팩토링해본 부분을 뒤의 커밋으로 나누었다. 그리고 나의 생각을 코드에 담으면서 질문들도 저절로 생기게 된 것 같다. 그래서 고민했던 부분에 대한 질문과 내 생각의 흐름을 보여드릴 수 있는 TIL을 함께 보내드렸다.

post8-7-mission2-first-pull-request-response.png

멘토님의 리뷰가 도착했다. 질문에 대한 답변도 매우 꼼꼼하게 해주셨고, 내가 작성한 PR이 가장 정성스러웠다는 말씀도 남겨주셨다. 그 리뷰를 통해 나는 두 가지 중요한 인사이트를 얻을 수 있었다.

첫 번째는 디자인 패턴은 말 그대로 ‘패턴’일 뿐, 반드시 지켜야 하는 정책처럼 받아들일 필요는 없다는 점이었다.
두 번째는 FSD(Feature-Sliced Design)라는 새로운 아키텍처를 소개받았다는 것이다.

사실 FSD 아키텍처는 이미 다른 수강생들의 코드 리뷰를 살펴보면서 한 번 눈여겨봤던 구조였다. 또, 다른 멘토님들의 리뷰 중에서 Atomic Design Pattern과 FSD를 함께 사용하고 있다는 내용을 본 기억도 있었다. 그때부터 나 역시 두 구조를 함께 활용해보고 싶다는 생각을 하게 되었던 것 같다.

Step 2는 나에게 정말 중요한 분기점이었다. 기존에 나는 모든 컴포넌트를 src/components 경로 아래에 정리 없이 모아두는 방식으로 작업하고 있었다. 이후 Atomic Design Pattern을 학습하면서, 미션이 진행될 때마다 새로 작성하는 컴포넌트들을 해당 패턴에 맞추어 작성하기 시작했다. 하지만 결과적으로 디자인 패턴을 도입했음에도 불구하고, 기존 구조와 섞이면서 폴더 구조는 오히려 더 복잡해졌고, 컴포넌트 분리 기준 또한 점점 모호해지는 문제를 겪게 되었다.

그 과정에서 나는 하나의 결론에 도달했다. “부분적으로 패턴을 적용하는 것이 아니라, 전체 구조를 Atomic하게 재정비해야 한다.” 

그렇게 나는 전체 구조를 다시 설계하기 위한 마이그레이션을 시작하게 되었다.

  • Atomic하게 프로젝트 Migration

post8-8-mission2-atomic-desgin-pattern-migration.png

보통 무언갈 생각할땐 화이트보드에 그려가며 생각하는 편이다. 원하는 구조를 잡고, 생각을 그린다고 생각하면 생각의 흐름이 자연스러웠기 때문에 좋은것 같다.

왜 Atomic을 선택했을까?

  1. 우선 Mission1때 멘토님께 받았던 리뷰의 영향이 컸고, 그 이후로 나는 컴포넌트를 설계할때 Atomic패턴을 적용해가며 설계해서 습관이 되었던것 같다.
  2. 이제와서 말할 수 있지만, step2까지는 기능에 대한 구현이 크지않았고, 예를들면 api사용도 없고, react hook form, Tanstack-Query처럼 고도화된 라이브러리를 쓸 일도 없고, 그냥 과제 예시 페이지의 디자인을 만들어가며 컴포넌트를 어떻게 설계하는지를 알아가는 과정이라고 생각했고, 따라서 기능을 분리하는 FSD보단 컴포넌트 설계에 특화된 Atomic Design Pattern을 선택하게 되었다.
  3. FSD는 아직 적용하기엔 학습곡선이 있다고 생각해서 당장 반영시키기엔 어려움이 있었다.

최종적으로 아래 처럼 리팩토링해서 멘토님께 리뷰를 부탁드렸다.

post8-9-mission2-atomic-design-pattern-structure.png

사실 Mission 2는 다른 미션들보다 수행 기간이 두 배 정도로 길었고, 그만큼 구현해야 할 기능들도 훨씬 많았다. Mission 1에서 크게 깨닫는 경험을 하며 정신이 얼얼할 정도로 많은 것을 배웠는데, 그 흐름이 이어지면서 가장 큰 성장을 체감했던 시점은 Mission 2였던 것 같다. 특히 멘토님께서 정말 세심하고 깊이 있는 코드 리뷰를 남겨주셔서 더욱 의미 있는 시간이 되었다.

멘토님께서는 단순히 코드의 정답 여부를 넘어, 실제 현업에서는 어떤 방식으로 문제를 해결하는지, 그리고 성능 최적화와 같은 디테일한 부분까지 함께 설명해 주셨다. 덕분에 단순 구현 능력을 넘어, 코드의 완성도를 높이는 사고 방식을 배울 수 있었던 것 같다.

코드 리뷰의 양도 상당히 많았는데, 멘토님께도 직접 말씀드렸지만 배우는 입장에서 받는 코드 리뷰는 그 자체로 매우 값진 경험이었다. 멘토님께서는 수강생들의 일정 부담을 고려해 일부 리뷰는 의도적으로 생략하기도 한다고 말씀해 주셨지만, 나는 오히려 가능한 한 많은 내용을 공유해 주시고 함께 이야기 나눌 수 있으면 좋겠다고 말씀드렸다.

post8-10-mission2-many-code-review.png
post8-11-mission2-many-pull-request-response.png

사실 step2까지는 멘토님의 모든 코드 리뷰에 답글을 달진 않고, 질문주신 부분에만 답글을 달았었다. 근데도 저 많은 댓글 수는 멘토님께서 정말 세심한 부분까지 터치해주셔서 생긴 숫자들이다. 현업으로 바쁘실텐데도 함께 코드를 이야기해볼 기회가 있어서 감사했다.

Mission2에선 무엇을 얻으셨나요?

  • Atomic design Pattern을 전체 프로젝트에 적용시키며 리뷰까지 받아볼 수 있었다.
  • FSD 아키텍처에 대해 생각해보게 되었다.
  • 현업에서의 코드스타일과 디테일적인 부분들을 생각해보게 되었다.

 

3. Mission 3 상품 목록 구현

Mission 3는 지금까지 진행했던 미션들 중에서 가장 작업량이 적었던 미션이었다. 그래서인지 기간도 가장 짧았고, 과제 역시 비교적 빠르게 마무리할 수 있었다. 덕분에 그동안 시도해보고 싶었던 여러 가지 개선 작업들을 직접 시도해볼 수 있는 여유가 생겼다.

개선하고 싶었던 점 (AS-IS)

  • 미션이 진행될수록 컴포넌트 수가 점점 많아졌고, Atomic Design Pattern 기반의 계층 구조는 유지되고 있었지만 관심사의 분리는 충분하지 못했다. 그 과정에서 “이 코드가 왜 여기 위치해 있을까?”라는 의문이 들기 시작했다.

  • 컴포넌트뿐만 아니라 특정 컴포넌트 전용으로 만든 커스텀 훅들 또한 모두 src/hooks 경로에 모여 있어 구조적인 한계를 느꼈다.

  • 미션 리뷰를 기다리는 동안 시간을 효율적으로 활용하고 싶었고, 제출 기한을 넘길 경우 과정에서 탈락할 수도 있었기 때문에 미리 다음 작업을 진행하고 싶었다. 하지만 Git에 대한 이해도가 부족해 작업 전략을 세우는 데 어려움을 겪었다.

어떻게 개선해보고자 했나 (TO-BE)

  • 컴포넌트 설계는 기존처럼 Atomic Design Pattern을 유지하되, 프로젝트 전체 아키텍처를 FSD(Feature-Sliced Design) 구조로 마이그레이션해보자는 목표를 세웠다.

  • Git의 rebase, cherry-pick, merge 개념을 제대로 학습하고, 실제 프로젝트 상황에서 활용할 수 있도록 충분히 실습해보자는 계획도 세웠다.

이번 미션을 진행하면서 한 가지 크게 깨달은 점이 있었다.
“아무리 결과물이 좋아도, 기한을 넘긴다면 그 결과물은 의미가 있을까?”라는 질문이었다.

앞서 언급했듯이 이번 미션 자체의 구현 난이도는 높지 않았다. 특히 Infinite Scroll 기능이 주요 구현 요소였는데, 나는 이미 개인 블로그를 개발하면서 Pagination과 Infinite Scroll을 모두 구현해본 경험이 있었기 때문에 과제 자체는 크게 어렵지 않았다.

그럼에도 이런 생각을 하게 된 이유는, 이번 주를 리팩토링과 Git 학습에 집중하는 기간으로 설정했기 때문이다. 하지만 리팩토링과 Git rebase를 진행하는 과정에서 예상보다 많은 오류가 발생했고, 결국 제출 마감 시간을 몇 분 넘기게 되는 상황이 발생했다.

그 경험을 통해 내 안에 하나의 기준이 생겼다.
“6:00과 6:01은 완전히 다른 시간이다.”

 

1. Git 학습기

번 과정에서 내가 맡은 작업 방식은 다음과 같았다.

  • 이전 Step에 대한 리뷰를 기다리는 동안 다음 Step 작업을 진행한다.

  • 이전 Step이 Merge되면, 그 결과물을 현재 작업 브랜치로 Rebase한다.

  • 이후 내가 작업한 내용도 다시 Rebase하여 최신 상태를 유지한다.

하지만 실제 작업에서는 예상하지 못한 문제가 발생했다.

예를 들어 Step 1을 PR로 제출한 상태에서, 멘토님이 수정 요청을 주신다면 나는 Step 1 브랜치로 돌아가 해당 내용을 수정해야 한다. 이 경우, Step 2를 임시 브랜치(step2-temp)에서 작업하고 있었다면, 이후 실제 Step 2 브랜치에 작업 내용을 Rebase할 때 충돌이 발생할 가능성이 매우 높았다.

이 문제를 해결하기 위해 다양한 방법을 고민했고, Rebase 연습을 겸해 여러 전략을 시도해 보았다.

  • step2-temp 브랜치를 기준으로 Rebase 진행

  • cherry-pick을 활용해 필요한 커밋만 선별적으로 적용

  • 다소 극단적인 방법이지만, step2 브랜치를 새로 생성한 뒤 step2-temp의 커밋 로그를 참고하여 수동으로 작업 내용을 재구성하는 방식

결과적으로 문제 해결에는 성공했지만, 과정이 예상보다 복잡했고 최적의 전략인지에 대한 확신은 들지 않았다. 그래서 멘토님께 내가 시도했던 방법과 학습 기록을 공유하며, 실무에서는 어떤 접근 방식이 가장 적절한지 조언을 구하게 되었다.

post8-12-mission3-mento-response-about-git.png

역시 멘토님의 생각은 cherry-pick이 가장 좋다고 생각하셨던 것 같다. 개인적인 욕심으로 Git에 대한 공부를 끼워서 질문드렸는데, 미션과 관련은 없어도 친절히 답변해주셔서 좋았다. 협업에 대해서도 여쭤봤었는데 그부분도 잘 알려주셔서 좋았고, 미션과 다른 부분이어도 다른 기술스텍을 알려주시고 공부해볼 부분을 알려주신점도 성장에 큰 도움이 되었다.

post8-13-mission3-question-and-response.png

step1에서 충돌이 있어서 재요청을 받은 경험이 있는데 오히려 그 경험이 나의 git활용 능력에 있어서 도움이 되었던 것 같다. 미션2 역시 좋은 멘토님과 코드에 대해 이야기 할 수 있어서 좋았다.

 

2. FSD아키텍처로 마이그레이션

FSD아키텍처로 구조를 갈아엎으며 정말 많은 공부를 할 수 있었다. FSD에 대한 내 작성 글만 해도 7개는 넘지 않을까?

구현하며 했던 생각들은?

  • 다른사람들은 domain(entities)와 features가 혼동이 있다는데 개인적으론 features와 widget의 경계가 헷갈렸다.
  • FSD 아키텍처의 가장 큰 장점은 명확한 계층 구조를 통해 관심사를 기능 단위로 분리할 수 있다는 점이라고 느꼈다.
  • 새로운 기능이나 컴포넌트를 추가할때, 위치와 분리에 대한 고민을 크게 덜어줄 정도로 잘 설계되었다.
  • widget이라는 layer가 굳이 필요한가? 라는 생각이 들었다.
  • 파일을 위치시킬때 오히려 정반대편에 있는 app과 shared를 비교할때가 많았다.
  • FSD는 강력한 아키텍처 가이드를 제공하지만 각 레이어의 활용 방식은 프로젝트 규모와 팀 컨벤션에 따라 유연하게 해석될 필요가 있다고 느꼈다.

 

4. Mission 4 상품 상세 구현

미션 4에서는 컴포넌트의 유틸함수를 만들듯이, 프로젝트 전체의 유틸을 생각해보는 기간이었다. api함수를 사용하면서 비동기 작업을 처리하게 되는데 이때 Suspense(로딩 상태)와 ErrorBoundary(에러 처리)를 만들게 되었다. 또, 내 프로젝트가 잘 동작하는지 테스트 코드를 작성해보는 시간이 있었고, 배포에 대해서도 공부하게 되었다.

특히 좋았던 부분이 최적화에 대해 다루는 부분이어서 내 생각을 담을 부분이 많아질 수 있었다.

  • Suspense와 ErrorBoundary를 감싸는 범위를 어떻게 설정할까?
  • API 최적화를 어떻게 시키는게 좋을까?
  • 어떤 테스트를 하고, 어떤 컴포넌트를 테스트하는게 좋을까?
  • 프로젝트를 마무리하며 리팩토링은 어떻게 하는게 좋을까?

우선 Suspense와 ErrorBoundary를 감싸는 부분에 있어서 FE강사님과 생각이 어느정도 비슷해서 놀랐다. 구현할때 ThemeField(선물테마) 부분은 터져도 랜더링안하는 쪽으로 설계하고, ProductRanking(상품랭킹)은 너무 큰 영역을 차지하고있고, 홈페이지의 핵심이라고 생각해서 이 부분이 터지면 페이지에 에러를 띄우도록 설계했었는데, 강의에서 이부분을 언급하셔서 깜짝 놀랐다.

API 최적화

어떻게 하면 UX를 향상시키면서, 동시에 DX도 향상 시킬 수 있을까?
이번 Step 2에서 가장 먼저 고민했던 질문이었다.

그리고 이 질문에 대한 답을 찾기 위해 어떤 과정을 거쳤는지 또한 TIL에서 자세히 정리하고 멘토님께도 공유드렸다.

우선 문제 상황부터 확인해 보았다.

post8-16-mission4-api-analysis.png

과제 예시 페이지에서 상품 상세 페이지에 진입했을 때, 로딩 시간이 3초 이상 지속되는 현상을 발견했다. 순간적으로 "이거 에러 난 거 아니야?"라는 생각이 들 정도였고, 이는 분명 사용자 경험 측면에서 좋지 않은 흐름이라고 느껴졌다. 예시 페이지에서는 모든 데이터를 한번의 fetch로 호출했다고 했는데, 쇼핑몰에 비교해봤을 때 상품 상세(상품 정보 더보기로 접혀있지도 않은), 사용자 리뷰,연관 상품 등을 한번에 호출하는 방식이었다. 

사실 과제의 요구사항 자체는 UX를 고려한 API 호출 최적화가 아니라, React Query 활용과 Suspense 및 Error Boundary 설정에 초점이 맞춰져 있었다. 하지만 나는 단순히 주어진 과제를 구현하는 것에서 그치기보다, 실제 서비스 환경에서의 사용자 경험까지 고려한 구현을 해보고 싶었다. 이러한 고민을 계기로, 모든 API를 한 번에 호출하며 사용자를 기다리게 하는 방식은 개선이 필요하다는 결론에 도달하게 되었다.

그렇다면 실제 서비스에서는 어떻게 처리하고 있을까?
궁금증이 생겨 카카오톡 선물하기와 쿠팡 같은 쇼핑몰을 직접 테스트해 보았다. 보통 쇼핑몰들에선 가장 먼저 보이는 곳을 최우선으로 랜더링했고, 헤더를 포함한 전체 화면을 스페너(로딩)처리하는게 아닌 상품이 보이는 부분에서 시작하거나, 상품 더보기 버튼을 두고, 접어두는 형태를 취하고 있었다. 이 과정에서, 내가 고민하던 방향성이 충분히 타당하다는 확신을 얻을 수 있었다.

프론트엔드에서 흔히 사용하는 개념 중에 낙관적 업데이트(Optimistic Update)가 있다. 인스타그램의 좋아요 기능처럼 서버 응답을 기다리지 않고 먼저 UI를 반영하는 방식이다. 이 개념의 핵심은 결국 UX를 얼마나 빠르고 자연스럽게 전달할 수 있는가에 있다. 사실 낙관전 업데이트는 제품 wish버튼에만 적용했지만, 나는 이러한 철학을 이번 API 최적화 과정에도 적용해 보기로 했다. 단순히 섹션별로 로딩을 분리하는 것만으로는 부족하며, 전체 로딩 경험 자체를 줄이는 것이 더 중요하다고 판단했기 때문이다.

어떤 방식이 가장 적절할지 고민한 뒤, 기존에 블로그 SEO 최적화나 개인 프로젝트를 진행하며 경험했던 로딩 전략들을 떠올렸고, 이를 기반으로 하나의 가설을 세웠다. 그리고 바로 구현하기보다는 멘토님께 먼저 설계 방향에 대해 질문을 드렸다.

post8-17-mission4-api-optimization-question.png

멘토님께서는 해당 접근 방식이 매우 좋은 방향이라고 말씀해 주셨고, 그 피드백을 바탕으로 실제 구현을 진행하게 되었다.

먼저 상품 상세 페이지에서 사용되는 API를 정리해 보았다. 총 4가지 API가 존재했다.

  • 최상단에 표시되는 상품 기본 정보: /id

  • 최하단에 표시되는 Wish(하트) 수: /wish

  • 상품 탭에서 확인 가능한 상세 설명: /detail

  • 상품 탭에서 확인 가능한 리뷰: /review

이후 사용자 관점에서 PC와 모바일 환경을 모두 고려해 사용자 흐름을 분석했다. 그 결과, 사용자가 페이지에 처음 진입했을 때 즉시 확인하는 영역은 최상단 상품 정보와 고정 버튼 영역이라는 점을 확인할 수 있었다.

post8-18-mission4-api-optimization.png

이 분석을 기반으로 다음과 같은 전략을 수립했다.

  1. 사용자가 페이지에 진입하면, 스켈레톤 UI와 함께 이미지, 가격과 같은 핵심 상품 정보와 좋아요 수처럼 상대적으로 가벼운 API만 우선 호출하여 화면을 빠르게 구성하도록 설계했다.

  2. 스크롤을 내려야 확인할 수 있는 상세 설명과 리뷰 영역은, 첫 번째 컴포넌트가 마운트된 이후 useEffect 등을 활용해 백그라운드에서 미리 데이터를 호출(Prefetching)하도록 구현했다.

이 과정에서 한 가지 고민도 생겼다.
“사용자가 실제로 보지 않을 수도 있는 탭 데이터를 미리 불러오는 것이 과연 맞는 선택일까?”라는 생각이었는데 결국 한번에 프리패칭으로 받아오기로 결정했는데 구현에 대한 최종 이유는 아래와 같다.

첫 번째는 데이터 사용 가능성이었다. 상품 상세 페이지까지 진입한 사용자라면 상세 정보나 리뷰를 확인할 확률이 매우 높다고 판단했다. 즉, 데이터를 미리 불러와도 낭비될 가능성보다 실제로 활용될 가능성이 훨씬 크다고 보았다.

두 번째는 UX의 연속성이었다. 사용자가 페이지 진입 과정에서 이미 로딩을 경험했는데, 탭을 클릭할 때마다 다시 로딩 스피너를 마주하게 된다면 서비스 경험이 단절될 수 있다고 생각했다.

세 번째는 API 네트워크 효율이었다. 데이터가 지나치게 방대하지 않은 경우라면, 가능한 한 API 요청 수를 줄여 한 번의 호출로 필요한 데이터를 가져오는 것이 네트워크 측면에서 효율적이라고 판단했다. 실제로 멘토님께서도 카카오맵의 경우 한 번의 패칭으로 관련 데이터를 모두 가져오는 방식을 사용한다고 말씀해 주셨다.

이러한 과정을 시작으로 나는 UX 향상을 끊임없이 고민했고 이를 통해 과제완 다르게 사용자에게 더 빠르고 자연스러운 페이지 경험을 제공할 수 있게 되었다.


다음은 테스트 코드에 대한 부분인데, NextStep의 강의자료와 FE강사님의 강의를 토대로 구현하게 되었다. 최대한 비슷하게 따라해보려고 노력많이했는데, 하루하루 TIL을 쓰던 중이었고, 이에 대한 부분도 노션으로 남겨둔것이 있어서 나중에 나도 다시 읽어봐야겠다. https://fog-alarm-d25.notion.site/TIL-refactoring-step3-22f9dbf949f4803abe5ad08d0c0c9cc1

post8-19-mission4-refactoring.png
post8-20-mission4-api-optimization-question.png

 

이번 멘토님께는 Mission3에서 migration했던 FSD아키텍처에 대해서도 평가를 받고 싶어서 질문을 했고, 여러가지 조언을 얻을 수 있었다.

post8-21-mission4-fsd-question.png

이렇게 질문을 많이 드려도 친절히 답변해 주셔서 감사한 마음을 갖고있다…

이번 Mission 4의 멘토님은 대체적으로 나의 생각을 많이 물어봐주셨고, 그에 대한 답변을 드리면서 내가 생각하면서 작성했던 코드들에 대해서도 다시 상기하게 되었고, 놓친 부분들도 배우게 되어 개발자의 생각을 반영하는 코드를 만들어가는데 큰 도움이 되었던 것 같다.

내 단점을 여쭤보다

지금까지 4분의 멘토님들 코드리뷰를 받아보면서 큰 성장을 이루었다. 하지만 질문에 대한 답변을 제외하고,내가 잘하고있는점이나 단점들 같은 나에 대한 평가가 궁금했다. 간혹 수강생들의 장점들을 언급해주시는 멘토님들도 계셨지만, 나는 그런 부분들 보단 단점을 파악해서 개선해보고자하는 니즈가 있었다.

그래서 마지막 미션을 완수하고, 이번엔 질문대신 나의 단점과 나아갈 방향성에 대해 여쭤보는 PR을 보냈다.

post8-22-mission4-code-review-final.png

답변을 받아보며, 정말 열심히 배우고 성장하고자 노력하면 그 모습이 분명히 드러난다는 것을 느꼈다. 구현 과정에서는 어떤 기술 스택을 선택하고, 어떻게 설계할지에 대해 AI에 의존하지 않고 나만의 생각을 담아 결정했고, 이를 문서화하여 멘토님들께 공유했다. 사실 멘토님의 역할은 코드 리뷰에 국한되지만, 그 외에도 수강생의 추가적인 질문과 생각까지 세심하게 봐주시고 리뷰해 주신 점이 감사하게 느껴졌다. 내 의견을 존중해 주시고, “스스로를 믿어보라”는 조언을 해 주신 덕분에 나 자신에 대한 확신이 커졌고, 앞으로 진로와 방향성을 설계할 때 중요한 기준점이 될 것 같다.

Comments