나는 소분소분 서비스의 본격적인 프론트엔드 개발에 앞서 프로젝트 셋팅와 레이아웃 잡는 것을 맡아서 했다.
이전에 만들어 본 개인 프로젝트에서 쓴 리액트 + Typescript 에 적합한 Foundation 을 기반으로 하였다.
src 폴더 안쪽이 본격적으로 작업이 이루어지는 공간이라고 할 수 있다.
apis 는 http 요청들을 관리하는 폴더이다.
client.ts 파일에는 요청마다 필요한 기본값 설정을 담은 axios 인스턴스를 만들었다.
const axiosApi = () => {
const instance = axios.create(baseSettings)
return instance
}
const axiosAuthApi = () => {
const instance = axios.create({
...baseSettings,
headers: { SOBUNSOBUN: `${localStorage.getItem('sobunsobun')}` },
})
return instance
}
export const defaultInstance = axiosApi()
export const authInstance = axiosAuthApi()
axiosApi 는 사용자 인증이 필요 없는 요청을 보낼 때 쓰는 인스턴스이고,
axiosAuthApi 는 사용자 인증이 필요한 요청을 보낼 때 쓰는 인스턴스이다.
assets 은 svg 와 image 파일들을 모아둔 곳이다.
export { ReactComponent as SearchIcon } from './search.svg'
<SearchIcon className={styles.searchIcon} />
svg 파일들은 ReactComponent 방식으로 가져왔다. 그래야 class name 을 넣을 수 있고 svg의 색도 바꿀 수 있어서, 모양은 같은데 색만 다른 svg는 css 로 컨트롤 할 수 있게 된다.
또한 svg 용량이 작으면 자동으로 js 파일에 박아서 다운 받아주기 때문에 랜더링 시간이 단축되는 장점이 있다.
import fruit from 'assets/images/fruit.png'
export const IMAGE_PATH = {
fruit,
} as const
image는 경로를 변수로 지정하여 import 해서 React 컴포넌트에서 사용할 수 있도록 하였다.
컴포넌트 폴더에서는 공통으로 쓰는 컴포넌트 위주로 분리하였다.
hooks 폴더 안에는 Custom hook을 모아놨는데, debounce 나 modal 같이 여러곳에서 쓰는 훅 뿐만 아니라, http 요청을 할 때 사용했던 useQuery를 hooks 으로 감싼 것도 있다. 재사용의 목적도 있지만 http 요청이 필요한 페이지 컴포넌트 안의 코드량이 방대해짐을 막기 위함도 있다.
pages 폴더는 는 route에 따라 랜딩되는 페이지 컴포넌트들을 두었다.
참고로 내가 맡았던 게시글 생성 페이지에서만 쓰는 컴포넌트들은 src/components 의 컴포넌트로 분리하는 것이 아니라 Posting 폴더 안쪽에 두었다.
게시글 생성 페이지에서만 쓰기 때문에 page 와 함께 두는 것이 가독성과 유지보수 측면에서 좋다고 생각했기 때문이다.
recoil 폴더에서는 전역상태로 관리될 state를 모아두었다. 전역상태 관리를 위해 recoil을 썼기 때문에 recoil 이라고 명명하였고 만약 리덕스와 병행해서 쓰게 된다면 state 로 바꿔도 좋을 것 같다.
route 는 url 이 달라질 때 보여질 페이지 컴포넌트들을 볼 수 있다.
const RootRoute = () => {
return (
<div className={styles.app}>
<Routes>
<Route path='/' element={<Layout />}>
<Route path='' element={<Splash />} />
<Route path='intro' element={<Intro />} />
<Route path='login' element={<Login />} />
<Route path='local' element={<LocalAuth />} />
<Route path='signup' element={<Signup />} />
</Route>
</div>
)
}
export default RootRoute
8) styles
Style 은 SCSS로 작업하기로 했기 때문에 SCSS파일들이 있다.
base 폴더 안에는 reset 파일 같은 기본 설정 파일이 있고
constants 에는 color나 fonts, 미디어쿼리 구간과 같은 변수들을 모아놓았다.
mixins 는 flex 설정이나 font-size, 각종 수치들을 vw로 계산하여 반응형 웹 만들 때 도움을 주는 계산식을 모아 두었다.
9) types
types 는 타입들을 관리한다.
10) utils
utils 함수와 배열들을 모아놓은 폴더이다.
여러명이 협업하는 팀 프로젝트인 만큼 효율적인 버전관리와 일관성 있는 코딩 스타일을 갖추기 위해 깃 버전관리 방법, 커밋 컨벤션, 각종 린터 및 프리티어 설정, 코드 컨벤션을 정하였다.
1) 깃 버전관리 및 협업 방법
프론트엔드와 백엔드에서 공동으로 사용할 SobunSobun 이라는 organization 을 만들었다.
새롭게 작업하는 브랜치는 앞에 feat를 붙여서
feat/home
이런식으로 이름을 붙였다.
이미 생성된 페이지 혹은 컴포넌트를 수정하는 브랜치는 앞에 'fix' 을 붙였다.
기능 구현이 마무리 되면 dev로 풀리퀘를 날렸고, 팀원들이 검토해서 보완할 부분은 코멘트를 남기고 머지 해주는 식으로 진행하였다.
2) 린터 & 프리티어
eslint에서는 마지막 줄에 라인 추가, semi 여부, import 순서 등을 정하였다.
prettier에서는 줄바꿈 폭 길이, 탭너비, 세미콜론 사용 여부, 줄바꿈 방식 등을 설정하였다.
stylelint 에서는 css 순서, name pattern 등을 정하였다.
3) 커밋 컨벤션
커밋을 할때 간단하게 어떤 작업을 했는지 표시하였다.
4) 코드 컨벤션
5) CSS Module 사용
컴포넌트를 스타일링 할 때 CSS Module 이라는 기술을 사용해서 CSS 가 중첩되는 것을 방지하였다.
6) classnames 라이브러리 사용
classnames 를 이용하여 조건을 주어 클래스명을 넣고 빼도록 하였다.
초반에 프론트 개발자들과 stack 은 어떤것을 쓸지, 코딩 규칙은 어떻게 할지 논의하고 폴더 구조 등을 미리 잡아놔서 기획하고 디자인 시안이 나왔을 때 바로 개발에 착수할 수 있어서 시간을 단축할 수 있었다. 초반에 확실히하게 컨벤션과 폴더 구조를 잡고 기본 셋팅을 해보고 빠르게 가이드를 주는 주었던것이 협업하기 좋은 환경을 만들어 준 것이라고 생각한다.
이전에 수행했던 팀 프로젝트에서는 나서서 무언가 하기보다는 누가 하자는 대로 따라갔었는데, 이번에는 주도적으로 프로젝트 셋팅을 할 수 있어서 보람있었고 뿌듯했다.