이번에 회사를 그만두고 구인을 하게 되면서, 많은 회사에서 react
를 선택하고 사용하고 있음을 느꼈다. 실무해서 사용해본 경험도 벌써 1년이나 지났고, 그동안 엄청난 버전업을 하였기에
이번 기회에 간단한 앱을 만들면서 다시 한번 react
에 대해 복습하고 그 과정을 포스팅하고자 한다.
React
는 페이스북이 개발한 UI 라이브러리이다. React
의 핵심은 재사용 가능한 UI의 생성이다. 이 재사용 가능한 UI를 컴포넌트화 하여 더 복잡한 UI 화면을 구성한다. 일반적인 MVC, MV* 패턴에서 View만 담당한다.
이외의 모델이나 다른 부분은 다른 라이브러리를 가져와 조합하여 사용해도 무방하다.
React
는 DOM을 Virtual DOM
을 이용해 표현하다. React
는 모델이 업데이트 되면, 화면을 re-render 한다. 일반적으로 jQuery를 이용해 DOM을 업데이트하는 상황을 생각해보자.
모델이 업데이트됨으로써 모델이 영향을 미치는 DOM 부분만 선택자를 통해 업데이트 한다. 하지만 React
는 해당 부분을 모두 다시 re-render 해버린다. 이렇게 되면 당연히 reflow, repaint상황이 더 많이 발생할 테고,
이에 따른 성능 문제는 없을까?
React
는 Virtual DOM
을 사용하여 이러한 걱정을 해소한다. 후술한 JSX
를 사용하여 최종 결과물(업데이트된 모델이 반영된 UI)에 대해서만 선언적으로 기술한다.
이후 모델의 업데이트가 발생하면 실제 DOM 트리에 반영하는 것이 아닌 가상 DOM 트리에만 적용한 뒤 최종적으로 이 두 DOM 트리를 비교하여 변경된 부분만 실제 DOM에 반영한다.
따라서 DOM을 직접 조작할 때 발생할 수 있는 reflow, repaint에 의한 성능 문제는 걱정하지 않아도 된다.
React
의 핵심은 재사용 가능한 UI의 생성이라고 했다. 모든 UI는 컴포넌트화 하여 구성한다. 아래의 코드는 여러개의 컴포넌트를 조합하여 하나의 어플리케이션을 구성하는 예제이다.
import React, { Component } from 'react';
class Header extends Component {
render() {
return (
<div>
<h1>Hello world!</h1>
</div>
);
}
}
export default Header;
import React, { Component } from 'react';
class Content extends Component {
render() {
return (
<div>
content...
</div>
);
}
}
export default Content;
import React, { Component } from 'react';
class Footer extends Component {
render() {
return (
<div>
footer
</div>
);
}
}
export default Footer;
import React, { Component } from 'react';
import Header from './Header';
import Content from './Conent';
import Footer from './Footer';
class App extends Component {
render() {
return (
<div>
<Header></Header>
<Content></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
각각 Header, Content, Footer 라는 컴포넌트를 만들어, App에서 사용하도록 하였다. 이렇게 컴포넌트화 하면 필요한 곳에서 얼마든지 재사용할 수 있다. 심화 내용은 실제 프로젝트 포스트를 작성하면서 소개하도록 하겠다.
JSX
는 Javscript와 XML을 결합한 확장 문법이라고 볼 수 있다. 이 문법을 사용하여 자바스크립트 코드에서 마크업을 할 수 있고, 손쉽게 변수나 함수를 태그 안에 바인딩 할 수 있다.
JSX
는 필수 사항이 아니지만, 왠만하면 사용하기를 권장한다. (초심자라면 특히.. 인터넷에 돌아다니는 거의 모든 react 예제는 JSX
로 작성되어 있다.)
이번 포스트에서는 JSX
를 어떻게 사용하는지 간단하게 알아보고, 심화 내용은 실제 프로젝트 포스트를 작성하면서 소개하도록 하겠다.
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div></div>
);
}
}
export default App;
먼저 다른 코드는 다 무시하고 render()
내부의 return
구문만 살펴보자. return
내부에 HTML 마크업이 되어 있는 것을 확인할 수 있다.
기본적으로, 기존과 동일하게 render
함수에서 원하는 UI를 마크업하여 return
값으로 지정하면 된다. (참 쉽죠?) 유의해야 할 점은,
JSX
에서 마크업을 할 때 몇가지 지켜야 할 규칙이 있다.
JSX
는 무조건 하나의 요소로 감싸야 한다. 즉 최상위 요소는 1개여야만한다.
// 이 코드는 에러가 발생합니다.!!
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div></div>
<div></div>
);
}
}
export default App;
위 코드와 같이 최상위에 요소가 2개 있는 경우 에러를 발생한다.
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
<div></div>
<div></div>
</div>
);
}
}
export default App;
위 코드와 같이 하나의 요소로 감싸야한다. css와 같은 스타일 가이드가 미리 나와서 다른 요소로 감싸기 곤란한 상황이라면, <Fragments>
태그를 사용한다.
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<Fragments>
<div></div>
<div></div>
</Fragments>
);
}
}
export default App;
JSX
를 사용하면 변수나 함수를 손쉽게 바인딩 할 수 있다고 했다. 아래 코드를 살펴보자.
import React, { Component } from 'react';
class App extends Component {
clickButton(e){
console.log('clicked');
}
render() {
const name = 'dohee';
return (
<div>
<h1>Hello {name}!</h1>
<button onClick={this.clickButton}>click me</button>
</div>
);
}
}
export default App;
{ }
로 표현된 부분을 자세히 보자. { }
를 사용하면 자바스크립트 표현식을 사용 할 수 있다. 이 표현식을 가지고 조건부 렌더링 또한 가능하다.
import React, { Component } from 'react';
class App extends Component {
render() {
let condition = true;
return (
<div>
{
condition ?
<div>true</div>
<div>false</div>
}
</div>
);
}
}
export default App;
주의해야 할 점은, if문은 사용할 수 없다는 것이다. 위와 같이 삼항 연산식을 사용하거나 즉시실행함수(IIFE)를 사용해야한다.
태그 내부에 Style 속성을 사용하게 될 경우, 아래와 같이 사용해야한다.
import React, { Component } from 'react';
class App extends Component {
render() {
const style = {
marginTop: 10,
color: 'blue'
};
return (
<div style={style}>inline style</div>
);
}
}
export default App;
React
에서는 데이터가 부모 컴포넌트에서 자식컴포넌트로 한 방향으로만 흐른다. two-way data bind를 사용하는 AngularJs
를 경험해본 개발자라면, 이 개념에 적응하는데 시간이 좀 걸릴 수 있다.
React
의 단방향 데이터의 흐름에서 다음과 같은 두가지 개념을 사용한다.
부모 컴포넌트에서 자식 컴포넌트로 전달하는 값이다. 이 Props는 전달받을수만 있고 수정은 불가능하다.
import React, { Component } from 'react';
import Child from './Child';
class Parent extends Component {
render() {
const name = 'dohee';
return (
<Child data={name}></Child>
);
}
}
export default Parent;
위와 같이 Parent
컴포넌트에서 name
이라는 Props
를 Child
컴포넌트에 전달하였다.
import React, { Component } from 'react';
class Child extends Component {
render() {
return (
<div>{this.props.name}</div>
);
}
}
export default Child;
Child
컴포넌트에서 전달받아 사용하는 코드이다. this.props
로 접근하여 사용할 수는 있지만, 값을 변경할 수는 없다.
Props
와는 달리 State
는 변경 가능한 컴포넌트의 상태값이다. 이 State
가 변경되면, 컴포넌트의 re-render가 발생한다.
import React, { Component } from 'react';
class App extends Component {
state = {
name : ''
}
clickButton(){
this.setState({name: 'dohee'});
}
render() {
return (
<div>
name: {this.state.name}
<button onClick={this.clickButton.bind(this)}>change name</button>
</div>
);
}
}
export default App;
버튼을 클릭하면, setState
를 호출하여 state
값을 변경하는 코드이다. clickButton
함수에 의해 state
값이 변경되고 나면, render()
함수가 호출되고 컴포넌트가 re-render되어 변경된 이름이 출력될 것이다.
여기까지 기본적인 React
의 기초와 특징에 대해서 포스팅하였다. 다음 포스팅부터는 mac의 미리 알림 앱을 React
로 구현하는 프로젝트를 위주로 구성해보려고 한다. 이 포스팅은 아래의 링크를 참고하여 작성하였다.