안녕하세요! 이번 2022 신입 개발자 공채로 입사한 커머스 FE개발파트 fleek(플릭)이라고 합니다. 저는 2022 신입 공채 프론트엔드 크루들이 경험한 6주간의 기술 온보딩에 대해서 소개하고자 합니다.
온보딩은 ‘배에 탄다’라는 뜻으로 신규 구성원이 조직에 수월히 적응할 수 있도록 업무에 필요한 지식이나 기술 등을 안내·교육하는 과정을 뜻합니다.
그렇기 때문에 기술 온보딩은 카카오의 뉴크루들에게 실무에서 일할 기술적 베이스를 만들어주는 과정이라고 이해하시면 될 것 같습니다.
그럼 본격적으로 FE뉴크루들을 대표하여 직접 경험한 6주간의 프론트엔드 기술 온보딩 과정을 소개하도록 하겠습니다!
6주 동안 했던 활동들
기술 직무 온보딩은 소프트웨어 전문 교육기업인 코드스쿼드가 함께해 주셨습니다.
6주간 아래의 일정으로 진행이 되었습니다.
온보딩에서는 다음의 활동을 가장 기본이자 중요한 활동으로 진행하였습니다.
- 미션
총 4개의 프로젝트로 주어진 기간과 요구사항에 맞춰
스스로 미션을 구현하는 시간
- 그룹 피어 세션
아침마다 8명씩 조를 이루어 자신이 직전까지 고민했던
코드 및 꿀팁을 공유하는 시간
- 코드 제출 & 코드 리뷰
매주 화/목요일 오후 3시까지 GitHub에 PR 보낸 후
사내 코드 리뷰어들에게 코드 리뷰를 받는 시간
- 미니 세미나
10분 내외 분량으로 자신이 공부한 내용 또는 기술 경험을 공유하는 시간
- 라이브 멘토링
전문가가 코드 리뷰 위주로 피드백을 전달하고 자유롭게 질의응답을 하는 시간
- 주간 회고
그룹별로 모여서 잘한 점/개선할 점을 작성하고 서로를 격려하고
피드백 해주는 시간
- 매일 3분 회고 작성
매일 3분 회고 작성을 통해 하루를 돌아보는 시간
- 페어 프로그래밍 & 페어 리뷰
같은 그룹 내의 지정된 사람과 짝을 이뤄서 서로의 코드를 리뷰하는 시간
프로젝트
저의 프로젝트 과정을 소개하도록 하겠습니다.
1차 프로젝트 : 카카오페이지 UI 클론
- 기한 : 5일
- 내용 : 카카오페이지의 UI를 클론 한다
- 특징적 요구사항
- 바닐라 자바스크립트로 구현
- ES6 클래스가 아닌 함수로 구현
- 하나의 페이지로 운영하며 상태를 이용해 뷰를 제어
기술 온보딩의 첫 번째 프로젝트인 만큼 본격적으로 HTML,CSS,JS를 다루기 전 잃어버린 감을 찾아오는 몸풀기 단계라고 생각을 했는데요. 오랜만에 바닐라 자바스크립트를 하는 게 어색하기도 했지만, 이 기반이 튼튼해야 추후 새로운 프레임워크를 다뤄도 흔들림이 없겠다 싶어서 열심히 임했습니다.
제가 이번 프로젝트를 통해 깨닫게 된 것은 다음과 같습니다.
1. DOM 탐색은 비용이 많이 드는 작업
사소한 것이지만 querySelector()를 쓸 때 document로 시작점을 정하는 습관이 많은 것으로 알고 있습니다. 하지만 DOM은 트리 구조를 가지고 있으며 DOM 트리의 그림을 떠올려 보면 document에서 출발해 element를 찾아가는 과정은 비용이 드는 작업이 됩니다.
그렇기 때문에 시작점을 특정 엘리먼트로부터 시작할 수 있게 해줘야 DOM 탐색의 범위를 좁힐 수 있다는 것, 어찌 보면 당연한 것이지만 그 이유에 대해서 완벽히 깨닫게 되었습니다.
또한 캐싱을 통해서 다음에는 캐시 된 값을 이용한다면 비용을 더욱 줄일 수 있습니다. 아래 사진에서 주석으로 표기된 로직을 사용하면 getTarget()을 호출할 때마다 DOM 탐색을 매번 실행하게 됩니다. 반면에 프로퍼티에 값을 저장해두면 다음 호출 때 이미 저장된 값을 이용해 불필요한 DOM 탐색을 줄일 수 있습니다.
2. 호출 스케줄링(setTimeout / setInterval) 및 애니메이션 최적화에 대한 이해
두 번째로는 캐로셀 구현에 관한 것입니다. 캐로셀은 위 1차 프로젝트 결과물 영상에서 슬라이딩 되는 UI 부분이라고 보시면 됩니다. 예전에 setTimeout으로 구현해 본 적이 있었기에 이번에는 setInterval를 통해서 구현하기로 결심했고 그 둘의 차이점을 이해하고자 했습니다.
setTimeout과 setInterval의 차이는 아래 사진과 같습니다.

setInterval 같은 경우에는 딜레이 시간에 콜백이 실행되는 시간도 포함이 되어 있다는 겁니다. 그렇기 때문에 콜백의 실행 시간이 길 경우 생기는 문제점이 있을 수 있습니다. 반면 setTimeout을 재귀적으로 호출하는 경우 딜레이에 콜백이 포함되지 않기 때문에 딜레이를 보장하는 부분에 있어서는 setInterval보다 강점이 있다고 볼 수 있습니다.
저는 예전에 setTimeout을 이용해서 구현했기 때문에 이번에는 setInterval를 이용했습니다. 또한 콜백이 무겁지 않았기 때문에 상관없다고 판단했습니다. 또한 제가 JS 애니메이션이 아닌 CSS 애니메이션을 적용한 이유는 다음과 같습니다.
- 간단한 애니메이션에 적합하다.
- 자바스크립트로부터 애니메이션 로직을 분리할 수 있기 때문에 컴포넌트의 진짜 역할에 대해서 좀 더 파악하기 쉽다.
마지막으로 애니메이션을 사용할 때 GPU 단에서 처리할 수 있는 속성(예를 들어, opacity / translate) 을 이용함으로써 repaint와 reflow가 일어나지 않게 하여 성능적 부분을 개선한 애니메이션을 구현하였습니다.
2차 프로젝트 : 카카오 쇼핑하우
- 기한 : 10일
- 내용 : 카카오 쇼핑하우의 UI를 클론 한다
- 특징적 요구사항
- 바닐라 자바스크립트로 구현
- ES6 클래스 이용
- 옵저버 패턴을 활용해서 M-V 간의 관계를 느슨하게 만듦
- Webpack과 Babel 세팅
두 번째 프로젝트에서는 주어진 기간이 길어진 만큼 요구사항도 늘어나고 양적으로든 질적으로든 좀 더 높은 수준의 퀄리티를 요구받았습니다. 그렇기 때문에 이번 프로젝트에서는 재사용성/가독성/유지 보수성 등을 최대한 신경 쓰면서 작업했습니다. 선언적 프로그래밍을 통해 가독성을 높이려고 하였고 부모에서 프로퍼티를 주입받아 컴포넌트의 재사용성을 높이려고 노력했습니다.
또한 백엔드 API를 직접 작업했습니다. 그 이유는,
- 서버에서 가공할 데이터를 프론트에서 데이터를 가공한다면 그것은 실무 코딩에 가깝지 않다는 생각을 했습니다.
- 프론트에서 어려운 부분 중에 하나가 비동기 처리이기 때문에 이런 부분들을 자주 겪어봐야 한다고 생각했습니다.
- 이런 경험을 통해서 백엔드 개발자와 협업할 수 있는 능력이 높아진다고 생각하기 때문에 전혀 시간이 아깝다고 생각이 들지 않았습니다.
두 번째 프로젝트를 진행하면서 가장 시간을 들인 부분은 다음과 같습니다.
1. 자동 완성 구현
여기서는 프로미스를 이용해서 구현할지 옵저버블을 이용해서 구현할지에 대한 고민을 했습니다. 고민 결과 RxJS을 이용한 옵저버블로 구현하자라고 정했는데요, 그 이유는 이 자동 완성 케이스에 대해서는 RxJS로 구현하기가 훨씬 쉽고 좀 더 가독성 있는 코드를 만들 수 있기 때문입니다.
또한 제공하는 오퍼레이터가 많기 때문에 디바운싱도 따로 구현하지 않아도 됐습니다. 추가적으로 요청을 중간에 취소할 수도 있다는 점이 아주 좋았습니다.
취소가 아주 좋다는 예시는 아래 사진을 이용해 말씀드리자면 요청을 중간에 취소할 수 없는 프로미스의 경우, 이후에 입력한 React 검색어가 이전에 입력한 Angular 검색어보다 결과가 일찍 도착한다면 최종적으로 결과는 늦게 도착한 Angular 결과로 렌더링 될 것이 문제가 된다는 점입니다.

2. 컴포넌트 재사용에 대한 고민
두 번째 프로젝트에서 시간을 제일 많이 소요한 부분은 컴포넌트 재사용입니다. 재사용을 하라는 말은 예전부터 많이 들었고 중요한 부분이라고도 생각합니다. 그렇기 때문에 컴포넌트를 어떻게 설계를 할까에 대해 많이 생각했고 최대한 재사용 할 수 있게 하려고 노력했습니다.
하지만 무조건적인 재사용을 하면 안 되겠다는 생각이 들었던 순간이 있었습니다. 아래 사진과 같이 두 사진은 하나의 컴포넌트를 재사용을 해서 구현을 할 수도 있지만 각각의 테이블이 구조가 달라 받아오는 데이터가 다르다는 점, 각각의 테이블은 계속 변할 수 있고 그거에 따라서 각각의 컴포넌트는 각자만의 방향으로 진화될 것이라는 점을 고려해 하나의 컴포넌트로도 재사용할 수 있지만 추후를 고려했을 때 따로따로 컴포넌트를 두는 게 낫다라는 방식을 생각을 결론을 냈습니다.
이 과정은 어느 구현 방법이 더 효율적인지 깊게 생각할 수 있었던 순간이었습니다.
3. 옵저버 패턴을 이용한 MV 간 느슨한 의존성 구현
요구사항에 모델과 뷰 사이의 의존성을 낮추라는 미션이 있었기 때문에 그 미션을 충족시키기 위해서 옵저버 패턴을 사용하였고 저는 아래 사진과 같은 느낌으로 단일 스토어를 운영했습니다.
특징은 이벤트 등록을 통해 Subject를 구독하고 이벤트 발생을 통해 구독한 옵저버에게상태를 전달하는 방식으로 구현했습니다. 아무래도 Mobx 상태 관리 라이브러리를 사용하신 분은 Store 구조가 눈에 익숙하실 것 같습니다.
결과적으로 의존성을 낮추기 위해 스토어에는 렌더링에 영향을 미치는 상태들을 모아두었습니다. 이렇게 스토어 분리를 하다 보니 데이터 관련 처리는 이 부분에서만 처리하기 때문에 에러 트래킹이 좀 더 수월하며 모델과 뷰 각각의 역할이 좀 더 명확해졌다고 느꼈습니다.
개인적으로 제가 사용한 기법은 상태가 많은 대규모 프로젝트보다는 관리할 상태가 적은 프로젝트에 어울린다고 생각합니다.
3차 프로젝트 : 자판기

- 기한 : 2일
- 내용 : 간단한 자판기를 만든다
- 특징적 요구사항
- React 이용
- 2인 1조 100% 페어 프로그래밍 진행
- style은 신경 쓰지 않음
세 번째 프로젝트부터 본격적으로 리액트를 사용하게 되었습니다. 세 번째 프로젝트는 2일이 주어졌고 비교적 간단한 구현 프로젝트였습니다.
다만 조건은 페어 프로그래밍 구현으로 짝과 같이 한 화면을 보고 코딩한다는 점이었습니다. 오랜만에 리액트의 감을 살리는 데 좋았던 시간이었고, 페어 프로그래밍에 장단점을 느낄 수 있었던 시간이었습니다.
제가 생각한 페어 프로그래밍의 장점은 동료가 어떻게 짜는지 어떤 시선으로 코드를 바라보는지 알 수 있었다는 것입니다. 그 과정에서 배울 수 있는 것들을 배웠습니다. 반대로 단점은 서로 코드 스타일이 다르다 보니까 나는 이렇게 짜고 싶은데 다르게 짤 경우 코드를 맞춰 가는 그 과정에서 시간이 소요 된다고 느꼈습니다. 특히 코드 스타일이 좀 더 자유로운 리액트라 더 그랬던 것 같습니다.
결과적으로, 페어 프로그래밍에 알려진 장점 중 하나가 둘이서 같은 코드를 보고 짜는 것이기 때문에 코드 리뷰를 할 필요가 없다는 것이고 결국엔 둘이 각자 짜서 코드 리뷰를 하는 시간과 같다는 것인데 저는 동료가 생각할 수 있는 방식을 봐서 성장에 도움이 될 수 있지만 생산성 측면은 잘 안 와닿았던 것 같습니다.
4차 프로젝트 : 이슈 트래커
- 기한 : 13일
- 내용 : 깃헙 이슈 시스템을 커스터마이징하여 구현한다
- 특징적 요구사항
- React 사용
- github Oauth 사용
- 상태 관리 라이브러리 사용
- React Router를 직접 구현
- webpack / babel 설정
마지막 프로젝트 이슈 트래커는 깃헙의 이슈 시스템을 커스터마이징하여 구현한 것입니다. 기한은 13일이지만 저는 완성도를 높이려고 빨간 날을 좀 더 썼답니다 .. : )
마지막 프로젝트답게 유종의 미를 거두고 싶어서 저는 실제 이 프로젝트를 서비스를 한다는 마음으로 임했습니다.
첫 번째로 주어진 기획서를 꼼꼼히 읽어보고 얼마나 시간이 소요될지 파악했습니다. 그러고 나서 주어진 기한까지 실제 서비스가 되기 위해서 지금 우선순위를 둬야 하는 것은 무엇이고 후 순위로 둬야 될 것은 무엇이든지 분류를 하였습니다. 또한 기획자가 없지만 기획자가 있다고 생각하고 그 기획서를 기반으로 제가 생각하기에 이런 방식이 더 낫다 싶은 것들을 수정했습니다.
두 번째로는 데이터가 제공되지 않았기 때문에 백엔드까지 구현을 했습니다. 백엔드 API부터 테이블 설계 / 배포까지 다 진행했는데 이유는 2차 프로젝트에서 다룬 이유와 동일합니다.
세 번째로는 UI/UX에 신경을 썼습니다.
- 웹 폰트
- 초기 로딩 속도 해결
- XSS 방지
- 토스트를 통한 메시지 전달
- github Oauth 로그인
등 여러 부분에서 신경을 썼는데 일부는 아래에서 자세하게 다루겠습니다.
마지막 프로젝트인 만큼 양도 엄청 많았고 그 안에서 엄청난 성장을 했다고 생각합니다. 그리고 리액트가 현 트렌드를 주도한다고 생각해서 최신 트렌드 및 기술을 적용해 보고 싶었습니다. 제일 열심히 한 프로젝트인 만큼 할 말도 많지만 추려서 경험하고 배운 것 4가지 정도 소개 드리고자 합니다.
1. CSR의 초기 로딩속도 문제 해결
현재 사용하고 있는 리액트(ver.17)는 클라이언트 사이드 렌더링 방식으로 초기 로딩 속도가 느리다는 치명적인 단점이 있었습니다. 초기 로딩 속도와 유저의 이탈률은 비례하기 때문에 꼭 신경을 써야 했습니다.
초기 로딩 속도를 줄이기 위해 시도한 방법은 다음과 같습니다.
- 번들 사이즈 자체를 줄인다.
- 웹 팩 설정을 프로덕션에 한해 프로덕션 모드를 적용하여 난독화/압축 등을 통해 번들 사이즈를 줄였습니다.
- 트리 쉐이킹을 이용하여 사용하지 않는 코드를 제거하여 번들 사이즈를 줄였습니다.
- npm dedupe를 이용하여 라이브러리 설치 과정에서 놓친 중복 디펜던시를 제거하여 번들 사이즈를 줄였습니다.
- 번들을 쪼개 메인 번들을 가볍게 한다.
- Dynamic Import를 사용해 필요할 때 컴포넌트를 동적 호출하여 메인 번들 자체를 가볍게 하였습니다.
- 일정 크기 이상의 모듈에 대한 중복 호출 시 번들을 분리할 수 있는 웹 팩의 splitChunksPlugin을 이용하여 메인 번들을 가볍게 하였습니다.


LightHouse를 이용해 성능 측정을 하였을 때 Before에 비해 After를 보니 전반적인 지표들이 상승했음을 알 수 있고, LCP(Lagest Contentful Paint) 지표는 로딩을 의미하는데 로딩 시간을 5초나 줄일 수 있었습니다.
2. Recoil과 React-query를 이용한 상태 관리
상태에 대한 좋은 글들을 미리 읽어보고 이번에 Recoil과 React-query를 꼭 써봐야겠다는 생각이 들었습니다. 제 기준에서 스토어에 상태를 넣을 때 UI 상태는 Recoil에 담는 것이 적절하다고 생각이 들었고 비동기 상태는 React-query로 관리하는 게 적절하다고 생각했습니다. 또한 이렇게 사용한다면 Recoil에서 관리할 전역 변수가 적기 때문에 리덕스를 사용할 필요성이 줄어들지 않나라는 생각이 들었습니다.
Recoil의 경우, 처음 사용해 봤는데 러닝 커브가 낮아 쉽게 접근할 수 있다고 생각했고 공식 문서도 잘 나와 있었습니다. 간단하게 UI 상태들을 담는데 편했던 느낌이 강했습니다. 개인적으로 점점 더 사랑받지 않을까 생각했습니다.
React-query의 경우, 이것도 역시 처음 사용해 봤습니다. 공식 문서는 다 영어로 돼 있고 생각보다 자료가 많은 거 같진 않지만 쓰면서 굉장히 강력한 도구라고 생각이 들었습니다. (1) 전역 변수 자체를 줄일 수 있다는 장점 (2) 그리고 캐싱을 손쉽게 쓰도록 지원해 준다는 것 (3) 두 개의 훅과 하나의 메소드로 사용할 수 있다라는 장점 (4) 동일한 요청이 여러 번을 보낼 때 첫 요청만 보내고 나머지는 취소시킬 수 있는 기능 탑재와 같은 장점들을 느꼈고, 서버와 상태를 좀 더 동기화시킬 수 있는 아주 좋은 도구라고 생각이 들었습니다.
좋았던 예를 2가지 소개 드리겠습니다.
첫 번째 예는, 위 필터 데이터는 바뀔 값들이 아니기 때문에 한 번 불러올 때 계속 사용하도록 하는 게 좋습니다. 저는 캐싱 시간을 조절해 다른 페이지에 갔다가 다시 와도 캐시 된 값을 썼기 때문에 효율적으로 API를 호출할 수 있다는 장점을 몸소 체감할 수 있었습니다.
두 번째 예로는, 위 이미지의 첫 페이지에서 다음 페이지로 넘어갈 때 일반적으로 로딩 바가 뜰 텐데 React-query를 이용해 옵션을 설정하면 가짜로 이전 데이터를 보여주고 실제 데이터가 올 때 실제 데이터로 교체해서 보여줌으로써 훨씬 더 깔끔한 화면을 제공합니다. 그리고 한번 갔던 페이지에 대해서는 캐시 된 값을 이용해 빠르게 뷰를 보여줄 수 있었습니다.
단기간에 두 개의 상태 관리 라이브러리들을 사용해 보면서 어떤 상태에 어떤 라이브러리를 적용하면 좋을까에 대해 깨닫게 되었습니다. 그리고 캐싱은 프론트 개발자에게 어려운 부분이라고 알고 있는데 React-query를 이용해서 쉽게 제공받았기 때문에 그 제공받은 것을 기반으로 캐싱 전략 구성에 집중할 수 있었던 것이 정말 좋다고 느꼈습니다.
3. Context API를 이용한 라우터 구현
일반적으로 쓰는 라우터를 구현하기 위해서 pushState와 popState 이벤트를 이용해야 하는데요. 저는 context API와 pushState 그리고 popState를 이용해 라우터를 구현했습니다. 제가 context API를 선택한 이유는 history.push()라는 페이지 이동할 수 있는 기능을 일일이 props로 내려주기 보다 context API를 이용해 props drilling을 없애 좀 더 편하게 쓰기 위함이었습니다.
그 결과 라우터를 만들면서 Context API에 대해 더 깊게 이해할 수 있었습니다.
4. 메모이제이션 기법에 대한 고민
useMemo / useCallBack / React.memo 이 3개를 어떻게 다루느냐에 따라 성능에 영향을 미치기 때문에 어느 정도의 빈도로 사용할까라는 고민을 했었습니다. 메모이제이션을 통해 성능을 올릴 수 있지만 가독성 문제와 메모리 문제 등 여러 문제가 있을 수 있기 때문에 고비용의 로직에만 적용하자는 결론을 내렸습니다.
이 과정에서 실제 프로덕션의 메모리는 얼마나 차지하며 얼마나 여유로울지에 대한 궁금증을 가지게 되었고 대부분은 메모이제이션을 사용해도 걱정할 정도는 아니지만 이것도 분명 메모리를 걱정해야 할 케이스도 있을 것이기 때문에 적용할 때 그 앱의 메모리에 대해서도 체크를 해야겠다는 생각이 들었습니다.
좋았던 점
FE 뉴크루들과 기술 온보딩에 대해 좋았던 점을 3가지 정도로 뽑아 봤습니다.
1. 그룹 세션
매일 오전에 진행했던 8명씩 조를 이루어 진행했던 그룹 세션의 경우, 자신의 코드에 대한 고민 및 꿀팁을 공유하는 자리였기 때문에 대부분이 굉장히 유익했다고 느꼈습니다.
2. 코드 리뷰
주 2회 사내 코드 리뷰어에게 코드 리뷰를 받는 시간이 있었습니다. 저희는 실무자의 관점에서 코드 리뷰를 받을 수 있어 굉장히 질적으로 좋았다고 생각합니다. 오히려 코드 리뷰 횟수가 더 늘었으면 하는 바람도 있습니다.
3. 새로운 기술에 대한 경험
모든 크루들이 기술온보딩을 통해 새로운 기술에 대한 경험을 했습니다. 자신의 프로젝트에 기술적으로 다양한 시도를 할 수 있는 기회였고 많은 생각을 하고 적용했기 때문에 성장을 많이 할 수 있었던 부분이라 생각합니다.
아쉬웠던 점
반면에 아쉬웠던 점을 3가지 정도로 뽑아 봤습니다.
1. 비대면
아무래도 온라인이 오프라인보다 대화를 나누거나, 친해지기도 어려운 환경이다 보니 많은 크루들이 아쉬워하는 부분인 것 같습니다.
2. 요구사항 구현에 대한 아쉬움
모두가 출발선이 다르기 때문에 누구에게는 익숙하지만 누구에게는 처음 마주하는 환경이었을 겁니다. 새로운 것을 많이 접하는 상황에서 요구사항을 본인이 만족할 만큼 구현하지 못해 아쉬웠습니다.
3. 기반을 탄탄하게 할 시간 부족
좀 더 기반을 탄탄하게 만들고 싶고 기술적으로 다양한 시도를 하고 싶어 하는 크루들이 많았습니다. 그렇기 때문에 시간이 부족한 상황에 대해 모두가 아쉬워했습니다.
그림으로 요약하는 FE 기술 온보딩
그림 솜씨도 예사롭지 않은 FE 뉴크루들! 그림을 자세히 보면 크루들의 당시 상태에 대해서도 파악이 가능합니다. : ) 재밌는 그림을 너무 잘 그려주셨어요!
FE뉴크루들의 한마디
마지막으로 기술 온보딩을 함께한 서로에게 짧은 메시지를 주고받았습니다.
마치며
이렇게 프론트엔드 기술 온보딩의 긴 이야기를 마쳐볼까 합니다! 정말 뜻깊은 시간이었고, 다들 노력했기 때문에 후회 없고 의미 있는 시간이었지 않나 싶습니다.
다시 한번 FE 뉴크루들 / 코드스쿼드 크롱 / 기술기획팀 / 코드 리뷰를 해주신 사내 코드 리뷰어 분들께 정말 고생 많이 하셨고, 감사하단 말을 전하고 싶습니다.
우리 FE 뉴크루들의 발전을 기원하며 글 마치겠습니다.
긴 글 읽어주셔서 감사합니다!