TypeScript_STUDY 8장 _ JSX에서 TSX로 [ 8.2 타입스크립트로 리액트 컴포넌트 만들기 & 8.3 정리 ]

zeroha·2024년 12월 23일
0

TypeScriptStudy

목록 보기
25/32
post-thumbnail

8.2 타입스크립트로 리액트 컴포넌트 만들기

타입스크립트는 리액트 프로젝트에서 공통 컴포넌트에 어떤 타입의 속성이 제공되어야 할까

.
.
.

1. JSX로 구현된 Select 컴포넌트

각 option의 key-value 쌍을 객체로 받고 있으며, 선택된 값이 변경될 때 호출되는 onChange 이벤트 핸들러를 받도록 구현됨.

  • 그러나
    추가적인 설명이 없다면 컴포넌트 사용자는 각 속성에 어떤 타입값을 전달해야 할지 알기 어려움.

  • 따라서
    컴포넌트 사용 개발자가 각 속성에 어떤 타입 값을 전달해야 할지 명확히 알 수 있도록 추가적인 설명이 필요


2. JSDocs로 일부 타입 지정하기

: 컴포넌트의 속성 타입을 명시 ( 컴포넌트 설명 + 속성의 역할 )

/**
* Select 컴포넌트
*@param {Object} props - Select 컴포넌트로 넘겨주는 속성
*@param {Object} props.options - { [key: string]: string } 형식으로 이루어진 option 객체
lement)
const Select = //...
**/

3. props 인터페이스 적용하기

  • 그러나 JSDocs 사용하면
    options가 어떤 형식의 객체를 나타내는지나 onChange의 매개변수 및 반환 값에 대한 구체적인 정보를 알기 쉽지 않아서 잘못된 타입이 전달될 수 있는 위험이 존재

  • TS를 사용하여 좀 더 정교하고 구체적인 타입 지적 가능

  • 먼저 JSX -> TSX로 변경한 후 Select 컴포넌트의 props에 대한 인터페이스를 작성


4. 리액트 이벤트

리액트는 가상 DOM을 다루면서 이벤트도 별도로 관리.

React 이벤트는 HTML DOM 이벤트와 유사하지만, React 자체의 합성 이벤트(Synthetic Event) 시스템을 사용해 일관성 있게 동작.

브라우저 간 호환성이 보장되며, camelCase로 작성된 이벤트 핸들러(prop)를 통해 정의.
리액트 컴포넌트에 연결할 이벤트 핸들러도 해당 타입을 일치시켜줘야 함.

예를 들어, onClick, onChange와 같은 이벤트를 사용하며, 기본적으로 이벤트는 preventDefault와 같은 메서드를 제공합니다.


5. 훅에 타입 추가하기

useState 같은 함수 역시 타입 매개변수 지정해줌으로써 반환되는 state 타입을 지정.
만약 제네릭 타입 명시 x -> 타입스크립트 컴파일러는 초깃값의 타입을 기반으로 state 타입 추론.

const fruits = {
apple: "사과", banana: "바나나", blueberry: "블루베리",};

const FruitSelect: VFC = () => {
const [fruit, changeFruit] = useState‹string | undefined>();

return (<Select onChange={changeFruit} options={fruits} selectedOption={fruit} />
  );
};



// fruit: undefined;
// changeFruit: (v: React.SetStateAction<undefined>) => void;
const [fruit, changeFruit] = useState();

return (
...
);
  • 하지만
    useState에 제네릭 타입을 지정해주지 않는다면 타입스크립트 컴파일러는 fruit를 string으로 추론, 다음에 다른 개발자가 changeFruit에 fruit 타입에 속하지 않는 orange를 넣을 수 있음.
    -> 컴파일러 역시 이를 에러로 잡지 않아 예상치 못한 사이드 이펙트 발생 가능

사이드 이펙트 side Effect
: 프로그램의 실행 결과 예상치 못한 상태로 변경되거나 예쌍치 못한 동작을 하게 되는 상황.
즉, 코드의 실행이 예상과 다르게 동작 -> 예상치 못한 결과를 초래하는 것.

-코드-

이럴 때는 타입 매개변수로 좀 더 명확한 타입을 지정 -> 다른 개발자가 해당 state나 changeState를 한정된 타입으로만 다룰 수 있게 강제

  • 이처럼 훅이나 외부 라이브러리 또는 내부 모듈의 함수는 적절한 제네릭 타입을 설정하여 활용 가능.

6. 제네릭 컴포넌트 만들기

const FruitSelect = () => {
const [fruit, changeFruit] = useState<Fruit | undefined>();

return (
<Select onChange={changeFruit} options={fruits} selectedOption="orange" />
  );
};

selectOption은 options에 존재하지 않는 값을 받아도 아무런 오류가 발생하지 않음.

  • 하지만
    changeFruit의 매개변수 Fruit는 prop으로 전달돼야 하는 onChange의 매개변수 타입인 string보다 좁기 때문에 타입 에러가 발생.

  • Select를 사용하는 입장에서 제한된 key & value 만을 가지도록 하려면 ?
    : 함수 컴포넌트 역시 함수이므로 제네릭을 사용한 컴포넌트를 만들어낼 수 있음.


7. HTMLAttributes, Reactprops 적용하기

HTMLAttributesReact.Props는 React 컴포넌트의 props를 정의할 때 유용.

  • HTMLAttributes
    : 기본 HTML 요소에 적용할 수 있는 모든 속성을 타입으로 제공하며, 특정 태그(button, div 등)에 특화된 속성도 포함.

  • React.ComponentProps
    : 기존 컴포넌트의 props를 확장하거나 참조하여 중복 없이 재사용할 수 있도록 도와줍니다.
    이를 통해 타입 안정성과 코드 재사용성을 높일 수 있음.


8. styled-components를 활용한 스타일 정의

  • styled-components : CSS를 자바스크립트 안에서 정의하고 관리할 수 있는 React 기반의 CSS-in-JS 라이브러리. ( CSS-in-JS 기법 사용 가능 )

CSS 스타일을 컴포넌트 수준에서 정의하며, 각 컴포넌트는 고유한 클래스를 생성해 스타일 충돌을 방지.

템플릿 리터럴을 활용해 동적 스타일을 쉽게 적용할 수 있으며, props 기반의 조건부 스타일링도 간편.

이를 통해 코드 가독성을 높이고 스타일과 로직의 결합도를 낮출 수 있음.


9. 공변성과 반공변성

  • 공변성
    : 타입이 더 구체적인 방향으로 확장될 때 허용되는 관계를 뜻하며, 함수의 반환값 타입에서 주로 사용.
    예를 들어, 부모 클래스 타입을 반환해야 할 때 자식 클래스 타입을 반환할 수 있습니다.

  • 반공변성
    : 반대로 타입이 더 일반적인 방향으로 확장될 때 허용되며, 함수의 매개변수 타입에서 주로 사용.
    예를 들어, 자식 클래스 타입을 받아야 할 때 부모 클래스 타입을 받을 수 있음.

이 두 개념은 타입 안전성을 유지하며 유연한 타입 설계를 가능하게 함.


8.3 정리

리액트 프로젝트에서 타입스크립트는 컴포넌트를 안전하게 조합하고 사용할 수 있도록 도와줌. 또한 다양한 훅을 활용하여 컴포넌트 내부 동작 구현할 때도 타입 명확하게 지정 -> 많은 실수 미리 방지 가능

.
.
.

도서참조 : 우아한 타입스크립트 with 리액트
profile
하 영

0개의 댓글

관련 채용 정보