React 5. Component와 Props

@t189216·2024년 3월 7일

😎 프론트엔드

목록 보기
17/31

리액트에서는 모든 페이지가 컴포넌트로 구성되어 있고, 하나의 컴포넌트는 또 다른 여러 개의 컴포넌트의 조합으로 구성될 수 있습니다.

React Component


자바스크립트의 함수가 입력을 받아서 출력을 내뱉는 것처럼, 리액트 컴포넌트도 입력을 받아서 정해진 출력을 내뱉습니다.

리액트 컴포넌트를 하나의 함수라고 생각할 수도 있습니다. 사실 정확하게는 다릅니다.

리액트 컴포넌트에서의 입력은 props, 출력은 리액트 엘리먼트가 됩니다. 어떠한 속성들을 입력으로 받아서 그에 맞는 리액트 엘리먼트를 생성하여 리턴해줍니다.

객체지향의 클래스와 인스턴스 개념과 비슷하게, 컴포넌트라는 틀에서 엘리먼트가 나온다고 생각해도 됩니다.

출처

Props


Property의 준말로, Component의 속성을 말합니다. Props 는 Component에 전달할 다양한 정보를 담고 있는 자바스크립트 객체입니다.

Props 는 리액트 컴포넌트가 엘리먼트를 생성하기 위해 사용하는 값입니다. 값을 변경할 수 없기에 다른 Props값을 엘리먼트를 생성하려면 새로운 값을 컴포넌트에 전달하여 새로 엘리먼트를 생성하야 합니다. 이 과정에서 엘리먼트가 다시 렌더링 됩니다.

모든 리액트 컴포넌트는 Props를 직접 바꿀 수 없고, 같은 Props에 대해서는 항상 같은 결과(리액트 엘리먼트)를 보여준다.

Props 사용법 #1

function App(props) {
    return (
        <Profile
            name="Ellie"
            introduction="Hi, I'm Ellie."
            viewCount={1500}
        />
    );
}

여기서 Profile 컴포넌트에 name, introduction, viewCount라는 속성이 있습니다.

JSX에서 중괄호를 사용하면 무조건 자바스크립트 코드가 들어간다.

마찬가지로 props에 값을 넣을 때에도 문자열 이외에 정수, 변수 그리고 다른 컴포넌트 등이 들어갈 경우에는 중괄호를 사용해서 감싸주어야 합니다.

{
    name: "Ellie",
    introduction: "Hi, I\'m Ellie.",
    viewCount: 1500
}

속성의 값들이 Profile 컴포넌트의 props로 전달되며, props는 이런 형태의 자바스크립트 객체가 됩니다.

Props 사용법 #2

중괄호를 사용해서 다음과 같이 props의 값으로 컴포넌트도 넣을 수 있습니다.

function App(props) {
    return (
        <Layout
            width={2500}
            height={1440}
            header={
                <Header title="환영합니다." />
            }
            footer={
                <Footer />
            }
        />
    );
}

Layout 컴포넌트의 props로 정수 값을 가진 width, height와 리액트 엘리먼트로 header, footer가 들어오게 됩니다.

Component 만들기

리액트에서 컴포넌트는 크게 클래스 컴포넌트와 함수 컴포넌트로 나뉩니다.

출처

함수 컴포넌트(Function Component)

function Welcome(props) {
    return <h1>Hi, I\'m {props.name}</h1>;
}

클래스 컴포넌트(Class Component)

class Welcome extends React.Component {
    render() {
        return <h1>Hi, I\'m {props.name}</h1>;
    }
}

함수 컴포넌트와 다르게 리액트의 모든 클래스 컴포넌트 는 React.Component를 상속받아서 만듭니다.

↗️ 클래스 컴포넌트와 함수 컴포넌트의 차이

⚠️ 컴포넌트 네이밍 주의사항 ⚠️
Component 이름은 항상 대문자로 시작해야 한다.
(React는 소문자로 시작하는 Component를 DOM태그로 인식합니다.)

Component 렌더링

렌더링하기 위해 가장 먼저 컴포넌트로부터 엘리먼트를 만들어야 합니다.

function Welcome(props) {
    return <h1>Hi, I'm {props.name}</h1>
}

const element = <Welcome name="Ellie" />;
ReactDOM.render(
    element,
    document.getElementById('root')
);

Welcome 함수 컴포넌트에 name="Ellie"라는 props를 넣어서 호출하고, 그 결과로 리액트 엘리먼트가 생성됩니다.

Component 합성과 추출

리액트에서는 복잡한 화면을 여러 개의 컴포넌트로 나눠서 구현할 수 있습니다. 또한 여러 개의 컴포넌트를 합쳐서 또 다른 컴포넌트를 만드는 것을 컴포넌트 합성 이라고 합니다.

function Welcome(props) {
    return <h1>Hi, I'm {props.name}</h1>
}

function App(props) {
    return (
        <div>
            <Welcome name="Mike" />
            <Welcome name="Steve" />
            <Welcome name="Jane" />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

props값을 다르게 해서 Welcome 컴포넌트를 3번 사용하고 있습니다. 그러므로 App 컴포넌트는 Welcome 컴포넌트 3개를 포함하고 있는 컴포넌트가 됩니다.

컴포넌트 합성과 반대로 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 나눌 수도 있습니다. 이를 컴포넌트 추출 이라고 합니다.

function Comment(props) {
    return (
        <div className="comment">
            <div className="user-info">
                <img className="avatar"
                    src="{props.author.avatarUrl}"
                    alt="{props.author.name}"
                />
                <div className="user-info-name">
                    {props.author.name}
                </div>
            </div>

            <div className="comment-text">
                {props.text}
            </div>

            <div className="comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}

이 컴포넌트는 댓글을 표시하기 위한 컴포넌트로 내부에 작성자의 프로필 이미지와 이름 그리고 댓글 내용과 작성일을 포함하고 있습니다.

function Avatar(props) {
    return (
        <img className="avatar"
        src="{props.user.avataUrl}" 
        alt="{props.user.name}"
        />
    );
}

추출한 Avatar 컴포넌트입니다.

function Comment(props) {
    return (
        <div className="comment">
            <div className="user-info">
                <Avatar user={props.author} />  // 변경됨
                <div className="user-info-name">
                    {props.author.name}
                </div>
            </div>

            <div className="comment-text">
                {props.text}
            </div>

            <div className="comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}

다시 Comment 컴포넌트에 반영했습니다. 가독성이 높아진걸 확인할 수 있습니다.

추출한 컴포넌트를 다른 컴포넌트와 같이 추출할 수 있습니다.

function UserInfo(props) {
    return (
        <div className="user-info">
            <Avatar user={props.user} />
            <div className="user-info-name">
                {props.user.name}
            </div>
        </div>
    );
}

사용자의 정보를 담고 있는 부분을 UserInfo라는 컴포넌트로 추출한 것입니다. Avatar 컴포넌트도 함께 추출된 것을 볼 수 있습니다. 또한 재사용이 가능하도록 좀 더 보편적인 의미를 가진 user를 사용했습니다.

function Comment(props) {
    return (
        <div className="comment">
            <UserInfo user={props.author} />  // 변경됨
            <div className="comment-text">
                {props.text}
            </div>
            <div className="comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}

다시 Comment 컴포넌트에 반영했습니다.

컴포넌트를 어느 정도 수준까지 추출하는 것이 좋은지에 대해 정해진 기준은 없습니다. 기능 단위로 구분하는 것이 좋고 나중에 곧바로 재사용이 가능한 형태로 추출하는 것이 좋습니다.

profile
Today I Learned

0개의 댓글