https://ghoon99.tistory.com/92
지난 글에서는 내가 직접 작성해본 깃 관련 컨벤션과 폴더구조에 대한 내용을 다뤘다.
이어서 코딩스타일 가이드, 그리고 이것들을 바탕으로 한 템플릿 레포지토리를 만들어보면서 생각난 것들을 간략하게나마 기록해본다.
코딩 스타일 가이드
https://github.com/airbnb/javascript
https://ui.toast.com/fe-guide/ko_CODING-CONVENTION
https://github.com/banksalad/styleguide
https://airbnb.io/javascript/react/
https://google.github.io/styleguide/
코드 스타일
https://ko.javascript.info/coding-style
이곳에 설명이 아주 잘 되어있다. 또 이미 잘 만들어진 참고 자료들이 많았다. 큰 규모의 규칙부터 사소한 것 까지 정해놓은 것도 있다.
위의 내용들을 참고하면서, 또 내가 프로젝트를 하면서 늘 걸렸던 것들에 대해서 규칙을 정하였다. 일단 생각나는 최소한의 규칙만 정해두고 점점 생각나는 대로 추가하는 방식을 택했다. 규칙을 정하면서 기억났던 것을 남겨본다. 특히 리액트 코드를 작성할 때 코드 스타일을 많이 정리해보았다.
- Type, Array<number> or number[]
https://stackoverflow.com/questions/36842158/arraytype-vs-type-in-typescript/36843084#36843084
코드를 작성하다 순간적인 호기심이 들었다. 뭔가 사소하지만 정하고 가면 좋을 듯 했다. 나는 number[] 쪽이 더 복잡하지도 않고
읽기 좋은 방식이라 생각한다. readonly 키워드를 붙일 수 있는것도..
Array<number|string> , (number|string)[] 은 후자가 더 귀찮아 보이지만 저런 타입은 다시 묶어 하나로 만들지 않을까..?
(ex. type Tag = number|string 후 Tag[] )
그래서 number[] 로 맞추기로 함..!
React Component 작성하는 방식
- props type type 이냐 interface 냐?
사실 무엇을 쓰던가는 큰 상관이 없고, 다만 둘이 어떤 차이점을 가지는지 알 필요는 있다.
나는 (위에서 보다시피 & 보단 extends..타입간의 합성) 공통 UI 컴포넌트의 type (다양한 타입이 필요하며 조합도 해야함)
interface [Component]Props 형태로, 보통적인 컴포넌트는 type Props 로 작성할 예정이다.
요즘은 타입스크립트를 자주 사용하다보니 타입을 부여하는 것의 감? 같은게 생겼다.
객체, 데이터의 관계를 나타내는 무언가, 무언가 확장할 수 있을거 같을 때는 인터페이스..
타입 그 자체 , 유틸성 타입 , 인풋타입, ..등 은 타입 으로 붙여야하는 느낌이 들지만 아직 추상적인 느낌일 뿐이다.
- 컴포넌트 작성 형태
이 글을 시작하면서 언급한 그것이다.
// React Component
export default function App({}: AppProps){}
const App:React.FC<TProps> = ({}) => {}
const App:FC<IProps> =({}) => {}
const App = ({}:Props) => {} // 등등
React.FC 는 자주 논란거리가 되었고 ( 암묵적인 children, default props 이슈, VFC 를 쓰라다가 또 deprecated 되고..)
제네릭 컴포넌트를 작성할 수 없다는 점에서 배제하였다.
함수는 진짜 필요할때 (화살표함수에서는 안되는 것들) 빼고 모두 화살표 함수를 사용하기로 했다.
( 콜백함수로서 보내줄때 화살표 함수가 아주 좋은 가독성을 보인다. 그럼 이왕 사용하는김에 일관성을 위해 모든 함수에 사용하자)
리액트 함수 컴포넌트도 함수이므로 결국 이 형태를 선택하였다.
const App = ({}:Props)=> {...}
- 컴포넌트의 폴더 구조?
이 부분도 고민이 좀 더 필요한 부분이다. UI 컴포넌트는 다음과 같이 나눴을 때 정돈이 잘 되었다.
(다양한 props 를 받아서 형태를 조합해야함 type 과 style 이 길어진다.)
하지만 일반적인 컴포넌트(root.components 내부가 아닌 컴포넌트) 는 (페이지를 위한 컴포넌트 UI 컴포넌트들을 합쳐만든 구체적인 컴포넌트들) 파일을 나누면 나눌수록 더 분리된 느낌만 주고 큰 장점이 느껴지지 않았다.
그래서 이런 일반 컴포넌트들은 따로 다음과 같은 방식으로 작성하기로 정하였다.
하지만 한 프로젝트에, 컴포넌트를 작성하는 것에 두가지 규칙이 존재하는 것이 썩 좋아보이지는 않았다. 그리고 너무 커스텀화 되어 마이너한 규칙이 된 것 같은 느낌도 받았다.. (overfitting..?)
Style 코드에 대해서 ( css-in-js 처리 방식)
현재 css-in-js 라이브러리 중에서 styled-components 를 사용중이다.
이것도 사람들 마다 다양한 방식으로 사용중이였고 , 내가 고민했던 2가지 방식에 대해서 적어보았다.
1. StyledWrapper 에서 scss nesting 문법을 사용하는 방법
css 를 작성하는 느낌이라 css in js 를 (styled-components) 처음 접하는 사람들에게 부담감없이 적응할 수 있게 되었다.
또 여러개로 나눠진 스타일 관련 컴포넌트를 돌아다니지 않고 하나의 StyledWrapper 만 쳐다보면 되어서 집중도가 높아졌었다.
어떤 html 태그인지 JSX 태그들에 바로 볼 수도 있다.
단점 으로는 className 을 지정해야되서 네이밍에 대한 고민이 생긴다. StyledWrapper 안의 태그들이 깊어지면 scss 코드 또한 깊어지게 되는 문제도 있다.
2. 태그 하나하나를 Styled 로 감싸는 방법
비슷한 스타일인 경우 스타일을 입힌 컴포넌트를 export 하여 다른 곳에서 또 사용할 수도 있었다.
className이 컴포넌트 이름으로 바꼈을 뿐 네이밍의 고민은 사라지지 않는다. 이 컴포넌트가 스타일만 가진 태그인지, 기능을 가진 컴포넌트 자체인지 한눈에 구별하기가 어려웠다. (그래서 이는 S, 혹은 Styled 접두사를 붙여 해결하기도 한다) .
그리고 어떤 종류의 html 태그인지 바로 볼 수가 없다.
- 스타일 파일 분리? 컴포넌트 안에?
이 주제는 많은 사람들이 고민하는 주제이다.
컴포넌트 파일에 스타일 코드를 포함시킬것이냐? 컴포넌트와 스타일은 분리되어야 맞는 것이냐?
지금도 어떤 것이 더 편하고 맞을지 다양하게 시도 중이다.
만약 Styled.Tag 처럼 사용하려면 이렇게
StyledWrapper 처럼 사용하려면 export default Component 문 바로 밑에 styled.div`` ... 를 선언하는 방식으로 정하였다.
현재는 두가지 방식을 동시에 사용해보려고 하였다.
import 하는 방식은 스타일 코드가 조건에 따라 많이 필요한 공통 UI 컴포넌트에 (root.components)
StyledWrapper 로 감싸는 방식은 UI 컴포넌트를 제외한 나머지 컴포넌트에 사용해보려고 한다.
prettier 와 eslint 로 어느정도 코드 스타일을 강제해보자
- typescript-eslint parser
타입스크립트를 사용하면 ts-eslint 를 사용하면 좋다. 다양한 ts 관련 규칙들이 존재하고 이를 강제할 수도 있어서 좋았다.
- prettier plugin import sort
https://github.com/trivago/prettier-plugin-sort-imports
import 순서를 프로젝트에서 지정한대로 포맷팅을 해주는 플러그인이 존재했다.
템플릿 만들어보기
매번 프로젝트를 시작할때 마다 똑같은 초기 세팅을 진행하면 귀찮을 것이다.
그래서 위의 가이드를 바탕으로 템플릿을 만들었다
깃허브에는 템플릿 레포지토리로 설정할 수 있는 기능이 있었고 이 템플릿을 기반으로 새 깃허브 레포지토리를 만들수도 있었다.
더 발전시킬만한 점들
여기서 끝이 아니라 만든 것을 꾸준히 지키며, 새로운 규칙을 도입하고, 상황에 맞게 수정하는 등 지속적인 관리도 필요하다.
더 구체적인 eslint rule 로 코드 스타일 일관성이 어긋나는 것을 코드 작성 단계 부터 막을 수 있기도 하다. commit 혹은 PR 시 lint, formatting action 을 걸어놔도 좋을 거 같다.
깃허브에 올려놓은 템플릿 레포지토리는 현재 React + Next + TS + react-query + styled 로 묶인 1개 짜리 밖에 없지만
후에 next example 처럼 폴더로 분리해놓거나 branch 별로 다른 스택의 템플릿을 만들어놓으면 좋을 것 같다.
https://github.com/vercel/next.js/tree/canary/examples
https://github.com/vitejs/awesome-vite#templates
마무리
직접 정리해본 깃 컨벤션, 폴더구조, 코딩 스타일 규칙을 대략적으로 살펴보았다.
사람마다 다양한 코딩 스타일을 가지고 있으므로 여러 사람이 진행하는 프로젝트일 수록 일관된 코드들과 구조들이 필요하다.
직접 프로젝트에 필요한 여러 규칙들을 정의해보면서 협업을 진행할때 어떤 것을 고려해야 하는 지를 알 수 있는 계기가 되었다.
왜 이렇게 이런 구조를 짰나, 이런 규칙을 만들었나 명확하게 설명을 할 수 있어야 한다. 조금만 더 구체적인 why 를 적어서 문서에 살을 덧붙여야 겠다.
지금은 나 혼자 쓰는 것이라 이것저것 도전적인 규칙도 만들어보고 바꾸고 할 수 있지만 여러 사람이 같이 쓰려면 적절한 선에서 합의가 필요하다. 사실 내가 작성한 폴더 구조를 보면서, 너무 커스텀화..? 되었다는 느낌을 받았다. 다른 곳에서 잘 안쓰는 딥한 구조를 가져갈 필요도 없고 일반적으로 통용되는 구조를 참고하며 적용하면 다른 사람들이 봐도 적용하기 편하지 않을까라는 생각도 들었다.
끝
'기술 메모장' 카테고리의 다른 글
잘하는 개발자를 보면서 포기하지 않기 (1) | 2023.12.17 |
---|---|
오픈소스 저장소, PR에서 볼 수 있는 것들 (feat. react-query, @toss/slash) (2) | 2022.11.16 |
나의 코딩 컨벤션과 폴더구조를 소개합니다. #1 (깃 컨벤션과 폴더구조) (1) | 2022.10.13 |
React Router를 직접 만들어보는 과정 (with 프리온보딩 FE 챌린지 10월) (1) | 2022.10.09 |
UNITHON 9TH 참가 후기 - 찐 I의 2박3일 오프라인 해커톤 도전기 (1) | 2022.09.13 |