React 컴포넌트에서 TypeScript Generics

발행: (2026년 1월 9일 오전 12:25 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

Introduction

제네릭은 매일 React 컴포넌트에서 사용하는 것은 아니지만, 특정 상황에서는 컴포넌트를 유연하면서도 타입‑안전하게 만들 수 있게 해줍니다.

Basic Component Definitions

Without Props

// Just FC component with no props
const Component = () => Hey ya!!!;

With Props using React.FC

// FC component with props
interface Props {
  name: string;
}

const Component: React.FC = ({ name }) => (
  Hey {name} ya!!!
);

React.FC는 몇 가지 이유로 선호도가 떨어졌는데, 그 중 하나는 우리가 필요로 하는 방식으로 제네릭을 처리하지 못한다는 점입니다. 그럼에도 불구하고 가독성을 위해 여전히 사용하는 개발자들이 많습니다.

Without React.FC

// FC component with simple props
interface Props {
  name: string;
}

const Component = ({ name }: Props) => Hey {name} ya!!!;

When Generics Are Needed

컴포넌트가 API에서 받아온 배열 형태의 DTO(Data Transfer Object)를 받는 상황을 생각해 보세요. 컴포넌트는 “이름”을 나타내는 속성을 표시해야 하는데, 정확한 속성 이름은 DTO마다 다를 수 있습니다.

Example DTO

interface ResponseDTO {
  id: number;
  name: string;
}

Component Tied to a Specific DTO

interface ExampleProps {
  data: ResponseDTO[];
  getName: (item: ResponseDTO) => string;
}

export const Example = ({
  data,
  getName = (item) => item.name,
}: ExampleProps) => (
  
    {data.map((item) => (
      {getName(item)}
    ))}
  
);

이 코드는 ResponseDTO의 정확한 형태를 컴포넌트가 알고 있기 때문에 동작합니다. 어떤 DTO든 “이름과 비슷한” 값을 가지고 있다면 처리하도록 만들고 싶다면 제네릭이 필요합니다.

Generic Props Interface

interface Props {
  data: T[];
  getName: (item: T) => string;
}

제네릭 파라미터 Tdata 배열과 getName 콜백을 연결시켜, 두 요소가 같은 타입을 사용하도록 보장합니다.

Generic Component

export const NameViewer = ({ data, getName }: Props) => (
  <>
    Look at the names:
    {data.map((item) => (
      {getName(item)}
    ))}
  
);

Note: In .tsx files, writing “ (with a trailing comma) disambiguates the generic declaration from JSX syntax.

Using the Generic Component

const unknownTypeData = [
  { id: 1, nameProp: 'John' },
  { id: 2, nameProp: 'Jane' },
];

const anotherUnknownTypeData = ['Foo', 'Bar'];

export const BusinessComponent = () => (
  
     item.nameProp}
    />
     item}
    />
  
);

NameViewer는 적절한 getName 함수만 제공하면 이제 어떤 타입의 데이터든 받아들일 수 있습니다.

Conclusion

이 간단한 예제는 제네릭을 활용하면 다양한 데이터 형태에 맞게 React 컴포넌트를 조정하면서도 타입 안전성을 유지할 수 있음을 보여줍니다. 앞으로의 글에서는 조건부 제네릭과 같은 더 고급 패턴을 살펴볼 예정입니다.

Back to Blog

관련 글

더 보기 »

InkRows 뒤의 tech stack

InkRows https://www.inkrows.com/ 은 웹과 모바일 플랫폼에서 원활하게 작동하도록 설계된 현대적인 노트‑테이킹 앱입니다. 깔끔하고 직관적인 …

React에서 간단한 Carousel/Slider 만들기

캐러셀 또는 슬라이더는 이미지나 콘텐츠를 하나씩 표시하는 훌륭한 방법입니다. 버튼을 사용하여 이를 탐색할 수 있습니다. 아래는 간단한 구현...