1. Component
리액트는 컴포넌트 기반의 구조이다.
하나의 컴포넌트는 또 다른 여러 컴포넌트의 조합으로 구성될 수 있다.
에어비앤비 페이지처럼 작은 컴포넌트들이 모여서 하나의 컴포넌트를 구성한다.
또 이러한 컴포넌트들이 모여서 전체 페이지를 구성하기 때문이다.
리액트 컴포넌트의 입력은 props가 되고, 출력은 React element가 된다.
2. Props
리액트 컴포넌트 입력으로 들어가는 props에 대해 살펴보자
prop은 property(속성)라는 영어단어를 줄여서 쓴 것이다.
즉, prop은 react 컴포넌트의 속성이다. 마치 붕어빵에 들어가는 재료와 같다.
같은 붕어빵이라도 어떤 맛을 넣냐에 따라 다른 맛이 난다.
에어비앤비 컴포넌트도 겉은 같은 모습이지만, 안에 들어가는 정보에 따라 다르게 나타난다.
3. Props 특징
props에 중요한 특징은 read-only이다. 읽을 수밖에 없다는 뜻은 값을 변경할 수 없다는 뜻이기도 하다.
잠시 자바스크립트 함수의 속성에 대해 짚고 넘어가보자.
자바스크립트 파라미터 a,b를 항상 같은 입력값을 준다면 항상 같은 출력값을 출력하는 pure한 함수이다.
그렇다면, pure하지 않은 경우는 어떤 경우일까?
계좌에서 출금하는 함수인데, 출금 금액과 계좌 총액이 매번 달라지므로 impure한 함수라고 볼 수 있다.
이렇게 pure 함수와 impure 함수를 본 이유는 리액트 컴포넌트의 정의와 관련되어 있기 때문이다.
모든 리액트 컴포넌트는 그들의 props에 관해서 pure 함수와 같은 역할을 해야한다.
즉 모든 리액트 컴포넌트는 props를 직접 바꿀 수 없고, 같은 props에 대해서는 항상 같은 결과를 보여줘야 한다.
4. Props 사용법
컴포넌트 내부에 키:값 형태로 props(속성)가 전달되고 있다.
또한 각 속성에 {} 중괄호를 사용한 것도 있고, 사용하지 않은 것도 있다.
우리는 앞서 중괄호 안은 자바스크립트 코드가 들어간다고 배웠다. 때문에 props 값을 넣을 때에도 문자열 이외의 정수, 변수, 다른 컴포넌트들이 들어갈 땐 {} 중괄호를 쓴다. 물론 문자열도 {} 중괄호로 감싸도 상관은 없다.
props로 컴포넌트는 이렇게 들어간다.
props는 이와 같은 형태의 자바스크립트 코드가 된다.
여기까지는 jsx 코드를 사용해 props를 넘긴 것이고, jsx 코드를 사용하지 않으면 다음과 같이 props를 넘겨준다.
5. Component 만들기
리액트는 함수 컴포넌트와 클래스 컴포넌트로 나뉜다. 하지만 클래스 컴포넌트가 사용하기 어렵다는 의견이 많아서 이후에는 함수 컴포넌트를 개선해서 주로 사용하게 되었다. 함수 컴포넌트를 개선하는 과정에서 나온 것이 훅이라는 개념이다.
5-1) 함수 컴포넌트
간단한 코드를 장점으로 가진다.
5-2) 클래스 컴포넌트
자바스크립트 ES6의 클래스라는 것을 사용해 만들어진 형태의 컴포넌트이다.
5-3) 컴포넌트의 이름
컴포넌트의 이름을 지을 땐 항상 대문자로 시작해야 한다.
만약 Welcome 컴포넌트를 welcome이라고 이름 지었다면 컴포넌트가 아니라 돔 태그라고 인식했을 것이다.
결과적으로 에러가 발생하거나 우리가 원하는대로 나오지 않게 될 것이다.
6. Component 렌더링
컴포넌트를 만든 다음에 렌더링은 어떻게 할까?
element는 Welcome 컴포넌트 속 props로 name을 주고 있다.
그런 element 돔태그를 render한다고 선언하면, Welcome 엘리먼트에서는 전달받은 props를 사용하여 리액트 엘리먼트를 생성한다.
이렇게 생성된 리액트 엘리먼트는 리액트 돔을 통해 실제 돔에 효과적으로 업데이트 되고, 우리가 브라우저를 통해 볼 수 있게 된다.
7. Component 합성
여러 개의 컴포넌트를 합쳐서 하나의 컴포넌트를 만드는 과정을 컴포넌트 합성이라고 한다.
같은 컴포넌트에 다른 props를 주어서 3개의 컴포넌트로 App컴포넌트를 이루고 있다.
8. Component 추출
합성과 반대로 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 나눌 수도 있다. 이런 과정을 컴포넌트 추출이라고 부른다.
컴포넌트 추출을 잘 활용하게 되면 컴포넌트의 재사용성이 올라가게 된다.
왜냐하면 컴포넌트가 작아질 수록 해당 컴포넌트의 기능과 목적이 명확해지고, props도 단순해지기 때문에 다른 곳에서 사용할 수 있는 확률이 높아지기 때문이다. 재사용성이 올라가면 개발속도도 함께 향상된다.
이 컴포넌트에서 컴포넌트를 하나씩 추출해보자.
8-1) avatar 추출
프로필 이미지를 avatar를 이용해 나타내고 있다.
함수 컴포넌트로 Avatar를 만들어주었다.
또한 props로 author 대신 user을 사용해줬다. 이처럼 보편적인 단어를 사용한 것은, 재사용성을 고려한 것이다.
추출된 Avatar 컴포넌트를 다시 적용한 모습이다.
8-2) userInfo 추출
userInfo를 추출하여 함수 컴포넌트로 만들었다.
함수 컴포넌트를 다시 적용한 모습이다. 좀 더 가벼워진 코드의 모습이다.
전체 구조이다.
나머지 코멘트 텍스트와 날짜도 추출해내도 된다.
컴포넌트를 어느정도 수준까지 추출해도 괜찮을지 정해진 기준은 없다. 하지만 기능 단위로 구분하는 것이 좋고, 나중에 곧바로 재사용 가능한 형태로 추출하는 것이 좋다. 재사용이 가능한 컴포넌트를 많이 가지고 있을수록 개발 속도가 빨라진다.
9. 댓글 컴포넌트 만들기
[comments.jsx]
import React from "react";
const styles={
wrapper:{
margin:8,
padding:8,
display:"flex",
flexDirection:"row",
border : "1px solid grey",
borderRadius: 16,
},
imageContainer:{},
image:{
width:50,
height:50,
borderRadius:25,
},
contentContainer:{
marginLeft:8,
display:"flex",
flexDirection:"column",
justifyContent:"center",
},
nameText:{
color:"black",
fontSize:16,
fontWeight:"bold",
},
commentText:{
color:"black",
fontSize:16,
},
};
function Comment(props){
return(
<div style={styles.wrapper}>
<div style={styles.imageContainer}>
<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png"
style={styles.image}/>
</div>
<div style={styles.contentContainer}>
<span style={styles.nameText}>{props.name}</span>
<span style={styles.commentText}>{props.comment}</span>
</div>
</div>
);
}
export default Comment;
[commentList.jsx]
import React from "react";
import Comment from "./Comment";
function CommentList(props){
return(
<div>
<Comment name={"이인재"} comment={"안녕하세요, 소플입니다."}/>
<Comment name={"유재석"} comment={"리액트 재미있어요~!"}/>
</div>
);
}
export default CommentList;
이런식으로 일일이 데이터를 써줘도 되지만 map 함수를 이용해 데이터를 돌려줄 수도 있다.
[commentList.jsx]
import React from "react";
import Comment from "./Comment";
const comments=[
{
name: "이인재",
comment:"안녕하세요, 소플입니다.",
},
{
name: "유재석",
comment:"리액트, 재미있어요~!",
},
{
name: "강민경",
comment:"저도 리액트 배워보고 싶어요!!",
},
]
function CommentList(props){
return(
<div>
{
comments.map((comment)=>{
return(
<Comment name={comment.name} comment={comment.comment}/>
);
})
}
</div>
);
}
export default CommentList;
comments라는 댓글 객체 리스트를 만들고, map함수를 이용해 돌려준다.
[index.js]
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import CommentList from './chapter_05/CommentList';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<CommentList/>
</React.StrictMode>
);
reportWebVitals();
결과 화면이다.
'FE > React' 카테고리의 다른 글
[React] styled-components (0) | 2023.06.08 |
---|---|
[React] react-router-dom (0) | 2023.06.08 |
[React] Elements (0) | 2023.06.01 |
[React] 상품 상세페이지 만들기2 : postman id 설정 (0) | 2023.05.02 |
[React] 상품 상세페이지 만들기 : 어떻게 여러 페이지를 한 번에 구분할 수 있을까? (0) | 2023.04.27 |