티스토리 뷰

[ Class 사용 시, extends를 남발하지 말자 ]

  • 상속(extends 키워드)를 사용하면 코드의 중복을 줄일 수 있다는 장점이 있다. 하지만 장점만 존재하는 것이 아니다.
  • 상속을 사용하면 코드가 "강 결합" 형태가 된다. 이렇게 되면 부모 클래스가 변경됐을 때, 다른 코드들에 모든 영향이 가게 된다. => 유지보수가 힘들어진다!
  • 그렇기 때문에 코드의 결합은 신중하고 최대한 느슨하게 하는 것이 좋다. (꼭 상속을 한다면 1단계, 2단계 정도만)
  • 그렇다면 대안은? 상속 대신, 의존성을 주입해주는 형태로 쓰면 된다. => 인자로 받는다는 소리

[ Class 내부에서만 사용하는 상수는 Class 안으로 넣어주기 ]

  • 좋은 코드의 큰 기준점 2가지: 결합도와 응집도 (낮은 결합도와 높은 응집도)
  • 함수(function)와 다르게 class는 상태라는 값을 가질 수 있기 때문에 클래스 멤버 변수로 담아둘 수 있다!
    • e.g.) private readonly URL = "/repos/facebook/react/"; //외부에서 사용x니까 private, 상수값이니 readonly

[ CSS-in-JS와 className을 이용한 스타일링 혼용 금지 ]

  • styled-component 나 emotion등을 사용할 때 스타일 컴포넌트를 생성하고 그 내부에 '클래스 네임'을 통해서 자식 요소에 대한 스타일링을 추가적으로 하는 경우가 있다. 간단한 프로젝트나 빠르게 진행해야 한다면 불가피하게 클래스 네임에 접근하여 스타일링할 수 있겠으나 이렇게 되면 디버깅이 너무 힘들어진다. (nesting depth가 깊을수록 더 어려움)
  • 위와 동일한 이유로 className과 더불어 tag selector( a태그, img 태그 h3 태그 등..) 사용 역시 지양돼야 한다.
  • 즉, CSS 컴포넌트 내부에 네스팅해서 className과 tag selector를 쓰면 안된다는 소리
  • CSS는 JS와 다르게 중구난방으로 서로 영향을 미치지만 어디서 어디까지 영향을 미치는 지 파악하기 어렵다.
    • 그래서 CSS 프로퍼티를 쓸 때에도 컨벤션을 맞춰주면 좋은데 예를 들어 영향을 많이 미치는 순서대로(e.g. position 등)쓴다든가 한다.  

[ 의미가 드러나지 않는 값들 대신에 의미를 명확하게 알려주기 ]

  • 코드를 짤 때는 읽는 사람의 입장에서 써야한다. 처음 읽는 사람도 이 함수가 어떤 기능을 하는 함수고 어떤 기능인지 코드만을 보고 이해할 수 있게 짜는게 제일 좋은 코드같다.

[ 너무 많은 정보를 주는 것은 추상화가 제대로 되지 않은 것 ]

  • 추상화: 문제 해결을 위해 필요한 핵심 내용만 남기고 관련이 없는 내용을 제거함으로써 문제를 단순화시키는 과정(맥락에 따라 의미가 다름)
  • 예를 들어, 커스텀 훅을 만들고 그곳의 리턴값이 너무 많으면 제대로 `추상화나 역할 분리`가 되지 않은건 아닌지 생각해봐야 한다. 적정선의 리턴값이라하면 아래와 같은 형태가 될 수 있다.
const { data, error, loading, hasNextPage } = useIssueList();

[ 동등성 제대로 보장해주기 ]

  • 예를 들어, 커스텀 훅을 만들고 내부에서 callback함수를 useCallback을 통해 함수의 동등성을 보장해줬다고 하자. 동드성을 보장한다는 말은 함수가 같다면 새로운 함수를 만들지 않을 것이라는 말로 이해하면 된다. 
  • 커스텀 훅에서 동등성을 보장해주고 호출하는 컴포넌트에서 리렌더링때마다 인자로 넘겨주는 함수가 있다면 그 역시도 동등성을 보장해줘야 한다. 만약에 상위에서 넘겨주는 함수가 컴포넌트가 렌더링될 때마다 새롭게 생성되어 넘겨지게 된다면 커스텀 훅에서 callback함수를 useCallback으로 감싸놔봤자 새로운 함수가 매번 넘겨지는 것이기 때문에 의미가 없다.
  • 해결방법: 넘겨주는 콜백인자함수를 사용하는 컴포넌트 내에서도 따로 선언해서 useCallback으로 묶어준 다음 넘겨준다.  

[ 의존성 잘 넣어주기 ]

  • useEffect 내부에서 사용하는 값이 외부값일 경우, 의존성 배열에 넣어줘야 한다. => 의존성 배열에 외부값을 넣어주지 않으면 해당 변수가 변했을 때, 값이 변했음을 인식하지 못하고 함수를 호출하지 않는 버그가 발생한다. 

[ 리액트 컴포넌트는 순수함수여야 한다 ]

리액트 컴포넌트는 props(의미적으론 state)를 받아서 JSX를 리턴하는 순수함수이다.

*순수함수? 같은 input 같은 output, 이런 함수가 되려면 side effect(사이드 이펙트란 외부의 값에 접근하거나, 변경하는 등의 행위)가 없어야 한다.

 

bad case 🔽

function Compoennt () {
return (
   <div>
   {alert("say hi to me!")}
   </div>
	)
}
  • 위의 코드는 안좋은 컴포넌트의 예시이다. 이유는 웹 브라우저의 alert API를 사용하고 있기 때문 => 이는 명백한 side effect 이다. 이 동작은 렌더링 과정에서 수행해서는 안된다.
  • 메모이제이션, 최적화, state, 서버 사이드 렌더링(SSR) 등은 JSX가 순수함수라는 것을 전제로 해서 동작하기 때문이다. (리액트에서 렌더링 과정은 무조건 순수해야 한다.)
  • 그렇기 때문에 이런 사이드 이펙트 작업을 수행하기 위해 React의 hook중 하나인 useEffect를 사용하는 것이다. (useEffect 실행 시점 => 컴포넌트 렌더링 작업이 다 끝났을 때인 이유) + 또는 이벤트 핸들러 내부에서 side effect 수행

TIP: 추가적으로, 엄격하게 따졌을 때: id selcctor를 리액트 컴포넌트에서 쓰면 한 HTML(document)에 단 1개만 존재하는 유일성이라는 의미가 퇴색되기 때문에 input id="a"과 label htmlfor="a" 조합처럼 특이 케이스가 아니라면 안쓰는 경우도 있다. (이건 개인 선호도에 따라 다를 듯하다.) => 몇몇 상황을 제외하고는 id는 리액트 컴포넌트에서 안쓰는 것이 좋다.

  • label 태그 안에 input을 넣어버리면 암묵적으로 해당 label은 내부의 input을 가리키고 있다고 지정되기 때문에 위와같이 id selector를 사용하지 않아도 된다. (nesting 하여 사용)

 

댓글