WIP - 논의 자료 준비 중입니다 👻
제안 기술스타일링 도구 → Tailwind가 제일 좋아요UI Framework → (무엇이든) 사용해요.서버 상태 관리 → 직접 하기보단 React-query로 관리해요메타 프레임워크 → Next.js를 사용하자패키지 매니저 → berry, pnpm 중 하나를 사용해요단위 테스트 작성 → 재사용되거나 복잡한 코드에는 작성하자제안 목표최적화: re-render보다 slow render 먼저 최적화해요개발 방법론: 작게 시작해서 빠르게 개발해요코드가 스스로 설명하지 못 하는 내용은 주석으로 설명해요브랜치(PR) 머지 전략 → Squash로 하자
기타
(놓치고 있던 것)
- 200 외의 응답이 온 경우:
- axios는 알아서 해주므로 괜찮다.
- fetch는 reject하지 않으므로 직접 ok 체크 후 reject 해줘야 한다.
- 요청 취소하려는 경우:
- AbortController 인스턴스 생성 및 signal option을 fetch 호출 시 전달해야 한다.
- React-query 사용 시에
signal
입력이 있으니 전달할 수 있다. (AbortController는 알아서 만들어주는 듯?) - signal 전달을 안 하면 React-query에서
queryClient.cancelQueries(...)
했을 때 API 요청 자체는 취소되지 않고 무시되는 식으로 동작한다.
- React-query의 tracked query
- useQuery 훅이 반환하는 객체의 수 많은 프로퍼티 중, 구조 분할 할당으로 가져온 값이 변경됐을 때만 re-render를 트리거하는 기능으로, 기본 활성화되어 있다.
- e.g.
isFetching
도 가져오는 경우, 뭘 가져올 때마다 re-render가 2번씩 된다. status: success, isFetching: true
,status: success, isFetching: false
- isFetching 등을 가져올 땐 조심하는 게 좋겠다.
- Suspense, ErrorBoundary로 로딩 상태를 분리하면 더 선언적일 것 같다.
- ErrorBoundary의 경우 천천히 도입해도 괜찮을 것 같다.
제안 기술
스타일링 도구 → Tailwind가 제일 좋아요
- Utility-first 계열은 Tailwind 외에도 있어요.
- Tailwind는 현재 스타일링 도구 중 styled-components와 함께 1위에요.
- sc가 17년도에 본격적으로 활성화, tailwind가 20년도에 본격적으로 활성화 됐다는 점을 고려하면 Tailwind가 상승세로 봤을 때 1위라고 할 수 있어요. (22년부터 폭발적으로 성장)

- Tailwind의 철학
- (잘 모르겠어요 ㅋ)
- styled-components, scss+BEM이 별로인 이유
- 단위를 만들지 않는 게 선택 사항이 아니에요.
- 별 거 아닌 애도 항상 이름을 지어줘야 해요.
- 이름이 있기 때문에 대충 지으면 오해의 여지가 생겨요.
- 중복 코드를 제거하려면 ‘덮어 씌우기’ 코드가 들어가는데, 특정 단위의 전체 스타일을 보기 위해선 각 ‘덮어 씌우기’ 코드를 한 번에 봐야 해요. (3단계 이상 들어가게 되면..흠…)
- Tailwind가 좋은 이유
- CSS 규칙이 짧아서 읽고 쓰기가 쉬워요.
- 단위를 만들지 않아도 돼요.
- 부모-자식 관계의 단위에서 스타일을 배치하는 고민을 할 때 원래 위치에서 벗어나지 않고 곧장 할 수 있어요.
- 설계 결정을 늦게 할 수 있어요. 단순 스타일 나열 식으로 스타일 단위의 설계가 없어도 되기 때문에요.
- 2차팀 프로젝트 경험
- 런타임에 실행되는 JS가 없어, 성능 저하가 없어요.
- 런타임 성능 저하가 없는 다른 유명 도구로는 https://vanilla-extract.style 가 있어요.
- Tailwind와는 Utility-first가 아니라는 점에서 달라요.
- Pure CSS는 Tailwind에 비해 특정 Style을 쓰거나 읽을 때 긴 문자열을 읽고 써야 해요.
- Tailwind를 사용하면 스타일 입력 시간이 체감 상 2배, 3배 빨라져요.
- 특히 미디어 쿼리나 상태 조건 부 스타일 입력이 빨라져요.
- 아주 가벼운 마음으로 작은 변화를 줄 수 있어요.
- 빠르게 쓸 수 있으니 의욕이 나요.
- 초기 퍼블리싱에서 마크업과 스타일을 계속 바꿔갈 때 특히 유리해요.
- 긴 스타일(flex + padding + gap + border + backgroundColor + color + hover 등)을 입력하는 시간이 압도적으로 빨라요.
- 매번 스타일드 컴포넌트를 정의하지 않아도 돼요.
- 다른 파일 혹은 저 아래에 정의한 후 계속 왔다 갔다 하지 않아도 돼요.
- 좋은 단위로 생성하고, 이름을 지어주지 않아도 돼요.
- Tailwind는 분리되지 않은 상태로 있어도 자연스럽지만, styled-components는 이상하게 분리되어 있는 경우 부자연스러워요.
- 기본 프리셋 값이 매우 좋아요.
- 기본 크기가 4px (0.25rem) 단위로 정의되어 있는데 매우 좋아요.
- (ex)
p-2 = padding: 0.5rem;
- 기본 컬러셋이 매우 좋아요.
- (ex)
text-orange-500
,text-green-500
- 응집도 있는 스타일 단위 정의에도 문제가 없어요.
- 함께 다니는 스타일은 커스텀 클래스를 작성하면 크게 줄어들어요.
- (ex)
.btn
,.btn-primary
- 당연히, 컴포넌트로 뺄 수도 있어요.
- (ex)
<Button>
,<Button variant="primary">
- 쓰기 최적화된 도구가 맞지만 유독 Tailwind여서 읽기 어렵다는 이슈는 없었어요.
- 어떤 도구를 쓰더라도, 남의 스타일을 고치려면 읽어야 하는 css규모는 비슷해요.
- Raw HTML Tag가 같이 보이기 때문에 의도 파악이 크게 어렵지 않아요.
- (ex)
<li className="flex flex-col gap-2 p-2 border-2 ...">
을 보면 List 컨테이너인 게 쉽게 보여요. - Tailwind의 축약어는 오히려 전체 스타일을 표현하는데 드는 코드가 줄어들어요.
- styled-components 등은 full css를 표현해야 하기 때문이에요.
- (ex)
"flex flex-col"
vs"display: flex; flex-direction: column;"
- Tailwind는 template string 등으로 동적 생성이 불가하다보니, 스타일을 생성하는 코드보다 스타일 문자열이 코드에 그대로 보존되어서, 오히려 머릿 속에서 컴파일하지 않아도 돼요. (대신 이렇게 하면 코드가 좀 길어질 수 있어요.)
- e.g. 텍스트 컬러 분기 예시 (TBD)
UI Framework → (무엇이든) 사용해요.
- 사용하지 않는 것보다 퍼블리싱 속도가 최소 2배는 더 나올 거라고 생각해요.
- 처음부터 만드는 것보다, 있는 걸 수정하는 게 훨씬 쉽기 때문이에요.
- 무엇을 할지도 더 구체적으로 알 수 있어요.
- 이미 일관성 있게 변수가 구성되어서 일관성 있게 커스텀할 수 있어요.
- Tailwind와 사용했을 때 Tailwind 기반의 UI Framework를 사용하지 않아도 돼요.
- 하지만 Tailwind class의 재사용이 크게 감소해서 효율이 안 좋을 거에요.
- 주요 Tailwind 기반 UI Frameworks:
- (Pro 버전을 판매하는 framework가 많은데 이것들은 제외했어요)
- Shadcn
- 미니멀, 깔끔한 인상을 줄 수 있다. 캐주얼 하지 않고 포멀하다.
- 단순한 스타일만 있는 게 아닌 기능도 포함하고 있다.
- e.g. Sonner → Noti 스택을 스스로 관리한다.
- e.g. Dropdown → on/off 상태를 스스로 관리한다.
- Daisy UI
- 캐주얼하고 가벼운 디자인이다. 약간 저 퀄 느낌이 날 수 있다.
- 단순 스타일 위주로 제공된다. 기능은 대개 직접 만들어야 한다.
서버 상태 관리 → 직접 하기보단 React-query로 관리해요
- query.gg 페이지에서 튜토리얼 제공해요.
- React-query의 의도
- Data fetching은 심플한데, 비동기 상태 관리는 복잡해요
- React-query는 data fetcing 라이브러리가 아니라 비동기 상태 관리자에요.
- Camera API 같은 비동기 상태에도 사용할 수 있어요.
- React-query의 장점
- React-query를 쓰면 고급 기능들이 기본 제공돼요.
- 캐싱, 디바운싱, 요청 취소, 재요청, 기본 상태 처리 등이 있고 원하면 사용할 수 있어요.
invalidateQueries
로 기존 서버 상태를 초기화하면 자동 re-fetch를 할 수 있어요.- 이것들을 맛 보면 되돌아갈 수 없다고 하는데 동의해요
- React-query를 쓰지 않고 직접 관리한다면 발생하는 문제점
- 직접 data를 가져온다면, data, loading, error를 상태로 갖고 있어야 해요.
- 오류/정상 응답에 따라 React State를 변경해줘야 해요.
- 오류 상태일 때 데이터 상태를 비우고, 정상 상태일 때는 오류 상태를 비워야 해요.
- useEffect에서 query하는 경우는 경쟁 상태가 발생한다.
- state, props가 바뀌는 순서와 비동기 데이터가 도착하는 순서는 다를 수 있어요.
- state, props는 새로운 id를 갖고, 비동기 데이터는 예전 id를 갖는 게 마지막 응답하면, 서로 불일치가 발생해요.
- 만약 데이터가 도착하기 전에 state, props 변경 시에는 이전 fetch를 취소해야 해요.
- 선언적인 Suspense를 사용하려면 직접 throw를 하는 등 연동이 필요해요.
메타 프레임워크 → Next.js를 사용하자
- 일단 Next는 저도 잘 몰라요..!
- 시장 상황
- React 다운로드의 1/4이 Next에요 (2천만 vs 500만)
- React 공식 문서에서도 메타 프레임워크로 시작하라고 추천해요
- 국내 JD에서는 대부분 Remix보다 Next를 사용해요

- Next 프로젝트에서 Next를 몰라도 React를 그대로 사용할 수 있어요.
- Next의 기능
- SSR은 ReactDOM.renderToString 후 ReactDOM.hydrate라는 과정을 거쳐요.
- 첫 화면을 renderToString으로 한다고 해도, 두 번째 화면부터는 CSR로 해야 돼요.
- CSR을 해야 할 때는 Next에서 Props를 JSON으로 내려줘요.
- 서버단에서 데이터를 가져와 미리 렌더링된 화면을 제공할 수 있어요.
- 페이지 별 미리보기 화면을 제공하는 open graph 등의 정보를 제공할 수 있어요.
- 페이지 별 검색 엔진 유입을 위해 JS 없이도 정보를 제공할 수 있어요.
- 이 때 꼭 SSR 뿐 아니라 SSG, ISR도 사용할 수 있어요.
- 이 부분이 아주 멋지다고 생각해요.
- React Server Component를 지원해요
- 자유로운 서버 리소스 접근
- 서버 컴포넌트는 서버에서 동작하기 때문에 데이터베이스, 파일 시스템 그리고 인터널 서비스 같은 서버 사이드 데이터 소스에 직접 접근할 수 있습니다.
Next는 기본적으로 React를 SSR을 하기 위한 도구에요. (펼치면 SSR 동작 설명)
패키지 매니저 → berry, pnpm 중 하나를 사용해요
- yarn berry 혹은 pnpm을 도입한다면 큰 러닝 커브 없이 설치 속도 개선을 얻을 수 있어요.
- 설치 속도 개선
- 벤치마크
- Yarn Berry의 경우 Zero Install을 통해 압축된 의존성을 다운로드하는 것으로 설치를 대체해요
- Next는 Yarn Berry Zero Install를 지원하지 않아요
- pnpm의 경우 전역 캐시에서 1회만 설치한 후 각 프로젝트의 node_modules에는 하드링크만 배포해요.
- 그래서 전역 캐시에 이미 있는 패키지를 설치할 때 최적이에요.
- 하드 링크란 리눅스/유닉스에서 하나의 물리적인 파일만 만들고 여러 곳에서 해당 파일을 공유하는 개념이에요.
- npm도 전역 캐시 폴더가 있어요. 대신 npm은 압축된 상태로 보관한 후 이를 설치 시마다 매번 압축해제-복사해요.
- 전체 비교 요약
단위 테스트 작성 → 재사용되거나 복잡한 코드에는 작성하자
- 테스트의 장점
- 테스트를 실행하는 것은 개발 서버를 키는 것만큼 쉽다. (
pnpm test
) - 첫 PR 이후에는 기존 동작의 무결성을 회귀 테스트가 알아서 체크해준다.
- 테스트는 코드의 사용 사례에 대한 문서화 도구이며 유효성 검사가 셀프로 된다. (vs 주석)
- 단위 테스트는 실행 속도가 빠르다.
- watch 모드로 실행한다면 매 코드 변경 시마다 기존 동작이 깨졌는지 확인할 수 있다.
- 특히 watch 옵션을 수정된 파일로 한정한다면 대부분 즉시 실행 완료된다.
- 테스트 작성 대상
- 테스트 가치가 높은 코드를 테스트해 수동 테스트 비용을 줄인다.
- 재사용되는 코드
- e.g. 공통 회원 상태, 스토리지 저장, 공통 컴포넌트의 뷰
- 재사용되지 않더라도 복잡한 코드
- 혼자서 복잡한 코드는 내부 로직 변경 시마다 매번 테스트하게 된다.
- 외부와 복잡하게 얽힌 코드는 외부 코드 변경 시마다 매번 테스트하게 된다.
- 테스트 비 대상
- 테스트 비용이 낮은 코드
- 동작이 자주 바뀌는 코드
- 테스트 코드도 함께 유지보수해야 하므로, 동작이 바뀌면 테스트도 유지보수해야 하므로 오히려 속도에 저하가 온다.
- 테스트 작성 내용
- 해당 코드의 사용 방법을 작성한다.
- 각 사용 사례와 의도한 결과를 명세한다. (happy path)
- 조금 더 쓴다면… 사용하면 안 되는 사례와 실패하는 결과를 명세한다. (unhappy path)
- 뷰가 없는 Custom Hook → state 변경 함수 호출 후 state 변화 관찰
- 뷰만 있는 Presentational Component → event 발생 후 view 변화 관찰
- 기본적으로 스타일에 대한 테스트는 어렵다.
- (화면이 실제로 어떻게 렌더링 되는지)
- 단위 테스트에서는 JSDOM을 사용하므로 Text, Element로 검증한다.
- 화면에 해당 Text가 있는지, 해당 버튼이 있는지 등
- 한계:
- 스타일을 검증하는 것은 한계가 있다.
- 화면은 자주 바뀔 수 있다. 이 경우 테스트 코드도 변경해줘야 해서 일이 더 많아진다.
제안 목표
최적화: re-render보다 slow render 먼저 최적화해요
- re-render가 여러 번 일어나는 것을 걱정하기 전에 slow-render가 되는 것을 걱정해봐요
개발 방법론: 작게 시작해서 빠르게 개발해요
- (TBD)
- 참고 자료
코드가 스스로 설명하지 못 하는 내용은 주석으로 설명해요
(TBD)
브랜치(PR) 머지 전략 → Squash로 하자
- 병합은 Squash로 한다.
- 장점:
- git history가 선형적이라는 rebase의 장점
- 커밋이 하나여서 전체 그림을 보기 쉽다는 squash의 장점
- 단점: git lens로 각 Line 별 변경의 이유를 볼 때 commit message가 PR 제목이므로 명확히 이해하기 어렵다.
- Merge Conflict는 PR 작성자가 한다.
git pull --rebase origin main
로 최신 main 브랜치 커밋을 리베이스로 받아오고,- 충돌이 있으면 해결 후 commit하고 PR을 생성한다.
- 예시
- (TBD)
- 참고 자료