처음 만난 리액트 문서


5.3 컴포넌트 만들기

5.3.1 컴포넌트의 종류

지금까지 리액트 컴포넌트와 props에 대해서 배웠습니다. 이제부터는 실제로 리액트 컴포넌트를 만드는 방법에 대해서 배워보도록 하겠습니다. 리액트에서의 컴포넌트는 아래 그림처럼 크게 클래스 컴포넌트와 함수 컴포넌트로 나뉩니다.

Component types

리액트의 초기 버전에서는 클래스 컴포넌트를 주로 사용하였습니다. 하지만 클래스 컴포넌트가 사용하기 불편하다는 의견이 많이 나왔고, 이후에는 함수 컴포넌트를 개선해서 주로 사용하게 되었습니다. 함수 컴포넌트를 개선하는 과정에서 개발된 것이 바로 훅(Hook)이라는 것인데, 이 부분은 7장에서 자세히 배울 예정입니다. 현재 리액트 개발에서는 거의 Hook을 사용한다고 생각하면 되는데, 그렇다고 클래스 컴포넌트에 대해서 공부하지 않고 그냥 모른채 지나가는 것을 추천하지는 않습니다. 왜냐하면 리액트의 기초를 탄탄하게 다지려면 클래스 컴포넌트와 6장에 나올 컴포넌트의 라이프사이클에 대해서 잘 이해하고 있는 것이 좋기 때문입니다.

5.3.2 함수 컴포넌트

먼저 함수 컴포넌트에 대해서 간단하게만 알아보도록 하겠습니다. 아까 앞에서 props에 대해서 설명할 때, 모든 리액트 컴포넌트는 Pure함수같은 역할을 해야한다고 했습니다. 이 말은 결국 리액트의 컴포넌트를 일종의 함수라고 생각한다는 뜻입니다. 아래 간단한 함수 컴포넌트 예시를 한 번 보도록 하겠습니다.

function Welcome(props) {
    return <h1>안녕, {props.name}</h1>;
}

이 코드에는 Welcome이라는 이름을 가진 함수가 하나 나옵니다. 이 함수의 경우 하나의 props객체를 받아서 인삿말이 담긴 리액트 element를 리턴하기 때문에 리액트 컴포넌트라고 할 수 있습니다. 그리고 이렇게 생긴 것을 우리는 함수 컴포넌트라고 부릅니다. 코드가 굉장히 간단하죠? 함수 컴포넌트는 이처럼 간단한 코드가 장점이라고 할 수 있습니다.

5.3.3 클래스 컴포넌트

클래스 컴포넌트는 자바스크립트 ES6의 class라는 것을 사용해서 만들어진 형태의 컴포넌트입니다. 클래스 컴포넌트의 경우에는 함수 컴포넌트에 비해서 몇가지 추가적인 기능을 갖고 있습니다. 이 부분에 대해서는 뒤에서 다루도록 하겠습니다. 아래의 클래스 컴포넌트 예제 코드를 한 번 보도록 하겠습니다.

class Welcome extends React.Component {
    render() {
        return <h1>안녕, {this.props.name}</h1>;
    }
}

이 코드는 우리가 위에서 살펴본 함수 컴포넌트 Welcome과 동일한 역할을 하는 컴포넌트를 클래스 형태로 만든 것입니다. 함수 컴포넌트와의 가장 큰 차이점은 리액트의 모든 클래스 컴포넌트는 React.Component를 상속(Inheritance)받아서 만든다는 것입니다. 상속이라는 것은 객체지향 프로그래밍(Object Oriented Programming, OOP)에서 나오는 개념인데, 한 클래스의 변수들과 함수들을 상속받아서 새로운 자식 클래스를 만드는 방법입니다. 여기에서는 React.Component라는 클래스를 상속받아서 Welcome이라는 클래스를 만들었고, 이는 React.Component를 상속받았기 때문에 결과적으로 리액트 컴포넌트가 되는 것입니다.

5.3.4 컴포넌트 이름 짓기

우리가 컴포넌트의 이름을 지을 때 한 가지 유의해야 할 중요한 사실이 있습니다. 바로 컴포넌트의 이름은 항상 대문자로 시작해야 된다는 것입니다. 왜냐하면 리액트는 소문자로 시작하는 컴포넌트를 DOM 태그로 인식하기 때문입니다. 예를 들어, <div><span> 같이 사용하는 것은 내장 컴포넌트라는 것을 뜻하며, 'div''span' 같은 문자열 형태로 React.createElement()에 전달됩니다. 하지만 <Foo />와 같이 대문자로 시작하는 경우에는 React.createElement(Foo)의 형태로 컴파일 되며, 자바스크립트 파일 내에서 사용자가 정의했거나 import 한 컴포넌트를 가리킵니다. 그렇기 때문에 컴포넌트 이름은 항상 대문자로 시작해야 합니다. 아래 예시 코드를 한 번 보도록 하겠습니다.

// HTML div 태그로 인식
const element = <div />;

// Welcome이라는 리액트 컴포넌트로 인식
const element = <Welcome name="인제" />;

첫 번째 코드는 DOM 태그를 사용하여 element를 만든 것입니다. 우리가 이미 많이 봐온 것처럼, DOM 태그들은 div, h1, span 등처럼 모두 소문자로 시작합니다. 두 번째 코드는 사용자가 정의한 Welcome이라는 컴포넌트를 사용한 element입니다. 만약 여기에서 컴포넌트 이름이 소문자로 시작하여 welcome이 되었다면, 리액트는 내부적으로 이게 컴포넌트가 아니라 DOM 태그라고 인식을 하게됩니다. 결과적으로 에러가 발생하거나, 우리가 원하는대로 결과가 나오지 않게 될 것입니다. 그래서 항상 컴포넌트의 이름은 대문자로 시작해야 된다는 사실을 꼭 기억해주시길 바랍니다. 만약 컴포넌트 이름을 정말 꼭 소문자로 사용하고 싶다면, 먼저 대문자로 시작하는 변수에 할당한 뒤 이 변수를 사용하면 됩니다. 하지만 웬만하면 대문자로 사용하는 것을 권장합니다.

5.3.5 컴포넌트 렌더링

컴포넌트를 다 만든 이후에 실제로 렌더링 하려면 어떻게 해야 할까요? 앞에서 배운 것처럼 컴포넌트는 붕어빵 틀의 역할을 합니다. 그렇기 때문에 실제로 컴포넌트가 화면에 렌더링 되는 것은 아닙니다. 컴포넌트라는 붕어빵 틀을 통해 찍어져서 나온 element라는 붕어빵이 실제로 화면에 보이게 되는 것이죠. 그렇다면 렌더링을 위해서는 가장 먼저 컴포넌트로부터 element를 만들어야 되겠죠? 아래 코드는 위에 나왔던 코드와 동일한 코드인데, 주석부분의 설명이 바뀐 것입니다.

// DOM 태그를 사용한 element
const element = <div />;

// 사용자가 정의한 컴포넌트를 사용한 element
const element = <Welcome name="인제" />;

위의 두 줄의 코드는 모두 리액트 element를 만들어내게 됩니다. 그러면 우리는 이제 이 element를 렌더링을 하면 되는 것이죠. 아래 실제 렌더링을 하는 코드를 한 번 보도록 하겠습니다.

function Welcome(props) {
    return <h1>안녕, {props.name}</h1>;
}

const element = <Welcome name="인제" />;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);

위 코드에서는 먼저 Welcome이라는 함수 컴포넌트를 선언하고 있습니다. 그리고 <Welcome name="인제" />라는 값을 가진 element를 파라미터로 해서 Root DOM node의 render()를 호출합니다. 이렇게 하면 리액트는 Welcome컴포넌트에 { name: "Inje" }라는 props를 넣어서 호출하고, 그 결과로 리액트 element가 생성됩니다. 이렇게 생성된 element는 최종적으로 React DOM을 통해 실제 DOM에 효과적으로 업데이트 되고, 우리가 브라우저를 통해서 볼 수 있게 됩니다.


마지막 업데이트: 2025년 08월 26일 02시 56분

이 문서의 저작권은 이인제(소플)에 있습니다. 무단 전재와 무단 복제를 금합니다.

On this page