
React TypeScript props를 컴포넌트에 전달하고 타입을 정의하는 것은 타입스크립트를 사용하는 리액트 프로젝트의 가장 기본이면서도 중요한 부분입니다. 타입을 명확하게 지정함으로써 개발 과정에서 발생할 수 있는 오류를 사전에 방지하고, 코드의 가독성과 유지보수성을 크게 향상시킬 수 있기 때문입니다. 많은 개발자가 처음 리액트에 타입스크립트를 도입할 때 props 타입 정의에서 혼란을 겪곤 합니다.
이 글에서는 제 경험을 바탕으로 가장 대중적인 방법부터 최신 권장 방식까지, React.FC
와 interface
, 그리고 children
props를 다루는 방법을 체계적으로 정리해 보겠습니다.
✨ 컴포넌트 타입 지정의 기본 React.FC
React.FC
(FunctionComponent의 축약형)는 함수형 컴포넌트의 타입을 정의할 때 가장 먼저 접하게 되는 방식입니다. 컴포넌트가 함수형 컴포넌트임을 명시하고, 제네릭(<>
)을 통해 props의 타입을 지정할 수 있습니다.
React.FC 기본 사용법
가장 기본적인 형태는 다음과 같습니다. React.FC
를 사용하고 제네릭 안에 props의 타입을 정의한 interface
나 type
을 넣어줍니다.
이 코드에서 Greetings
컴포넌트는 GreetingProps
타입을 따르는 name
과 message
라는 두 개의 props를 받습니다. name
은 필수이지만, message
는 ?
가 붙어 있어 선택적으로 전달할 수 있습니다.
React.FC의 특징과 변화
과거 React.FC
는 children
prop을 암묵적으로 포함하고 있었습니다. 이 때문에 props 타입에 children
을 명시하지 않아도 컴포넌트가 children
을 받을 수 있었죠. 하지만 React 18 버전부터는 React.FC
가 더 이상 children
을 암묵적으로 포함하지 않도록 변경되었습니다. 이는 children
을 받지 않는 컴포넌트에 실수로 children
을 전달하는 상황을 방지하고, 타입 정의를 더 명확하게 만들기 위한 좋은 변화입니다.
따라서 최신 버전의 React와 TypeScript를 사용한다면 children
이 필요할 경우 직접 타입에 명시해주어야 합니다. (이 부분은 아래에서 자세히 다루겠습니다.)
📝 interface와 type으로 props 타입 정의하기
최근 커뮤니티에서는 React.FC
를 사용하는 대신, 컴포넌트의 props 타입을 직접 interface
나 type
으로 정의하고 함수 매개변수에 적용하는 방식을 더 선호하는 추세입니다. 코드가 더 간결해지고, React.FC
의 암묵적인 특징들에서 자유로워질 수 있기 때문입니다.
interface를 사용한 props 정의
interface
는 객체의 구조를 정의하는 데 사용되며, 확장(상속)이 가능하다는 특징이 있습니다. 컴포넌트 props는 객체 형태이므로 interface
를 사용하기에 매우 적합합니다.
위 예제에서는 React.FC
없이 함수 매개변수 부분에 직접 : UserProfileProps
형태로 타입을 선언했습니다. 이 방식이 현재 가장 널리 사용되는 표준적인 방법 중 하나입니다.
type을 사용한 props 정의
type
키워드는 interface
와 유사하게 객체 타입을 정의할 수 있을 뿐만 아니라, 유니언(|
)이나 인터섹션(&
) 같은 더 복잡한 타입 조합을 만드는 데 유용합니다.
ButtonType
처럼 특정 값들만 허용하는 유니언 타입을 정의하고 이를 ButtonProps
에서 사용하여 props의 타입을 더욱 엄격하게 제한할 수 있습니다.
interface vs type 언제 무엇을 써야 할까?
interface
와 type
사이에는 몇 가지 차이점이 있지만, 컴포넌트 props를 정의하는 데 있어서는 대부분의 경우 개인이나 팀의 스타일 가이드에 따라 선택합니다.
저의 경험상, 컴포넌트의 props나 API 객체의 응답 형태를 정의할 때는 interface
를, 그 외 복잡한 타입 조합이나 별칭이 필요할 때는 type
을 사용하는 것이 코드의 의도를 명확히 하는 데 도움이 되었습니다.
👶 children props는 어떻게 다루나요?
children
은 React에서 컴포넌트 사이에 다른 엘리먼트나 컴포넌트를 삽입할 때 사용되는 특별한 prop입니다. TypeScript에서는 이 children
prop의 타입도 명시적으로 정의해주어야 합니다.
children
에 가장 적합한 타입은 React.ReactNode
입니다. 이 타입은 JSX 엘리먼트, 문자열, 숫자, null
, undefined
등 React 컴포넌트가 자식으로 가질 수 있는 모든 종류의 값을 포함합니다.
이렇게 children: ReactNode;
라고 명시해주면, Layout
컴포넌트는 내부에 어떤 종류의 React 엘리먼트든 자식으로 받을 수 있게 됩니다. 과거 React.FC
에 의존하던 방식보다 훨씬 명시적이고 안전한 방법입니다.
만약 children
으로 특정 컴포넌트만 받도록 제한하고 싶다면 React.ReactElement
를 사용할 수도 있지만, 대부분의 유연한 컴포넌트 설계에서는 React.ReactNode
가 더 적합합니다.
🚀 실제 프로젝트 적용 사례 (경험 기반)
이론을 아는 것도 중요하지만, 실제 프로젝트에서 어떻게 적용되는지 살펴보는 것이 이해에 큰 도움이 됩니다. 아래는 사용자 정보를 표시하는 Card
컴포넌트 예제입니다.
이 예제에서는 다음과 같은 점들을 고려했습니다.
이처럼 React TypeScript props를 명확하게 정의하는 습관은 단순히 타입을 맞추는 것을 넘어, 컴포넌트의 API를 설계하는 과정이며 이는 곧 애플리케이션 전체의 안정성과 확장성으로 이어집니다.
결론
React 프로젝트에 TypeScript를 도입하면 props를 통해 컴포넌트 간에 데이터를 전달할 때 강력한 타입 안정성을 확보할 수 있습니다.
올바른 props 타입 정의는 협업하는 동료에게 컴포넌트의 사용법을 알려주는 훌륭한 문서 역할을 하며, 장기적으로 유지보수가 용이한 코드를 만드는 데 핵심적인 역할을 합니다. 프로젝트 초기에 팀 내에서 props 타입 정의에 대한 컨벤션을 정하는 것을 강력히 추천합니다.
관련 글
무료 폰트 사이트 추천 TOP 7 저작권 걱정 없는 상업용 한글 폰트 모음