1. 컴포넌트 만들어 보기에서 우리는 컴포넌트를 만드는 법을 살펴 보았습니다. 컴포넌트를 사용하여 원하는 데이터를 웹 페이지 화면에 그릴 수 있습니다. 그런데, 많은 경우에, 컴포넌트는 개발자에 의해 미리 정해진 데이터를 단순히 그려주는 정도가 아니라, 사용자가 입력하는 값에 따라 다른 데이터를 보여줘야 하는 경우도 있습니다.
한 번, 이런 경우를 상상해 봅시다. 사용자가 자신의 별명과 좋아하는 색깔을 입력하면, 별명에 입력된 색깔을 적용한 텍스트를 렌더링해주는 웹사이트가 있습니다('고릴라', 'blue'을 입력하면 파란색의 '고릴라'라는 글씨를 보여줍니다). 리액트로 이 부분을 구현하려면 어떻게 해야 할까요? 우선은 입력창이 있고, 결과를 그려주는 컴포넌트(<ColoredNickname />
이라고 하겠습니다)가 있겠지요. 그렇다면, <ColoredNickname />
는 사용자가 입력한 값을 받아와 별명 텍스트는 화면에 그리되, 색깔은 컴포넌트의 style에 적용되어야겠지요. 여기서, 입력받은 '별명'과 '색깔'을 어떻게 컴포넌트에 전달할 수 있을까요? 이 역할을 하는 것이 바로 props 입니다.
props는 properties를 줄인 표현으로, 컴포넌트에 어떤 값을 전달할 때 사용합니다. props는 해당 컴포넌트를 사용하는 부모 컴포넌트에서 설정합니다. 이렇게 말로만 해서는 잘 와닿지가 않으니, 예시를 보겠습니다.
말머리에서 언급한 예시의 웹사이트를 리액트로 구현해 봅시다. 웹사이트의 메인 컴포넌트인 <App />
컴포넌트가 있고, 그 안에 컴포넌트가 입력된 별명과 컬러값에 따라 텍스트에 색상을 적용해 주는 <ColoredNickname />
이 있습니다. 아래와 같이 말이예요.
App.js
import React from 'react';
import ColoredNickname from './ColoredNickname';
function App() {
return (
<ColoredNickname name="고릴라" color="blue"/>
);
}
export default App;
여기서, <App />
는 <ColoredNickname />
의 부모 컴포넌트이고, ColoredNickname />
는 <App />
의 자식 컴포넌트입니다. <ColoredNickname />
컴포넌트에 두 가지 파라미터와 value가 설정되어있는 것이 보입니다. name의 value는 '고릴라', color의 value는 'blue' 입니다.
이것을 보고 "ColoredNickname 컴포넌트는 name, color라는 두 가지 props를 받도록 작성되어 있겠구나." 라고 생각하셨다면, 정답입니다. 이처럼, 부모 컴포넌트는 자식 컴포넌트를 품은 상태에서 name과 color라는 props를 설정합니다.
<ColoredNickname />
는 name, color라는 props를 받아와 렌더링해주도록 설정되어 있습니다. 즉, ColoredNickname 함수의 파라미터로 props를 받는 형태로 작성됩니다. 아래와 같이요.
ColoredNickname.js
import React from 'react';
function ColoredNickname(props) {
return(
<div style={{display: 'flex'}}>
<div>나의 별명은: </div>
<div style={{color: props.color}}>{props.name}</div>
</div>
)}
export default ColoredNickname;
props는 JSX 내부에서 {} 기호로 감싸주면 됩니다.
그런데, props값을 컴포넌트에서 조회 또는 사용할 때마다 props.XXX
형태로 사용하는 것은 번거롭습니다. Javascript의 구조 분해 할당(=비구조화 할당) 문법 을 사용해 props 내부 값을 바로 추출할 수 있습니다.
import React from 'react';
function ColoredNickname({ color, nickname }) {
return(
<div style={{display: 'flex'}}>
<div>나의 별명은: </div>
<div style={{color: color}}>{name}</div>
</div>
)
}
export default ColoredNickname;
코드가 조금 더 간결해졌습니다!
만약, <ColoredNickname />
에 전달할 color값과 name값을 지정하지 않았을 경우에 보여줄 기본값을 정하고 싶다면, defaultProps
라는 값을 설정하면 됩니다.
import React from 'react';
function ColoredNickname({ color, nickname }) {
return(
<div style={{display: 'flex'}}>
<div>나의 별명은: </div>
<div style={{color}}>{name}</div>
</div>
)
}
//props가 입력되지 않을 때 출력할 기본값 설정
ColoredNickname.defaultProps = {
name: "닉네임",
color: "green"
}
export default ColoredNickname;
App 컴포넌트에서 name, color 없이 ColoredNickname 컴포넌트를 렌더링하면 다음과 같이 나옵니다.
App.js
import logo from './logo.svg';
import './App.css';
import ColoredNickname from './ColoredNickname';
function App() {
return (
<ColoredNickname />
);
}
export default App;
컴포넌트 태그 사이의 내용을 보고싶을 때는, props.children
이라는 개념을 사용하면 됩니다. children
이란, 한 컴포넌트의 태그와 태그 사이에 들어간 어떠한 값을 의미합니다.
이제, 우리는 2. props의 기본값 설정
의 마지막에 나온 나의 별명 텍스트가 검은 테두리가 있는 네모난 영역 안에 나오도록 하고 싶습니다. 이를 위해, props.children을 사용하는 컴포넌트를 아래와 같이 만들어 봅시다.
(참고로, App.js
, ColoredNickname.js
, Wrapper.js
는 모두 /src
디렉터리 안에 있습니다!)
Wrapper.js
import React from 'react';
function Wrapper() {
const style = {
border: '2px solid black',
padding: 16,
};
return <div style={style}></div>
}
export default Wrapper;
이 컴포넌트를 App에서 사용해 보겠습니다.
import logo from './logo.svg';
import './App.css';
import Wrapper from './Wrapper';
import ColoredNickname from './ColoredNickname';
function App() {
return (
<Wrapper>
<Hello />
</Wrapper>
);
}
export default App;
자, 한 번 브라우저를 열어 결과를 볼까요?
이럴 수가! 테두리 있는 네모 영역이 나오긴 나왔지만, <ColoredNickname />
컴포넌트는 보이지 않네요. 이를 해결하려면, Wrapper에서 props.children
을 렌더링하면 됩니다.
import React from 'react';
function Wrapper(props) {
const style = {
border: '2px solid black',
padding: 16,
};
return <div style={style}>{props.children}</div>
}
//비구조화 할당을 사용하여 간결하게 작성하면 아래와 같습니다.
function Wrapper({ children }) {
const style = {
border: '2px solid black',
padding: 16,
};
return <div style={style}>{children}</div>
}
export default Wrapper;
Wrapper 안에 childeren을 렌더링 해 주니 결과가 아래와 같이 잘 나옵니다.
App.js
에서 <Wrapper />
컴포넌트 안에 <ColoredNickname />
컴포넌트가 들어가 있었죠? 이 <ColoredNickname />
컴포넌트가 <Wrapper />
의 children입니다. 이처럼, props.children
은 컴포넌트 태그 안에 있는 내용을 렌더링 해 줍니다.
이번 장의 내용을 정리하겠습니다. 이번 장에서는 props로 컴포넌트에 값을 전달하여 브라우저에 렌더링 해 보았습니다. 또한, 컴포넌트 태그 안에 있는 내용을 렌더링하기 위해 props.children이라는 개념을 사용했습니다.
props.
을 생략해도 되어 코드가 보기에 간결하다.컴포넌트명.defaultProps = { ... }
와 같이 defaultProps
를 설정해 준다.