React는 프론트엔드 개발을 위한 Javascript 오픈소스 라이브러리이다.
React 특징
- 선언형 : 하나의 파일에 HTML,CSS, JS를 명시적으로 작성할 수 있게 JSX를 활용한 선언형 프로그래밍을 지향한다.
- 컴포넌트 기반 : 하나의 기능 구현을 위한 컴포넌트를 기반으로 개발하며, 컴포넌트로 분리하면서 서로 독립적이고 재사용 가능하게 한다. 기능 자체에 집중하여 개발 가능.
- 범용성 : Javascript 프로젝트 어디에든 유연하게 적용될 수 있다.
- 오직 View만 신경쓰는 라이브러리이다. VirtualDOM 사용
참고
VirtualDOM : 실제 DOM에 접근하여 조작하는 대신 이를 추상화한 자바스크립트 객체를 고성하여 사용한다.(DOM의 가벼운 사본과 비슷)
이로써 DOM 처리 횟수를 최소화하고 효율적으로 진행한다.
단, 지속적으로 데이터가 변화하는 대규모 어플리케이션 구축에 리액트가 적합하다. 무조건 VirtualDOM이 빠른건 아니다.진행 절차
- 데이터를 업데이트하면 전체 UI를 VirtualDOM에 리렌더링한다.
- 이전 VirtualDOM에 있던 내용과 현재 내용을 비교한다.
- 바뀐 부분만 실제 DOM에 적용한다.
JSX는 JavaScript가 확장된 문법이지만, 브라우저가 바로 실행할 수 있는 JavaScript 코드가 아니다.
Babel로 JSX를 브라우저가 이해할 수 있는 일반 JavaScript로 변환 후, JavaScript를 브라우저가 읽고 화면에 렌더링할 수 있게 한다.
왜 최신 자바스크립트로 작성된 코드를 변환해야 하는가?
구버전 웹 브라우저와 호환을 하기 위해 변환한다. 이때에도 바벨이라는 도구를 사용하여 ES5 형태의 코드로 변환시켜 준다.
컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야한다.
-> 이유: Virtual DOM에서 컴포넌트 변화 감지시 효율적으로 비교하기 위해.
자바스크립트 표현식 사용시 JSX 내부에서 { } 로 코드를 감싸야한다.
엘리먼스 클래스 사용 시, class 대신 className 으로 표기
If대신 조건부 연산자 사용
사용자 정의 컴포넌트는 대문자로 시작 PascalCase 사용
여러개의 HTML 엘리먼트 표시할 때, map() 함수 이용
주석은 표기가 다름
function Hello(){ //5번
const name = "React"
return(
<div> //1번
<h1>One</h1>
<h2>Two</h2>
<h3>{name}</h3> //2번
<div className="greeting">Hello!!</div> //3번
<div>{(1+1 === 2) ? (<p>정답</p>) : (<p>오답</p>) }</div> // 4번
{/* 주석은 이렇게 작성 */} // 7번
</div>
)
}
추가적으로 리액트 v16 이상에서는 Fragment 사용가능
import {Fragment} from 'react';
function Hello(){
return(
<Fragment>
<h1>One</h1>
<h2>Two</h2>
</Fragment>
)
}
React에서 여러 데이터를 렌더링 할 때 map 메서드를 사용한다.
return 문 안에서 map 메서드를 사용할 수도 있다. JSX를 사용하면 중괄호 안에 모든 표현식을 포함할 수 있기 때문에 map 메서드의 결과를 return문 안에 인라인으로 처리할 수 있다.
다만, 코드 가독성을 위해 변수로 추출할지 아니면 인라인에 넣을지는 개발자가 판단해야 한다.
React에서 map 메서드 사용 시, key 속성을 넣지 않으면 리스트의 각 항목에 key를 넣어야 한다는 경고가 표시된다. key 속성의 위치는 map 메서드 내부에 있는 엘리먼트 즉, 첫 엘리먼트에 넣어주면 된다.
//1. map() 처리 결과를 변수에 담는 경우
function Blog() {
const postToElement = (post) => (
<div>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
const blogs = posts.map(postToElement);
return <div className="post-wrapper">{blogs}</div>;
}
//2. postToElement라는 함수로 나누지 않는 경우
function Blog() {
// postToElement라는 함수로 나누지 않고 아래와 같이 써도 무방합니다.
const blogs = posts.map((post) => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
));
return <div className="post-wrapper">{blogs}</div>;
}
//3. 추가적으로 컴포넌트를 넣을 수도 있다.
<ul className="tweets">
{tweets.map((el) => {
return <Tweet tweet={el} key={el.id} />;
})}
</ul>