기술스택 선정 - 100-hours-a-week/KTB4-3rd-wiki GitHub Wiki
| 언어 | 장점 | 단점 |
|---|---|---|
| JavaScript | - 별도로 TypeScript를 공부하지 않아도 됨 - 타입 작성이 없어 초기 개발 속도가 빠름 |
- 타입 체크가 없어 런타임 오류가 발생할 수 있음 - 유지보수 시 데이터 구조 파악이 어려울 수 있음 - 변수명이나 데이터 구조 변경 시 누락 가능성이 있음 - API 응답 형태를 코드만 보고 파악하기 어려움 |
| TypeScript | - 데이터 타입을 명확하게 정의할 수 있음 - 컴파일 단계에서 오류를 발견할 수 있음 - 자동완성 기능으로 DX 향상 - 코드 수정 시 연관된 오류를 쉽게 파악할 수 있음 - 협업 시 함수와 변수의 용도를 파악하기 쉬움 |
- 초기 타입 작성에 시간이 걸림 - 러닝커브가 있음 - 프로젝트 설정과 빌드 과정이 복잡해질 수 있음 - 타입 오류로 개발이 중단될 수 있음 |
- TypeScript
- TypeScript 사용 경험이 있어 러닝커브가 크지 않다.
- TypeScript의 장점이 단점보다 크다고 판단했다.
- 버전 업그레이드 과정에서 API 응답 형식 등이 변경되는 상황에 보다 안전하게 대응할 수 있다.
- 데이터 타입을 명확하게 정의하여 예상하지 못한 런타임 타입 오류를 최소화할 수 있다.
| 기술 | 특징 |
|---|---|
| React | - TypeScript와 호환성이 좋음 - React Native를 사용하여 모바일까지 확장 가능 - 단방향 데이터 흐름으로 상태 예측이 쉬움 |
| Vue | - 양방향 바인딩 지원 - React의 VDOM 채택 - HTML을 그대로 사용할 수 있어 러닝커브가 낮음 |
| Angular | - 프레임워크가 무거워 초기 로딩 속도는 느린 편 - 페이지 전환 속도는 빠른 편 - 양방향 바인딩 지원 - 정해진 템플릿 문법 사용 - 세 기술 중 러닝커브가 가장 높음 |
세 기술 모두 컴포넌트 기반 UI 구성을 지원한다.
- React
| 기준 | 선택 이유 |
|---|---|
| 단방향 데이터 흐름 | 단방향 데이터 흐름 구조를 기본으로 하기때문에 데이터 흐름을 예측하기 쉽다. |
| TypeScript 호환성 | JavaScript 기반 구조이기 때문에 TypeScript와 호환성이 좋다. |
| VDOM | 이전과 변경된 부분만 실제 DOM에 반영하며, 개발자가 DOM을 직접 조작하지 않아도 된다. |
| 러닝커브 | React 사용 경험이 많기 때문에 익숙하고 빠르게 개발할 수 있다. |
| 생태계 | 참고 문서와 예제가 많아 빠르게 개발해야 하는 환경에 적합하다. |
| 프레임워크 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Gatsby | 정적 사이트 생성에 적합 | 정적 사이트 생성만 지원하여 지도, 채팅 등 동적인 페이지가 많은 서비스에는 적합하지 않음 | 제외 |
| Next.js | - CSR, SSR, SSG, ISR 등 렌더링 방식 선택 가능 - SEO에 유리함 - 라우팅, 이미지 최적화, 코드 분할 등이 통합됨 - 생태계와 자료가 풍부함 |
- Server Component, 캐싱, 렌더링 방식 등 학습할 내용이 많음 - 단순 SPA보다 구조가 복잡함 - 잘못된 렌더링 방식 선택으로 성능 저하가 발생할 수 있음 |
선택 |
| Remix | - 서버 중심 데이터 처리와 폼 제출에 강함 - 중첩 라우팅과 에러 처리 구조가 체계적임 - 웹 표준과 점진적 향상에 유리함 - 동적인 서비스와 데이터 변경 흐름에 적합함 |
- Next.js보다 국내 자료와 사용 사례가 적을 수 있음 - Remix만의 라우팅과 데이터 로딩 방식을 학습해야 함 |
제외 |
| React + Vite | - 구조가 단순함 - 개발 속도가 빠름 - SPA와 실시간 지도·매칭 UI 구현에 적합함 - 정적 파일로 배포하기 쉬움 |
- SSR, SSG, 라우팅, SEO 등을 별도로 구성해야 함 - 초기 HTML 기반 SEO에 불리할 수 있음 |
제외 |
| 기준 | 선택 이유 |
|---|---|
| SEO 최적화 | 매칭과 커뮤니티 구조의 서비스이므로 사용자 유입이 중요하다. SEO 최적화를 통해 서비스 노출과 사용자 유입을 높일 수 있다. |
| 유연한 렌더링 방식 | 지도나 채팅처럼 동적이고 사용자별 데이터가 다른 페이지는 CSR로, 커뮤니티 게시글처럼 정적인 데이터는 SSR로 구현할 수 있다. |
| 통합 기능 | 파일 기반 라우팅, next/image 이미지 최적화, 라우트 단위 코드 분할 등을 기본으로 제공하여 설정 부담을 줄일 수 있다. |
| 번들사이즈 축소 | 서버 컴포넌트는 클라이언트 번들에 포함되지 않아 번들 사이즈 축소에 유리하다. |
- 서버컴포넌트와 클라이언트 컴포넌트를 나눠 하이브리드 렌더링 방식으로 진행할 것 같다.
- 기본적으로 서버컴포넌트를 사용하고, 사용자 상호작용이나 브라우저 api가 필요한 곳은 클라이언트 컴포넌트를 사용 할 예정.
- 클라이언트 컴포넌트의 범위를 최소화하여 hydration 시간을 단축해 FCP와 TTL의 간격을 줄이도록 할 예정.
- 커뮤니티 게시글처럼 꼭 실시간 데이터가 필요하지 않은것들은 Ondemand ISR 방식을 사용해도 괜찮을 것 같다.
Ondemand ISR : 캐시된 정적 페이지를 제공하다가 해당 데이터 변경이 일어나면 관련 캐시를 무효화하고 이후 요청부터는 변경된 데이터로 제공하는 방식
공식문서 - on-demand-revalidation-with-revalidatepath
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Base UI | - 접근성, 키보드 조작, 상태 관리 등 기본 동작 제공 - 기본 스타일이 없어 자유롭게 커스터마이징 가능 - Tailwind CSS, CSS Modules, 일반 CSS 등과 함께 사용 가능 - 지속적인 업데이트와 유지보수 |
- 기본 스타일을 직접 구현해야 함 - 디자인 토큰과 컴포넌트 규칙을 별도로 정해야 함 - 빠른 화면 구성에는 시간이 오래 걸릴 수 있음 - 프로젝트 규모가 커지면 자체 디자인 시스템 관리 필요 |
일부 사용 |
| Material UI | 기본적인 UI 컴포넌트를 빠르게 구성 가능 | Material Design 기반이므로 자체 디자인을 적용하려면 많은 커스터마이징이 필요함 | 제외 |
| 직접 구현 | - 프로젝트 디자인과 브랜드에 맞게 제한 없이 구현 가능 - 서비스 특화 UI를 원하는 방식으로 설계 가능 - 외부 라이브러리 의존성 및 버전 충돌 회피 - 컴포넌트 구조와 동작을 완전히 제어 가능 |
- 초기 개발 시간 증가 - 접근성, 반응형, 터치 동작, 애니메이션 등을 직접 처리해야 함 - 상태와 예외 상황을 직접 설계하고 테스트해야 함 - 자체 디자인 시스템 관리 필요 |
일부 사용 |
- Base ui사용 또는 직접 구현하기
- 기본 스타일이 없어서 자유롭게 tailwind를 사용해서 커스텀이 가능하다.
- 제공되는 컴포넌트 종류가 충분하다고 판단하였다.
- 접근성, 키보드 조작, 상태 관리 등 기본 동작을 제공해줘 효율적으로 개발이 가능하다
- 지속적인 업데이트와 유지보수가 이루어진다.
- shadcn이 radix대신 baseui를 기본값으로 전환
| 라이브러리 | 장점 | 단점 |
|---|---|---|
| lucide | - 1600+개의 아이콘 - figma 플러그인 |
라이브러리 의존성 생김 |
- lucide Icon 라이브러리를 사용
- 라이브러리에 없는 아이콘은 직접 svg 따와서 사용하는것으로 보완
- 페이지 구현에 필요한 아이콘이 모두 제공되어있다.
- figma 플러그인이 있어서 화면과 통일성이 좋다
| 기술 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Tailwind CSS | - 유틸리티 클래스를 조합해 빠른 UI 구현 가능 - 반응형, hover, focus 등 상태별 스타일 적용이 쉬움 - 디자인 토큰과 간격 체계 유지에 유리 - 사용한 스타일만 빌드에 포함 - 별도 CSS 파일 작성 부담 감소 |
- JSX의 className이 길어질 수 있음- Tailwind 문법 학습 필요 - 동적 클래스 사용 시 빌드 과정에서 인식되지 않을 수 있음 |
결정 |
| CSS / SCSS | - 표준 CSS 기반이라 학습 부담이 적음 - 스타일을 세밀하게 제어 가능 - SCSS의 변수, 중첩, mixin 사용 가능 - 특정 라이브러리 의존성이 낮음 |
- 전역 스타일로 인한 클래스명 충돌 가능 - 프로젝트 규모가 커질수록 스타일 관리가 복잡해짐 - 반응형, 상태별 스타일, 디자인 토큰을 직접 관리해야 함 - CSS 번들이 커질 수 있음 |
제외 |
| CSS Modules | - 클래스명을 컴포넌트 단위로 지역 범위화 - 클래스명 충돌 감소 - 컴포넌트와 스타일을 함께 관리하기 쉬움 - CSS와 SCSS 모두 사용 가능 |
- 클래스 조합과 상태별 스타일을 직접 관리해야 함 - 조건부 스타일 코드가 길어질 수 있음 - 디자인 토큰과 컴포넌트 규칙을 직접 정해야 함 - 유틸리티 클래스를 제공하지 않음 |
제외 |
- Tailwind CSS
- Tailwind CSS는 다른 ui 라이브러리와 호환성이 좋다
- jsx안에서 스타일 수정이 가능해 유지보수측면에서 좋다
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Zustand | - 보일러플레이트가 적음 - 번들 사이즈가 작음 - 러닝커브가 낮음 - 사용 경험이 있음 - 생태계가 넓음 |
- 프로젝트 규모가 커지면 Store 구조를 직접 설계해야 함 - Middleware 추가 시 번들 크기가 증가할 수 있음 |
선택 |
| Redux | - 전역 상태를 하나의 Store에서 관리할 수 있어 상태의 출처가 명확 - 기능별 Slice로 Store를 나눌 수 있어 프로젝트 규모가 커져도 일관된 구조를 유지하기 쉬움 |
- Zustand에 비해 개념과 설정해야 할 코드가 많아 초기 러닝커브가 높음 - 작은 규모의 상태를 관리할 때에도 Store, Action, Reducer, Slice 등을 구성해야 하므로 과한 설계가 될 수 있음 - 새로고침 후 상태 유지를 위해서는 별도의 저장 로직이나 라이브러리 설정이 필요 |
제외 |
| Recoil | - Atom 단위로 상태를 세분화 가능 - React 컴포넌트와 자연스럽게 연결 가능 |
- 2025년 1월부터 저장소가 Archived 상태 - 최신 React와의 호환성 및 유지보수가 어려울 수 있음 |
제외 |
| Jotai | - Atom 단위의 간단한 상태 관리 - 필요한 Atom만 구독하여 불필요한 리렌더링 감소 - 기본 기능과 유틸리티가 분리됨 |
- Atom이 많아지면 상태 간 의존성 파악이 어려울 수 있음 - 대규모 프로젝트에서는 상태 구조를 별도로 설계해야 함 - 고급 기능 사용 시 추가 학습 필요 |
제외 |
- zustand
- 매칭탭이나 커뮤니티 등 유저가 등록을 할때 여러 페이지에서 사용자 입력을 받는 경우가 많다. 이때 전역상태관리가 필요하다.
- 예를 들어, 택시팟 매칭 등록에서 출발지/목적지를 선택할 때 첫 화면에서 지정한 출발지 값이 위치 검색 페이지의 출발지 인풋에 있어야한다.
- 반대로 위치 검색 페이지에서 뒤로가기를 눌렀을 때도, 유저가 지정한 출발지 값의 상태에 맞게 지도 위치 및 값이 나타나야한다.
- 로그인 유도 모달같은 전역 모달이나 api 요청 실패같은 전역 토스트 상태도 zustand를 통해 관리 가능하다.
- Redux와 비교해 보일러플레이트 코드가 적고, 간단한 API로 상태를 관리할 수 있다.
- 별도의 Provider나 reducer 없이 사용할 수 있어 러닝커브가 낮으며, 기존 사용 경험을 활용할 수 있다.
- selector를 통해 필요한 상태만 구독해서 불필요한 리렌더링을 줄일 수 있다.
- 여러 페이지에서 사용자 입력을 이어서 받는 흐름이 많기 때문에
persist미들웨어를 활용할 수 있다. - jotai는 세밀한 상태관리의 필요성을 아직 느끼지 못해 제외.
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| TanStack Query | - api 요청 상태관리 - 캐싱과 중복 요청 제거 - stale 데이터 관리 - 백그라운드 refetch - 페이지네이션, 무한스크롤 - 낙관적 업데이트 - SSR hydration |
- 기능이 많아 학습량이 있음 - 캐시 정책과 Query Key 설계 필요 - 런타임 및 캐시 관리 코드 추가 |
선택 |
| SWR | - API가 단순하고 사용하기 쉬움 - 자동 재검증과 캐싱 제공 - Tree-shaking과 Path import 지원 - 번들 및 런타임 부담이 비교적 적음 |
- TanStack Query보다 캐시와 Mutation 기능이 단순함 - 복잡한 서버 상태 흐름은 직접 구현해야 할 수 있음 |
제외 |
TanStack Query
- mutation이 자주 일어나고 서버간의 관계와 변경 흐름이 복잡함.
- 예를 들어 유저가 채팅방에 입장하면, 다음 서버 상태들도 변경되어야합니다.
- 바텀시트 목록의 참여인원 수 / 게시글 상세의 참여인원 수 / 유저의 채팅방 목록
- TanStack Query는 query key의 계층 구조를 기반으로 특정 데이터만 무효화할 수 있기 때문에 이런 구조에 적합하다고 판단했습니다.
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Zod | - TypeScript 타입과 런타임 데이터 검증을 함께 관리 가능 - API 응답과 Form 입력값 검증에 활용 가능 - TypeScript 타입 자동 추론 가능 - Zod Mini 사용 시 번들 크기 감소 가능 |
- 클라이언트 사용 시 검증 코드가 번들에 포함됨 - 복잡한 Schema가 많아지면 JavaScript 크기가 증가할 수 있음 |
선택 |
Zod 사용
-
typescrip만으로는 런타임 데이터 검증을 수행할 수 없기 때문이다.
-
서버가 잘못된 데이터를 보냈을때, 검증을 수행하지 못하면 예상하지 못한 에러나, 의도하지 않은 결과가 나올 수 있다.
-
사용자 입력을 받을때도, zod를 통해 폼 검증 코드를 하나의 스키마에 모을 수 있습니다.
-
zod를 사용하지 않으면, 타입과 검증 규칙을 별도로 작성해야합니다. 이로 인해 타입과 검증 규칙이 서로 달라질 수 있는 위험이 있습니다.
-
다만, 큰 데이터의 경우는 매번 검증하면 파싱 비용으로 성능 저하가 발생할 수 있기 떄문에, 다음 방법들을 고려하겠습니다.
- API 응답을 처음 받는 경계에서 한 번만 검증하고 그 결과 재사용
- 필요한 필드만 부분 검증
- 서버 검증
- 전용 validator 사용
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| React Hook Form | - Form 상태 관리와 입력값 검증을 간단하게 처리 가능 - 작은 크기와 적은 의존성 - 불필요한 Form 전체 리렌더링 감소 - SEED UI와 연동하기 좋음 |
- 복잡한 Form에서는 추가 학습 필요 - Zod Resolver 사용 시 추가 JavaScript 포함 - Form 상태와 서버 상태를 별도로 관리해야 함 |
사용 |
React Hook Form 사용
- 직접 Form 검증 hook을 작성하지 않고도 간편하게 구현 가능하다.
- 크기가 작아서 번들 부담도 적다
- form의 불필요한 리렌더링을 막아준다.
- 아래와같은 인풋을 여러개 받는 form 화면이 서비스에 꽤 많아서 활용도가 높다.
| 라이브러리 | 장점 | 단점 | 결정 |
|---|---|---|---|
| Storybook | - 컴포넌트를 페이지와 분리해 개발 및 테스트 가능 - 공통 컴포넌트의 상태와 Variant 문서화에 적합 - 디자이너와 개발자가 UI를 확인하기 쉬움 |
- Story 작성과 설정에 추가 시간 필요 - 의존성과 빌드 시간 증가 - 팀 규모가 작거나 컴포넌트가 적으면 활용도가 낮을 수 있음 - 실제 페이지와 Storybook 환경이 달라 별도 검증 필요 |
사용 |
storybook 사용
- 디자인시스템 관리가 용이하다.
- 당근의 디자인시스템 Seed를 사용하긴해도 커스텀이나 자체 컴포넌트를 스토리북으로 관리하는게 장기적으로 유리할 것이라고 생각했다.
- 컴포넌트를 따로 떼서 테스트할 수 있다는 점이 좋다고 생각했다.
- 협업을 할때 스토리북 배포를 통해 컴포넌트 단위 피드백 및 커뮤니케이션을 할수있어서 좋았다.
| 사용처 | 선택한 라이브러리 |
|---|---|
| UI | Base UI |
| Icon | lucide Icon 라이브러리 |
| Style | Tailwind CSS |
| 클라이언트 상태 관리 | zustand |
| 서버 상태 관리 | tanstack query |
| 런타임 타입 검사 | zod |
| Form | react hook form |
| 컴포넌트 문서화 | storybook |
- oxlint
- oxfmt
-
Oxlint는 ESLint보다 50~100배 빠르다고함 Oxlint 공식문서
-
typescript와 호환성이 좋음
-
865개 이상의 규칙을 포함하고 있으며 , 대부분의 팀이 이미 사용하고 있는 린터 플러그인을 포괄하는 기능을 제공
-
Oxfmt는 Prettier보다 약 30배, Biome보다 약 2배 빠르다고함 Oxfmt 공식문서
-
Prettier의 JavaScript 및 TypeScript 적합성 테스트를 100% 통과
- Naver Map
- Kakao Map
2026.09.02 pl미팅 피드백 기반 추가학습 2026.09.03 pl미팅 피드백 기반 추가학습 2026.09.04 pl미팅 피드백 기반 추가학습