정신없는 추석 연휴의 마지막쯔음에, 커리큘럼을 다시 살펴보았다. 정신없는 NodeJS학습이 끝나고 바로 리액트 스프린트에 들어가는 일정. 리액트가 정확히 무엇인지는 몰라도 개발을 공부하기로 마음먹었을때부터 이 알고리즘이라는 놈은 인스타,페북 등 온갖 곳을 통해 리액트를 배워야한다는 이야기를 뿜어내셨다. 덕분에 이 기술이 정확히 무엇인지는 알지 못해도 최근 개발 트렌드에서 상당히 중요한 역할을 하는 친구라는 것 정도는 조금이나마 알 수 있었다. 그리고 드디어 그 리액트를 만나게 되었다.
리액트를 들어가기 전 랩탑에 이제 잘 부탁한다는 의미로 리액트 스티커를 붙였다. 내가 이 스텍을 원활하게 사용한 뒤에 붙이는것도 의미가 있겠지만야, 그러면 내가 언제 이 스티커를 붙이겠나... 'Hello world'와 함께 리액트 스티커를 JS 아래 살포시 내려놓았다. 안녕 리액트? 너도 날 엄청 괴롭히겠지. 그래도 어쩌겠니, 지지고 볶고 잘 지내보자.
리액트는, 유저 인터페이스를 만드는 데 사용되는 프론트앤드 오픈 소스 자바스크립트 라이브러리다. 모던웹 환경은 수많은 상태관리가 필요하다. 리액트는 컴포넌트 단위로 상태의 변경을 관리하는데 최적화된 라이브러리다. 자바스크립트 라이브러리라는 말 처럼, 리액트는 이 상태관리에 있어서 ES6문법을 기반으로, JSX 문법을 활용한다.
리액트를 시작하는 방법은 공식홈페이지를 통해 상세하게 서술되어있다.
리액트 프로젝트를 실행하는 간단한 방법을 서술하면, (npx 기준)
npx create-react-app my-app
cd my-app
npm start
해당 my-app폴더에 리액트 프로젝트가 생성되며, 실행후는 별도 호스트를 지정하지 않을시 http://localhost:3000 을 통해 결과를 확인할 수 있다.
위의 방법과는 별도로, react를 글로벌로 설치하고, 프로젝트를 생성하고자하는 폴더에서 create-react-app .
을 입력하면 해당 폴더에 바로 프로젝트를 생성할수도있다.다만 npx로 설치시 프로젝트마다 항상 최신 버전을 유지할 수 있다.
JSX는 (Javascript + XML)라는 자바스크립트 확장 문법으로, xml형태로 코드를 작성시 Babel이 이를 자바스크립트 형태로 변환한다. 리액트의 모든 코드가 JSX로 작성해야 하는것도 가능하지만, 효율적인 UI 관리를 위해서는 JSX를 사용하는것이 좋다.
JSX는 중괄호 활용을 통해 모든 자바스크립트 표현식을 사용할 수 있다.
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
...
const root = document.getElementById('root');
ReactDom.render(element,root);
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
const root = document.getElementById('root');
ReactDom.render(element,root);
const element = <img src={user.avatarUrl} />;
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
다른 특징들에 대한 상세한 설명은
리액트 공식 홈페이지 - JSX 소개
리액트의 흐름을 이해하는데 가장 중요한 포인트는 (내맘대로) Render다.
리액트는 작성된 리액트 컴포넌트를 모아 html의 root 안에 Render, 말 그대로 끼워넣는다. 또 다른 리액트 Render에 있어서 중요한 점은, 변경사항이 있을시, 이전의 엘리먼트와 상태를 비교해 변경된 경우에만 그 부분에 한하여 DOM을 업데이트하는데 있다.
import React from 'react';
function App(){
return (
<div>
<h1> hello world </h1>
</div>
);
}
export default App;
App() 함수는 함수 내부를 통해 html 엘리먼트를 반환하고 있다. 그리고 export를 통해시 app 함수를 사용할 수 있으며, ReactDOM.render()를 통해서 해당 함수에서 리턴하는 엘리먼트를 화면에서출력할 수 있게 한다. 따라서, 컴포넌트를 한마디로 정의하면, React Element를 Return하는 함수 라고 할 수 있다.
컴포넌트는 위에서 정의한것과같이, 함수이기 때문에, 자바스크립트의 기본적인 함수 작성방법에 따라 만들수도 있으며, ES6 Class를 활용해 만들수도 있다.
function Welcome(props) { //함수 컴포넌트
return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component { //클래스 컴포넌트
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
컴포넌트는 Props와 State라는 두 가지 인스턴트 속성을 갖는다. 그 중 Props는 컴포넌트에서 컴포넌트로 전달하는 데이터를 말한다.
function Food(props){
return <h1> I Live {props.food}</h1>
}
function App(){
return (
<div>
<Food food="pizza" />
</div>
)
}
export default App;
다음 App컴포넌트는 내부에서 Food 컴포넌트를 실행시키고있다. 이때 Food컴포넌트는 props 객체의 food property를 받아 출력하는데, <Food food="pizza" />
에서 Food는 food='pizza'를 props.food로 전달한다. props는 다음과 같이 재활용도 가능하다.
...(생략)
function App(){
return (
<div>
<Food food="pizza" /> //다음과 같이
<Food food="ramen" /> //재활용이
<Food food="coffe" /> //가능하다
</div>
)
}
export default App;
Props의 특징
- 데이터 단일 읽기 전용 객체다.
- 모든 React 컴포넌트는 자신의 Props를 다룰때 반드시 순수함수(Pure function)처럼 동작해야 한다.
( 불가변성을 유지해야한다)- 컴포넌트는 반드시 대문자로 시작해야한다.
State란, Props와 반대로 가변적으로 다루어야하는 데이터로, class형 컴포넌트에서 사용할 수 있다. 클래스형 컴포넌트에서 state는 다음과 같이 선언할 수 있다.
class App extends React.Component {
state = {
}; //es7 문법으로, 이는 es6의 아래와 같다.
constructor(props){
super(props)
this.state={ }
}
render(){
return(
)
}
}
export default App;
(일반적으로) Props는 불변적인것, State는 가변적인 데이터를 담는데 사용한다.
State의 특징
- 리액트는 State의 직접적인 상태변화를 줄 수없다(렌더링되지 않는다)
- State를 지정할 수 있는 유일한 공간은 constructor다.
- state의 업데이트는 비동기적으로 이루어진다.
- State의 업데이트는 병합된다.
state는 언급한것처럼 가변적이다. 이 데이터를 다루기 위해서는 setstate()
메소드를 활용해야한다.
import (생략)
class App extends React.Component{
state={
count:0,
};
add =()=>{
this.setState(current=>({
count:current.count +1,
}));
}
minus = ()=>{
this.setState(current=>({
count:current.count -1,
}));
}
(생략)
SetState()의 특징
- SetState()의 인자로 state를 전달하면 리액트는 이전 state와 새로운 state를 비교하여 바뀐 데이터만 업데이트한다. 따라서 최상단의 예와 같이 변경 대상이 아닌 키와 키값은 그대로 유지된다.