성장과회고

11.14.2024(목) TIL

에밀오구 2024. 11. 14. 13:56

1.  새롭게 배운 점은? (Learned)

"프론트엔드는 클린 코드보다 중요한 게 정확한 기능구현과 정확한 퍼블리싱" 라는 강사님 말씀이 인상깊었습니다. 그래서 오늘은 보다 정확한 퍼블리싱을 구현하도록 고민하고 시멘틱 태그를 다시 한 번 고민을 하는 시간을 가졌어요.  더 나아가서는  테일윈드 css 와 grid로 코드짜는 것에 익숙해지는 시간을 가졌습니다. 아래 내용은 새롭게 안 내용과 고민입니다.

분석과 고민

1. search-bar.tsx 파일 분석

1-1. 조건부 렌더를 쉽게 작성하려고 만든 cn 유틸 함수

search-bar는 내부적으로 cn함수를 사용하는 데 살펴보니 utils 폴더 내부에 있는 사용자 정의함수이고 이는 조건부 렌더를 쉽게 작성하기 위해 만든 함수라고 합니다. 

//utils>index.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

1-1-1. clsx 라이브러리

clsx 라이브러리는 클래스명 문자열을 조건부로 구성하기 위한 작은 유틸리티입니다.  스타일을 여러 조건부로 나눠 처리하고 싶을 때 조건식을 객체화시켜서 사용하는 방식이네요. 

function Button () {
const [isClick,setIsClick] =useState(false);

const handleClick = () =>{
setIsClick(!isClick);
}

return(
<button 
  onClick={handleClick} 
  className = {clsx(`w-full h-5 `,{'bg-red-200': isClick})}
>
</button>
)
}

1-1-2. tailwind-merge 라이브러리

tailwind-merge 라이브러리는  "스타일 충돌 없이 JS에서 Tailwind CSS 클래스를 효율적으로 병합하는 유틸리티"입니다.  여기서 중요한 점이 CSS 캐스케이딩(cascading:스타일 규칙 및 선언이 어떻게 적용되는지에 대한 규칙 및 우선 순위를 정의하는 프로세스)라는 개념인데 className 에 들어가는 클래스명의 순서는 의미가 없다는 점입니다.   만약 "  default style이 p-4(padding:8px)인 버튼 컴포넌트를 특정 케이스에만  p-2 로 바꾸고 싶다" 라고 가정해봅시다. 그러면 className 에  p-4가 있는 상태에서 p-2 를 추가로 넣으면 p-2 는 무시되기 때문에 기존 p-4 클래스를 삭제하고 p-2를 넣어야하는 조건부 렌더링을 해야 한다는 것입니다. 어제 테일윈드를 쓰다가 해당 내용을 몰라 어 이게 왜 동작을 안하지 싶었는 데 이해되는 순간이네요.(야호) 

 이러한 이유 때문에 테일윈드로 스타일 분기처리를 하려면 덮어 쓸 수 없고 조건부 렌더링을 해야하는 데 tailwind-merge 에 twMerge 함수를 사용하면 충돌하는 클래스들을 같이 써도 원하는 데로 덮어쓸 수 있다는 것입니다. 

 

1-2. forwardRef 

forwardRef()를 호출하면 컴포넌트가 ref를 받아 하위 컴포넌트로 전달합니다.  forwardRef 는 jsx 에서 렌더링할 수 있는 React 컴포넌트를 반환하고 일반함수로 정의된 React 컴포넌트와 다르게 forwardRef가 반환하는 컴포넌트는 ref props도 받을 수 있다고 하네요. 

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  // ...
});

forwarRef는 해당 컴포넌트가 ref.를 사용하여 부모 컴포넌트의 DOM 노드를 노출할 수 있습니다. 말이 좀 어려운데요. 아래 코드를 보니 이해가 됐습니다.  아하 외부 컴포넌트 동작에 의해  특정 컴포넌트 동작(input)을  활성화 되게 하려고 이 두 컴포넌트의 부모단에서 제어하는 구조로 사용되는 구나!  이해되는 순간이였어요. 

function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
      <MyInput label="Enter your name:" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}

 

2. width 값이 일정한 형제요소가 있고 나머지 width 값을 전부 차지해야하는 컴포넌트가 있을 때 height 값은 어떻게  줘야 할까?

-> [ 해결 ] 부모요소에 flex 속성을 주고 해당 태그에 flex-1 를 주면 나머지 영역 전체를 차지하게 됩니다.  또 형제요소의 너비값을 상수 변수로 만든 후 부모요소 너비 100%에 형제요소 너비값을 빼주면 됩니다.

더 나아가 테일윈드에서 calc 를 사용하는 방법은  w-[calc(100%-30px)]  이렇게 사용할 수 있습니다. 중간에 공백 넣으니 스타일이 먹지 않네요.

 

새롭게 안 내용 

0. export  경로 묶기 컴포넌트 파일에 index.tsx 파일을 만들고 export 를 묶어주면  외부에서 컴포넌트들을 import 할때 코드 양을 줄일 수 있다.  

ui 폴더 내 index.ts
사용

1. @ 를 사용해 특정 경로를 별칭으로 정의해 편리하게 import 할 수 있다.

-> [ 더 알아보기 ] 해당 기능은  Path Aliasing 이라고 합니다. Path Aliasing 는 프로젝트 내에서 특정 경로를 별칭( alias )으로 정의하여 import 할 수 있도록 하는 기능 입니다.

 

 

2. 테일윈드 css 에서 h-20 는 height가  20*4 = 80px -> 숫자가 있다면 *4 하면 px 값을 예상할 수 있다.

3. 시맨틱 테그는 원칙적으로 영역을 꽉차게 잡는 다.

4. css 네이밍 규칙 중 .page__container  처럼 작성하면 scss  작성시 장점이 있다. html을 해당 파일처럼 작성한다면 scss 로  아래와 같이 스타일링 할 수 있다. 단 뎁스가 3개를 넘어가면 가독성이 떨어지니 뎁스가 깊어진다면 다른 클래스 명으로 작성하는 게 바람직하다.

또한 _fonts.scss 처럼 scss 파일 앞에 _ 가 있다면 빌드시 css 로 변환할 필요없는 파일이란 것을 의미한다. 요새 css 가 scss 문법을 기본적으로 통합하고 있어서 알고만 있으면 좋을 것같아요. 

<div class="page">
  <div class="page__container">
     <div class="page__container_wrapper">
              <div class="card">
                    <div class="card__wrapper">
 
                     </div>
               </div>
     </div>
  </div>
</div>

 

 

 

2. 앞으로 뭘 더 하면 좋을까? (Longed for)

타입스크립트를 좀 더 연습하는 시간을  갖고 지금처럼 당일 새롭게 알게 된 부분들을 정리하고 또 혼자 더 나아가서 찾아보고 공부하는 시간을 유지해야겠습니다.