세 달 간의 오늘의집 개발자 온보딩 과정을 돌아보다
지금 당신이 오늘의집 개발팀에서 일해야 하는 이유
2021년 8월 17일

회사에서 한 일, 해나갈 일

안녕하세요. 오늘의집에서 프론트엔드 챕터를 이끌고 있는 존입니다.

어느덧 제가 버킷플레이스에 입사한지 3개월이 지났습니다. 얼마 전 온보딩이 끝나며 정식 사원증도 받았습니다. 요즘 리추얼이라고 부르는 저만의 의식을 만드는 데에 신경쓰고 있는데, 5월달에는 매일 점심 요가를 했고, 코로나가 심해지기 전에는 오전에 30분 정도 커피챗을 가지기도 하였습니다.

흔히 온보딩 기간이라 불리는 버킷플레이스에서의 3개월을 돌아보며, 제가 이곳에 와서 한 일과 앞으로 해나갈 일에 대해 정리해 보았습니다.

체계 만들기

입사 후 제일 처음 한 일은 사내 프로젝트가 어떻게 동작하고 있는 지, 그 사이에서 제가 어떤 역할을 수행해야할 지 분석하는 일이었습니다. 오늘의집은 크게 4개의 제품 조직이 존재하는데요. 챕터 리드로서 저의 역할은 그 사이에서 지식이 흐르게 하고 정보를 서로 공유하게 하는 것이었습니다.

또한, 어느 회사들과 마찬가지로 제품에 딱 엮이지 않는 애매한 부분(회색 영역)에 대한 처리를 제게 먼저 할당하게 한 뒤, 다른 파트로 넘기는 방식을 취하고 있습니다. 그렇게 하여야 작업의 범위나 크기, 그리고 언제나 한 사람이 하게되는 일을 사전에 방지할 수 있기 때문입니다.

프론트엔드 프로젝트 설계하기

개발 블로그에 이미 올린 내용이지만, 기존에 오늘의집의 프로젝트는 Rails 에 React 를 연결시켜서 만든 조금은 이질적인 구조였습니다. 거기에 React-Rails 라는 라이브러리를 사용해서 SSR (Server Side Rendering) 을 구현했는데, 이 구조가 적절하지 않다는 이야기는 예전부터 나오고 있었다고 했습니다. 다시 설계가 필요한 부분이었죠.

<문제점>

1. 방대한 서비스의 크기

우선 제품의 크기가 너무나도 컸습니다. 단순히 ‘커머스’ 라는 카테고리만 보더라도 규모가 거대한데, 거기에 ‘콘텐츠’ 와 ‘시공’ 이라는 카테고리가 각자 또 붙어있으니 한 서비스의 크기가 얼마나 거대해질 지는 상상할 수 있으리라 생각합니다. 다행히 이런 상황에서도 일관성을 유지시키기 위해 UI 컴포넌트들을 별도 라이브러리로 빼낸 뒤, 해당 컴포넌트를 Import 해서 사용하는 방식을 취하신 상태여서 생각해보면 너무 다행이라고 생각합니다.

서비스의 크기가 너무 크다보니 빌드 시간도 오래 걸릴뿐만 아니라, 서비스간 격리가 어려워지고 서비스 사이에서 의존성을 가지기 시작하면서 조금씩 관심사가 여기저기 섞이기 시작하였습니다.

2. Client Server의 부재

서버 레이어에 대한 처리를 레일즈 서버가 모두 처리하고 있었는데, 당연히 레일즈 서버에 부하가 걸릴 수밖에 없는 구조이면서도 클라이언트 서버 로직을 처리하기 위한 모든 영역이 React 에 묶여있을 수밖에 없었습니다. 대표적인 예시가 바로 라우팅 처리인데요. 라우팅 처리를 서버에서도 한 번 등록해주고 클라이언트에서도 한 번 등록해주는 식으로 구조를 잡아야하는 상태입니다. Rails 에서 라우팅하는 Path 를 등록하고, React 에서도 해당 Path 에 특정 컴포넌트가 존재한다는 걸 알려주어야 했기 때문입니다.

또한 데이터 처리에 대한 문제도 있었습니다. 어떤 케이스에서는 포매팅을 서버에서 해주고 있었고, 어떤 케이스에서는 Plain Data 를 내려주면 클라이언트에서 정제해서 사용하는 구조를 취하기도 하였습니다. 다르게 이야기하자면 일관성을 유지하기 어려운 구조였습니다.

<해결방안>

1. MSA

우선 서비스들을 모두 MSA 구조로 가져가기로 하였습니다. 정확히 어느 단위로 나눌지에 대해서는 지속하여 논의 중이지만, 현재로서는 모놀리틱 구조가 한계라고 인식하고 있습니다.

2. FE on MSA

백엔드가 MSA 로 갔다고 해서 FE 도 반드시 MSA 로 갈 필요가 있는 것은 아니지만, 지금 상황에서 모놀리틱 아키텍쳐가 여러 문제를 추가로 만들어내고 있다고 생각하였기에 저는 이와 같이 정리하였습니다. 다만 이 구조는 비교적 최근 모델이기 때문에 예시로 들 사례를 아직 알려드리기는 어렵습니다. 추후에 서비스를 오픈하고 난 뒤 케이스를 공유드리도록 하겠습니다.

  • 도메인 단위 (= 보통 배포 단위)로 저장소를 만든다.
  • 해당 도메인 내의 여러 제품은 단일 저장소 내에서 관리한다.
  • 도메인이 다른 경우에는 별도 저장소로 분리한다.
  • 개별 저장소의 테크 스택은 개별 도메인에 맡긴다. (다만 표준은 존재한다)

3. 표준 테크 스택

표준 테크 스택은 아래 도표로 정리하였습니다.

기본 개발 환경

  • 타입스크립트를 기본으로 합니다.
  • 번들러는 WebPack을 사용합니다.
  • 구버전 브라우저 지원을 위해 Babel을 사용합니다.
  • 코드 일관성 유지를 위해 ESLint를 사용합니다.
  • 서비스에 따라 다르지만, 기본적으로는 SSR을 지원합니다.

클라이언트 개발 환경

  • NextJS 를 기본으로 합니다.
  • React 를 사용합니다.
  • 함수 컴포넌트 + Hooks + React Query (or Apollo Client) 구조를 권장합니다.
  • 스타일은 Emotion 을 활용한 Styled Component를 사용합니다.
  • 유닛 테스트에는 Jest를 사용하고 있습니다.
  • 퍼포먼스 측정을 위해 Lighthouse 를 사용합니다.
  • UI 관리를 위해 Storybook 을 사용합니다.

클라이언트 서버 개발 환경

  • NextJS 를 서빙하는 Express 서버를 둡니다.
  • 로깅을 위해 WinstonJS 를 활용합니다. (DataDog를 함께 사용합니다)
  • 서버 모니터링을 위해 DD-Trace 를 활용합니다. (DataDog를 함께 사용합니다)

BFF 서버

  • 공통 로직 관리 어떻게 할 지 고민

  • 여러 MSA에서 제공하는 API를 묶거나 컨버팅 하는 걸 목표로 합니다.

    • API Endpoint 를 은닉할 수 있습니다.
    • 클라이언트 표시를 위해 필요한 작업을 줄일 수 있습니다.
    • 클라이언트 로직 중 크리티컬한 비즈니스 로직을 은닉할 수 있습니다.
  • DB는 직접 건드리지 않습니다.

  • NestJS 를 기본으로 활용합니다.

    • 크리티컬한 성능 저하는 없으나 기본으로 제공하는 것들이 많아 사용하고자 합니다.

      • 타입스크립트를 기본으로 지원합니다.
      • Express를 기본 미들웨어로 지원합니다.
      • 아키텍처를 제한하기 때문에 일관성 있는 코드를 만들기 좋습니다.
  • GraphQL 을 선택적으로 사용합니다.

    • 서버에서 제공하는 RESTful API 를 Apollo Server를 이용하여 GraphQL로 변경합니다.
    • 이 경우 클라이언트에서도 Apollo Client 를 사용합니다.

아키텍처는 사내 구성원이라면 누구나 볼 수 있는 위키에 올려두었는데요. 이 방법이 반드시 정답이라고 생각하고 있지는 않습니다. 실제로 지금 진행하고 있는 프로젝트들에서 BFF 서버는 Next.js 가 기본으로 제공하는 API 를 사용하는 케이스도 존재하고요.

여기서 말씀드리는 모델은 어디까지나 표준안입니다. 표준안에서 다양한 변형이 나올 수 있음을 전제로 하고 있으며, 비즈니스의 목표와 방향에 따라서 다양한 설계 패턴을 고려해볼 수 있음을 전제로 하고 있습니다. 언제든지 바뀔 수 있음을 염두해두고 있죠.

문제를 해결하고 더 나은 서비스를 만들기 위해

지금까지 경험해왔던 회사들의 사례를 살펴보면, 어떤 문제가 생겼을 때 우회하여 해결하는 모습을 종종 보이곤 했습니다. 물론 그게 나쁘다는 건 아닙니다. 핵심 문제가 어딘가에 존재하는 데 그 핵심 문제를 직접 건드리기에는 시간도 리소스도 부족하고 리스크가 너무 크니 우선 돌려서 해결하자는 방식을 취했던 것이죠.

하지만 그러는 동안에도 핵심 문제는 점점 덩치를 키워나가고, 결국에는 그 문제가 우리의 중요한 시점에 발목을 잡기도 합니다. 그리고 그런 문제들을 모아 우리는 기술 부채라고 말합니다. 기술 부채는 관리되어야 하고, 언젠가 해결해야할 문제이지만 부채가 너무 커졌을 때 우리가 아무것도 하지 못한다면 거기에는 폐허만 남습니다.

그런 의미에서 지난 3개월을 돌아보았을 때,

문제가 발생하면 이를 회피하지 않고 직접 마주하고, 우리가 가진 문제를 해결하기 위해서 어떤 식의 접근방식이 필요할 지 서로 논의하는 버킷플레이스의 문화는 상당히 인상깊었습니다. 문제가 있을 때 문제의 원인을 개인에게 돌리지 않고, 그 상황에서 가장 적절한 답이었을거라 생각하며 앞으로 더 나은 제품을 위해 무슨 노력을 기울이는 게 좋을 지 회사 구성원들이 모두 함께 판단하는 문화가 중요하다고 생각하기 때문입니다.

우수한 개발 문화를 기반으로, 더 나은 서비스를 만들기 위해 노력하는 오늘의집 개발팀과 함께할 여러분을 환영합니다. 망설이지 말고 지금 지원하세요!

오늘의집에서 당신을 찾고 있습니다!
Engineering Manager, ApplicationsSenior Technical Program ManagerSenior Software Engineer, BackendSoftware Engineer, BackendSenior Software Engineer, FrontendSoftware Engineer, FrontendSenior Software Engineer, AndroidSoftware Engineer, AndroidSenior Software Engineer, Machine LearningSoftware Engineer, Machine LearningSenior Software Engineer, Machine Learning, Extended RealitySenior Software Engineer, Vision ML
목록으로 돌아가기