당근페이 FE, 4개의 프로젝트를 하나로 합치며 나눈 대화들

Kooku
당근 테크 블로그
20 min readMar 20, 2024

안녕하세요, 당근페이에서 결제서비스를 개발하고 있는 프론트엔드 개발자 Kooku예요.

당근페이 프론트엔드는 Dylan, Peter, Yena 그리고 저를 포함해 총 4명의 개발자가 함께 일하고 있어요. 팀은 다르지만 리소스가 부족할 때는 서로 도와주고, 더 훌륭한 서비스를 만들고 효율적으로 일하기 위해 많은 대화를 나누는 편이에요.

현재 저희는 각자 맡아왔던 프로젝트 4개를 하나로 통합하는 큰 변화를 진행하고 있는데요. 이러한 결정에 이르게 된 과정과, 문제 해결을 위해 어떻게 소통하고 노력하고 있는지에 대해 이야기해보려고 해요. 그리고 치열한 논의 끝에 도출된 현재 프론트엔드 프로젝트 폴더구조를 소개할게요.

본 글을 통해 많은 분들이 당근페이 프론트엔드 개발자들이 어떻게 일하는지, 어떤 폴더구조를 사용하는지 보며 유익한 인사이트를 얻으셨으면 좋겠어요.

FE 프로젝트 역사

당근페이 내에는 MONEY PAYMENT ACCOUNT CARD 총 4개의 프로젝트가 있었어요. 처음부터 이렇게 4개의 프로젝트가 있었던 건 아니에요. 당근페이 초기에는 FE 개발자인 Dylan 혼자 MONEY 프로젝트를 책임지고 있었어요. 당시에는 MONEY 프로젝트가 송금, 페이홈, 가입, 탈퇴, 계좌 연결 등 페이 내 모든 스펙을 다루고 있었죠.

그런데 Peter가 당근페이에 합류하면서 변화가 시작되었어요. FE 리소스가 부족해서 백엔드 개발자 분들이 결제창까지 담당하고 있었던 상황에서 Peter가 합류하면서 PAYMENT 프로젝트가 시작되었고, 다른 서비스들에서 결제 시스템을 쉽게 연동할 수 있도록 SDK도 만들어졌죠.

그리고 Yena가 합류하면서 MONEY 프로젝트 중 계정과 관련된 부분을 분리하기 시작했어요. 그 결과 ACCOUNT 프로젝트가 생성되었고, ACCOUNT 서비스에서는 token 발급, 본인 인증, 페이 가입, 계좌 연결, 약관 관리, 탈퇴 등을 담당하게 됐어요.

마지막으로 제가 페이에 합류하면서 CARD 프로젝트가 새로 생겨났어요. CARD 프로젝트에서는 카드 등록과 관리를 책임지고 있죠.

분리된 프로젝트, 단점이 보이기 시작하다

각자 팀이 다르고, 담당하는 서비스도 다른 4명의 FE 개발자들이 자연스럽게 프로젝트를 나누어 개발하게 되었어요. 이런 구조는 각 팀이 자유롭게 개발을 진행할 수 있게 하여 개발 속도를 빠르게 하고, 배포가 분리되어 있어 배포에 대한 부담을 줄이는 장점이 있었어요. 하지만 시간이 지날 수록 장점보다 단점들이 더 많이 보이기 시작했어요.

(1) 프로젝트 역할과 범위의 불명확성

프로젝트의 분리는 개발 속도의 향상과 배포의 편리함을 가져다주었지만, 각 프로젝트의 역할과 범위가 명확하지 않다는 문제점이 있었어요. 프로젝트가 팀별로 분리됨에 따라, 특정 팀이 담당하지 않는 부분이 생겼을 때 해당 기능을 어느 프로젝트에 구현해야 하는지 결정하기 어려웠어요. 예를 들어, 약관관리 페이지가 만들어졌을 때 ACCOUNT 프로젝트에 들어가야할지 MONEY 프로젝트에 들어가야할지 혼란스러웠어요.

(2) 프로젝트 복잡성 증가 : 역할과 맥락의 혼재

프로젝트가 역할별로 분리되었음에도 불구하고, 프로젝트의 성격과 다른 맥락과 요구사항들이 조금씩 추가되기 시작했어요. 예를 들어 카드 등록 화면에서 가입을 시키는 flow가 추가된 경우가 있었어요. CARD 프로젝트에서 ACCOUNT 프로젝트로 진입하는 상황이었죠. 이때 가입 완료 화면에서 카드 등록 하러가기 버튼을 보여주고, 가입 플로우에 있는 계좌 연결 단계를 생략하거나 특정 조건에 따라 다르게 처리해야 했어요. 이렇게 ACCOUNT에 다른 프로젝트들의 요구사항들과 맥락들이 추가되면서 ACCOUNT가 점점 복잡해지기 시작했어요. 많은 분기문이 들어가게 되고 매우 많은 맥락들이 포함되었죠.

(3) 동일한 작업의 반복, 라이브러리 관리, 인터페이스 단일화의 필요성

4개의 프로젝트에서 모두 동일한 작업을 반복해야 하는 경우들도 생겼어요. API 헤더에 커스텀 헤더를 추가해달라는 요구사항이 있었을 때가 그랬죠. 당근에서 사용중인 Stackflow 라이브러리 업데이트도 동일했어요. 프로젝트 분리에 따라 이처럼 같은 작업을 여러 번 반복해야 하는 상황이 자주 발생하게 되고, 이는 작업의 효율성을 떨어뜨렸어요.

프로젝트마다 라이브러리 버전을 다르게 관리하다보니, 라이브러리에 인터페이스가 변경된 breaking changed가 있을 때 개발자가 버전 확인을 하지 않아 실수할 수 있는 상황이 발생하기 쉽기도 했어요. 특정 기능을 수행하는 라이브러리(unique-id 생성, date 등)나 eslint 설정들도 프로젝트마다 달라, 다른 프로젝트에서 개발할 상황이 있을 때 적응하기도 쉽지 않았어요. 또한, 각 프로젝트에서 사용중인 동일 기능의 함수들의(modal) 사용 방법들도 각각 달라 매번 사용법과 인터페이스를 새로 파악해야 하는 수고도 필요했어요. 새로운 도메인의 화면이 나와 새 프로젝트를 만들기로 결정했을 때 ci, cd, infra 셋팅등에 들어가는 리소스도 너무 많았어요.

프로젝트가 분리되었기에 관리가 쉬워질 것이라 생각했지만 시간이 지날수록 관리해야할 포인트들이 점점 많아졌어요. 각 프로젝트마다 서로의 영역을 조금씩 포함하는 요구사항이 들어올 때는 많은 논의와 인터페이스 변경이 필수적이였고요. 서로의 프로젝트가 SDK를 통해 open되는 상황에서 SDK의 인터페이스 변경시 배포 디펜던시까지 생겨 버렸어요.

(4) 쏟아져 나오는 여러 단점들

갈수록 여러 단점들이 쏟아져 나왔고, 당근페이 FE 개발자 4명이 모여 각자가 생각한 프로젝트 분리의 단점을 털어놓기도 했어요. 결국 논의 끝에 나온 결론은, ‘변화가 필요하다’는 거였어요.

Kooku: 지난번에는 웹 지원을 위해 account와 card에 변경사항을 반영하고 SDK도 버전업을 해야 했어요. 그때 하위 호환성을 유지하면서도 순차적으로 배포를 해야 했는데, 고려해야 할 사항이 너무 많아서 힘들었죠. 프로젝트를 분리하면서 이점도 있었지만, 현재 상황에서는 단점이 더 많은 것 같아요.

Dylan: 지금은 A 웹뷰에서 B 웹뷰를 띄울 때 새로운 웹뷰를 띄우고 stream을 통해 데이터를 가져오고 있어요. 하지만 stream을 너무 무분별하게 사용하고 있고, stream 부분에서 예상치 못한 에러들도 많이 발생하고 있어요.

Yena: redirection을 통해 해결할 수도 있지만, redirection에서 발생하는 깜박임이나 queryParams를 계속 물고다니고 관리해야 하는 이슈, 그리고 웹뷰의 메모리 누수로 인해 새로운 웹뷰가 로딩될 때 문제가 발생하기도 해요. 또한, 도메인이 다르기 때문에 모든 웹뷰가 상태를 동기화시키지 못하는 문제도 있어요.

Peter: 사실 해결 방법은 다양하지만, 현재 ROI(투자 대비 수익)가 너무 낮은 것 같아요. 그리고 이렇게 큰 기술과제와 다른 작업들을 동시에 진행하기도 쉽지 않을 것 같아요.

1) 우리는 원레포 원도메인으로 가기로 했다.

그래서 우리가 결정한 것은 ‘하나의 프로젝트, 하나의 도메인’이에요. 원프로젝트, 원도메인으로 변경되면 코드는 간결해지고 유지보수하기도 쉬워질 것 같았어요. 그리고 위에서 언급됐던 문제들도 쉽게 해결할 수 있을 것 같았어요.

하지만 원레포로 가기 위해서는 거쳐야 할 관문들이 많았어요. 논의 이후로 수 개월이 지났지만 아직도 해야 할 게 많이 남아있어요.

개성 강한 4개의 프로젝트를 하나로 합치기 위해서는 매우 많은 논의가 필요했어요. package.json 에 있는 라이브러리들과 버전들을 맞추고, eslint, prettier, config(vite, jest, playwright, …)를 이야기하면서 통일시켜야 했죠. 무엇보다 이상적인 폴더구조를 설계하기 위해 많은 논의를 했어요. 치열하게 폴더구조를 논의했던 팀원들과의 소통 방식이 인상적이었어서, 그 과정을 공유해보고자 해요.

2) 폴더구조 논의, 그 치열하고 긴 여정

(1) 첫 번째 논의: 대원칙 그리고 큰 틀 잡기

폴더구조를 정할 때 명확한 원칙과 기준을 바탕으로 방향을 잡으면 좋을 것 같았어요. 폴더구조에서는 가독성, 또 파일과 폴더를 쉽게 찾을 수 있는 게 가장 중요한 것 같은데요. 따라서 처음에 다음과 같은 대원칙을 정했어요.

  1. 연관된 것은 모아두자 : 도메인이 같은 것들은 같은 폴더에 모아두자.
  2. 직관적인 구조를 만들자 : 특별한 패턴을 따르기보다 처음 본 사람도 쉽게 찾아갈 수 있도록 하자

page 폴더

4개의 프로젝트를 나누었을 때 팀 별로 프로젝트를 나누었다고 봐도 과언이 아니에요. 서버 따라서 만들었다고 해야 할까요? 그렇다 보니 ui만 담기는 화면이나 새로운 도메인에 대한 화면이 나왔을 때 어느 프로젝트에 화면을 담아야 할지 항상 고민을 했어요. 프로젝트 내에서 도메인을 어떻게 정의하고 구분할지도 고민이 되었어요. 서버의 msa 구조를 따라 만들지(뱅킹, 결제, 머니, 카드, 유저, …) 프론트에서 자체적으로 도메인을 정의할지 말이에요. 서버를 따라서 만든다면 페이홈 같이 여러 도메인이 복합적으로 들어가는 페이지, ui만 그리는 페이지는 어디에 넣어야 할지 고민이 생길 것 같았어요. 자체적으로 정의한다면 서버 정의보다 더 세부적으로 페이지 단위가 만들어질 것 같았어요. (페이홈, 카드, 인증, 주소, 결제, ….)

결국 우리는 자체적으로 도메인을 정하기로 했어요. 그리고 page 폴더에 도메인 별, 그리고 상위 도메인에 하위 도메인들이 포함되며 page의 디렉토리 구성은 route 규칙의 path depth와 맞추어 설계하기로 했어요.

📦page
┣ 📂account
┃ ┣ 📂authentication
┃ ┣ 📂sign-out
┃ ┗ 📂sign-up
┣ 📂banking
┣ 📂benefit
┣ 📂payment
┃ ┣ 📂card
┃ ┃ ┣ 📂management
┃ ┃ ┗ 📂registration
┃ ┣ 📂index
┃ ┗ 📂receipt
┣ 📂terms
┗ 📂transfer

그리고 page에 강결합된 컴포넌트, 유틸함수, 훅스들은 대원칙인 “연관된 것은 모아두자”는 원칙에 따라 각 페이지 컴포넌트와 함께 두었어요.

📦page
┗ 📂payment
┗ 📂card
┗ 📂management
┣ 📂commponent
┃ ┣ 📜CardItem.tsx
┃ ┗ 📜CardList.tsx
┣ 📂hook
┣ 📂util
┣ 📜CardManagementPage.tsx
┗ 📜index.tsx

shared 폴더

개발을 하다 보면 여러 도메인에서 가져다 사용하는 컴포넌트나 함수 파일들이 많이 생기기 마련이에요. 하지만 이렇게 둘 이상의 도메인에서 사용되었을 때 다른 도메인의 폴더 내 파일을 참조하게 되면 의존성이 꼬여 나중에 찾아가기도 힘들고 유지보수하기도 어려울 것으로 판단했어요. 따라서 같은 도메인 내에서 공통되는 게 생기면 상위로 옮기고, 다른 도메인에서 가져다 사용할 컴포넌트가 생기면 shared로 옮기는 것으로 이야기했어요.

common 폴더

도메인에 종속되지 않으며 shared보다 더욱 추상화된 컴포넌트나 함수들은 common에 두기로 했어요.

service 폴더

추가로 bridge, google-analytics, sdk 등 외부 라이브러리를 wrapping 하거나 외부에 의존적인 로직을 포함하는 파일들을 분리하기로 하여 service라는 폴더가 나오게 되었어요.

📦src
┣ 📂common
┃ ┗ 📂service
┣ 📂page
┗ 📂shared

폴더 네이밍은 단수형으로

추가로 나온 의견 중에 하나가 폴더 네이밍 규칙이었어요. 폴더명을 복수로 사용하는 경우도 있고 단수로 사용하는 경우도 있는데, 사람마다 모두 다르기도 하고 명확한 기준이 없기에 폴더명은 모두 단수형을 사용하기로 결정했어요.

(2) 두 번째 논의: shared와 common의 기준

폴더구조에 관한 첫 번째 논의를 진행했지만 아직도 팀원들에게 찝찝한 감정이 남아있었어요. common과 shared에 대한 기준이 명확하지 않았기 때문이에요. shared, common, page라는 큰 틀을 정했다고 생각했지만, shared를 없애고 밖으로 다 빼는 건 어떨지에 대한 이야기도 나왔어요.

이때부터는 4명의 팀원들끼리 굉장히 다양한 의견을 나누며 치열하게 논의했는데요. 어떤 이야기들이 오고 갔는지, 그 대화록을 보여드릴게요.

① 한 번에 정해버리자 VS 그게 가능한 걸까?

저와 Yena는 폴더의 기준이 명확하지 않으면 pr을 만들 때마다 고민을 해야 하고, 관점 차이로 많은 논의를 해야할 것 같다고 생각했어요. 그래서 이번 논의에서 기준이 확실히 정해졌으면 좋겠다고 했죠. 반면 Peter와 Dylan은 애매한 게 없어져야 하는건 동의하지만 그걸 한 번에 다 추려낼 수는 없기에 애매한 게 생길 때마다 깊게 논의하는 게 좋다고 생각했어요.

Kooku: 지금 폴더의 기준을 명확히 정하지 않고 나중에 논의를 하게 되면 새로운 폴더나 파일이 만들어질 때마다 논의를 해야 하고 이때 사람마다 관점이 다 다를 수 있을 것 같아요. 그리고 이건 common과 shared의 기준이 명확하지 않다는 증거인 것 같아요. common과 shared의 기준이 애매하지 않았으면 좋겠어요. 사람마다 다르게 생각할 수 있는 요소들은 명확한 기준을 정하는 게 좋을 것 같아요.

Dylan: 앞으로 논의를 하지 않기 위한 준비를 하는 건 바람직하지 않은 것 같아요. 이런 논의는 시간을 많이 쓰더라도 필요할 때마다 하는 게 맞지 않을까? 하는 생각이에요.

Yena: 저는 그때그때 해야 할 논의가 적지 않을 것 같고, 그렇기에 개발할 때 항상 고민이 될 것 같아요. 여러사람이 같이 작업하는 프로젝트인 만큼 혼란스럽고 헷갈리는 걸 지양해야 하지 않을까요?

Kooku: 한 번 정한 후에는 논의를 아예 안 하겠다는 건 아니고, 헷갈리는 걸 없애서 나중에 비슷한 논의를 했던 걸 다시 또 하지 않았으면 좋겠다는 의미였어요. 애매하게 정하게 되면 처음에는 여기에 들어가는 게 맞다고 생각했는데 시간이 지나 다시 생각해보니 여기에 들어가는 게 아닌 것 같은 경우가 생기고 계속 위치가 변할 거예요.

Peter: 디렉터리 구조에 대한 논의를 통일시키지 않으면 앞으로 계속 혼란이 생길 것 같긴 해요. 한 사람이 다른 생각을 가지고 있으면 원레포로 작업하는게 오히려 고통스러울 것 같아요. 추가로 유지 보수성 측면에서 앞으로 의논을 최대한 덜 하는 방향으로 이야기하고 싶어요. 하지만 큰 단위의 통일을 초반에 정하는 일은 현실적으로 힘들 것 같고 그건 발생할 때마다 논의를 해야할 것 같아요.

Yena: 논의 자체보다는 논의가 길어지는 게혼란스러워서 그렇다고 생각해요. 또 긴 논의를 통해 정했다고 하더라도 이걸 다른 사람에게 설명할 때 각 폴더와 파일별 긴 논의의 맥락을 설명해야 할 텐데 어떻게 해야 하나? 고민이 되고요. 그렇다면 거의 규칙이 없는 상태에 가까운 거 아닐까요?

Dylan: 저는 오히려 우리가 이렇게 많은 이야기를 통해 정하면 신규 입사자가 왔을 때 덜 혼란스러울 것 같아요. 우리가 대충 논의하고 넘어가면 그 사람도 왔을 때 대충 이해할 수 밖에 없을 것 같아요. 여러 번 논의하더라도 결론이 명확하게 나오면 그 사람이 와서 결론만 볼 것이기에 명확할 것이라 생각해요.

② Shared에 생성하고 이후에 Common으로 옮기기

Yena: 코드 짤 때마다, pr 올리기 전에 shared에 두는 게 맞을지 common에 두는 게 맞을지 항상 고민할 것 같은데 이게 계속 신경쓰여요. 그런 고민을 안 하고 싶어요.

Kooku: 그렇다면 공통의 파일과 폴더를 개발할 때 일단 shared로 하고, common으로 올릴 때는 pr로 따로 만들어 FE 4명이 전부 다 동의를 해야 옮길 수 있도록 하면 어떨까요? 그렇다면 그 때만 논의를 하면 되니 매번 개발할 때 고민해야 하는 걱정은 많이 없어질 것 같은데요.

Yena: 그러면 좀 괜찮을 것 같아요. 제가 개발 시 매번 고민할 것 같았던 부분과 논의가 많이 될 것 같다는 걱정이 없어질 것 같아요.

두 번째 논의 정리

1) shared

  • page 내부에 있는 것들 중 다른 도메인에서도 사용되는 것은 shared로 옮긴다.
  • 여러 도메인에서 사용되는 것들 (component, util, hook, …)

2) 기타

  • 서로의 생각이 달랐기에 shared와 common에 대한 큰 틀을 우선 정하고 common을 보수적으로 가져가기로 결정했어요.
  • 매번 고민하지 않도록 shared에 기본적으로 만들고, shared에서 common으로 파일을 옮기거나 추상화시킬 때 깊게 논의하고 고민해보자. 그러면 매번 고민해야 할 부분이 많이 없어질 것이다. (common으로 옮길 때는 4명의 approve가 있어야만 옮길 수 있다)

(3) 세 번째 논의: common에 들어갈 수 있는 것들, 비즈니스 로직에 대하여

두 번째 논의에서 우선 shared에 만들고 common으로 올릴때 pr로 만들어 다 같이 이야기 해보자 라고 했어요. pr을 올릴 때 common에 넣어야 할지 shared에 넣어야 할지에 대한 고민은 없앴지만 common과 shared의 기준이 명확히 정해지지 않았기에 근본적인 문제는 해결하지 못했어요. 기준이 명확하지 않기에 논의가 많아질 것이고, 시간이 지나면 논의에 힘과 시간을 쏟기 부담스러워져 shared에만 코드가 쌓일 것 같았어요. 문제를 제대로 해결하지 않는다면 앞으로의 많은 일들에 장기적으로 영향을 줄 것이기 때문에, 치열하게 논의하고 결정하는 과정이 필요했어요.

Yena: 예전에 읽은 함수형 프로그래밍 책에서 모든 코드를 액션과 계산 그리고 데이터 세 가지로 분리했어요. 액션은 사이드 이팩트가 있는 함수들, 계산은 순수함수예요. 기준이 명확했죠. 저희는 common과 shared를 단순 비즈니스 로직의 여부로 구분하면 좋을 것 같아요. 트랜잭션 아이디가 무엇인지, 페이 아이디가 무엇인지 이해가 필요한 함수들은 모두 shared에 들어가는거죠.

Kooku: 좋아요. 그러면 common과 shared 구분하기 쉬울 것 같아요.

Yena: 갑자기 든 궁금증이 production, beta, userId 같은 것들은 비즈니스 로직일까요?

Dylan: stage가 비즈니스 로직이냐 아니냐 같은 의문이 계속 튀어나올 것 같은데 이건 비즈니스 로직이고, 이건 아니다 라는걸 계속 적립시켜 나가야 할 것 같아요.

Peter: common의 기준이 비즈니스 로직이다 아니다도 중요하지만 자주 변하는 거, 변하지 않는 거 라고도 생각했어요. 비즈니스 로직이 있으면 자주 변하기 때문에 shared에 들어가고 자주 변하지 않는 것들은 common에 들어가게 되는데 그런 관점에서 production, beta, alpha는 변하지 않는 것들이라 common에 들어가도 괜찮지 않을까 생각이 들어요.

세 번째 논의 정리

1) common에 들어갈 수 있는 것

  • 비즈니스 로직이 포함되지 않은 함수
  • 외부 IO
  • 변하지 않는 것

2) common 내 폴더별 예시

  • util: 비즈니스 로직이 포함되지 않은 함수, web api
  • service: 라이브러리를 한 번 wrapping 한 것들
  • style: animation, reset css
  • hook: 비즈니스 로직이 포함되어 있지 않은 커스텀 훅
  • component: 당근 디자인시스템에 아직 구현되어 있지 않은 컴포넌트

3) 기타

  • production, beta, alpha, userid 같은 것들은 회사의 정책이고 자주 변하는 것이 아니기 때문에 common에 개념이 들어가도 됨

수많은 논의로 탄생한 폴더구조

팀원들과 수많은 논의를 거친 결과, 아래와 같은 폴더구조가 탄생했어요. 이 구조는 팀원들의 깊은 경험과 통찰을 반영한 결과물이지만, 팀원 누구도 이것이 정답이거나 최종 모습이라고 생각하지 않아요. 이 폴더 구조를 실제로 적용해본 후, 그 과정에서 느끼는 불편함이나 개선해야 할 부분이 있다면, 언제든지 다시 테이블에 앉아 논의하고 수정할 예정이에요.

대원칙

  1. 연관된 것은 모아두자 : 도메인이 같은 것들은 같은 폴더에 모아두자.
  2. 직관적인 구조를 만들자 : 특별한 패턴을 따르기보다 처음 본 사람도 쉽게 찾아갈 수 있도록 하자

기타원칙

  • 폴더명은 단수형
  • 파일명은 카멜케이스

폴더 규칙

common

  • 어느 도메인에도 속하지 않고, 비즈니스 로직이 없는 컴포넌트, 함수들을 포함해요.

common > service

  • 외부 라이브러리를 한 번 wrapping 한 것, 외부에 의존적인 것들을 모아둬요.
📦src
┣ 📂common
┃ ┣ 📂component
┃ ┣ 📂hook
┃ ┣ 📂service
┃ ┗ 📂util
┣ 📂page
┗ 📂shared

page

  • path를 따라 폴더를 구성해요
  • 하위 도메인과 path가 있는 경우 루트 폴더는 폴더 네이밍을 index로 가져가요.
  • 해당 페이지에서만 사용되는 컴포넌트나 함수들은 leaf 폴더에 component, hook, util 폴더를 만들어 모아둘 수 있어요.
📦src
┗ 📂page
┗ 📂payment
┣ 📂card
┃ ┗ 📂management -> https://daangnpay.com/payment/card/management
┣ 📂receipt
┗ 📂index -> https://daangnpay.com/payment
┣ 📂commponent
┣ 📂hook
┣ 📂util
┣ 📜PaymentPage.tsx
┗ 📜index.tsx
  • path의 1depth인 최상위 도메인에서 공유되는 컴포넌트와 함수들은 최상위 폴더에 shared 폴더를 만들어 모아둬요.
📦src
┗ 📂page
┗ 📂payment
┣ 📂shared
┃ ┣ 📂commponent
┃ ┣ 📂hook
┃ ┗ 📂util
┣ 📂card
┃ ┗ 📂management
┣ 📂receipt
┗ 📂index

shared

  • 여러 도메인에서 사용되며 비즈니스로직이 포함된 컴포넌트, 함수들을 포함해요.
  • component, hook, contant, store, storage 등이 포함돼요.
📦src
┣ 📂common
┣ 📂page
┗ 📂shared
┣ 📂api
┣ 📂component
┣ 📂constant
┣ 📂exception
┣ 📂hook
┣ 📂storage
┣ 📂store
┣ 📂style
┗ 📂util

shared > api

  • api 폴더구조는 url path를 따라가요.
  • api 폴더 최상위에는 instance.ts 에는 인스턴스와 초기화 함수가 들어있어요 (set interceptor, set header)
  • header set, interceptor와 같은 함수들은 util 폴더에 넣어요.
  • api 폴더 최하단에는 index.tstype.ts 로 타입을 파일로 분리해요. api response type이 큰 경우가 많고 한 파일에 api 함수들이 많으면 가독성이 떨어지기 때문이에요.
  • 외부 도메인은 external 폴더에 넣어요.
📦src
┣ 📂common
┣ 📂page
┗ 📂shared
┗ 📂api
┣ 📂api-gateway
┃ ┣ 📂payment
┃ ┃ ┗ 📂order-sheet -> https://api.daangnpay.com/payment/order-sheet
┃ ┃ ┣ 📜index.ts
┃ ┃ ┗ 📜type.ts
┃ ┣ 📜initialize.ts
┃ ┗ 📜instance.ts
┣ 📂external
┃ ┗ 📂juso
┃ ┣ 📂addr -> https://juso.com/addr/..
┃ ┃ ┣ 📜index.ts
┃ ┃ ┗ 📜type.ts
┃ ┣ 📜initialize.ts
┃ ┗ 📜instance.ts
┗ 📂util
┣ 📂interceptor
┃ ┣ 📜request.ts
┃ ┗ 📜response.ts
┗ 📜common.ts

글을 마치며

이처럼 저희는 문제가 생기면, 모두가 함께 논의하며 해결책을 찾아나가고 있어요. 각자 생각하는 바를 적극적으로 표현하며, 이 과정을 통해 더 잘, 제대로 일하기 위한 방향을 모색해 나가고 있죠.

물론, 항상 옳은 결정을 내리는 것은 아니에요. 하지만 잘못된 결정을 내리더라도 그것이 다음 번에 더 좋은 결정을 내리는 데 도움이 되는 값진 경험이라고 모두 생각하고 있고, 이것이 저희가 제품의 퀄리티와 사용자 경험을 위해 끊임없이 노력하는 방식이에요.

이처럼 당근페이 프론트엔드 팀은 계속 대화하며 성장하고 있는데요. 제품과 팀을 위해 문제를 제대로 해결하기 위해 치열하고 끈기 있게 논의하는 당근페이 팀원들의 열정, 여러분도 느끼셨다면 좋겠어요. 읽어주셔서 감사합니다.

--

--