[javascript] React 기초 part-1

React Basics1

목차

React란?

A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

리액트 공식 홈페이지에 들어가보면, 리액트란 UI를 만들기 위한 자바스크립트 라이브러리 라고 작성되어 있다.
리액트는 페이스북에서 개발한 유저인터페이스 라이브러리로서 개발자로 하여금 재사용 가능한 UI를 생성 할 수 있게 해준다.

이 라이브러리는 Virtual DOM 이라는 개념을 사용하여 상태의 변함에 따라 선택적으로 유저인터페이스를 렌더링한다. 따라서, 최소한의 DOM 처리로 컴포넌트들을 업데이트 할 수 있게 해준다.

라이브러리 vs 프레임워크

이 때, 라이브러리와 함께 자주 언급되는 프레임워크의 차이를 먼저 알아보자.

Virtual DOM

Unlike browser DOM elements, React elements are plain objects, and are cheap to create.
React DOM takes care of updating the DOM to match the React elements.

React.js는 자바스크립트 내에 DOM Tree와 같은 구조체를 VIRTUAL DOM으로 갖고 있다.

Virtual DOM은 실제 DOM의 구조와 비슷한, React 객체의 트리다.
개발자는 직접 DOM을 제어하지 않고 Virtual DOM을 제어하고, React에서 적절하게 Virtual DOM을 DOM에 반영하는 작업을 한다

다시 말해, DOM을 제어하는 방식이 아니라 중간에 가상의 DOM인 Virtual DOM을 두어 개발의 편의성(DOM을 직접 제어하지 않음)과 성능(배치 처리로 DOM 변경)을 개선한 것이다.

setState(forceUpdate) 함수가 호출되면 그 컴포넌트와 하위 컴포넌트가 다시 랜더링되는 대상이 된다.
이 말을 듣게 되면 매번 광범위하게 DOM이 갱신된다고 느껴지지만 React.js에서는 VIRTUAL DOM이라고 하는 형태로 메모리상에 DOM의 상태를 유지하고 있고, 전/후 상태를 비교하여 달라진 부분만 실제 DOM에 반영한다. 참고로 CSS도 마찬가지로 객체 형식으로 지정해 변경된 Style만 갱신한다.

즉, UI를 다시 그릴 때는 그 구조체의 전후 상태를 비교하여 변경이 필요한 최소한의 요소만 실제 DOM에 반영한는 말이다. 따라서 무작위로 다시 그려도 변경에 필요한 최소한의 DOM만 갱신되기 때문에 빠르게 처리할 수 있다.

보다 자세한 내용은 React and the Virtual DOM 영상이나 NAVER D2에 올라온 React 적용 가이드 - React 작동 방법 의 Virtual DOM 항목을 정독하자.

ReactJS의 장점

ReactJS의 단점

React의 구조

Elements

Elements are the smallest building blocks of React apps. An element describes what you want to see on the screen:

Element는 리액트 앱을 만들 때 필요한 최소한의 블럭이다. 브라우저 요소인 DOM과 달리 React Element는 보다 적은 비용으로 생성할 수 있으며, React DOM은 React Element와 일치하도록 DOM을 업데이트 한다.

Elements를 DOM으로 렌더링하기

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

다음과 같은 코드가 있을 때, React의 관점에서는 저 root 노드를 중심으로 코드가 돌아갈 것이다. 이 것을 리액트에서는 Root DOM node 라고 부른다. 이 태그(root) 내부의 모든 element는 React DOM에 의해 관리된다.

const element = (
    <h1>Hi!</h1>
);
ReactDOM.render(element, document.getElementById('root'));

getElementById를 통해 root노드를 select해서 이 루트노드 안에 element를 render 할 수 있다.

With our knowledge so far, the only way to update the UI is to create a new element, and pass it to ReactDOM.render().


Immutable Element

리액트에서는 Element가 렌더 된 이후에는 해당 element의 자식이나 attribute를 변경할 수 없다. UI를 변경하고 싶다면 새로운 element를 전달하여 업데이트 해야한다.

만약 ‘새로이 전달되는 element가 굉장히 길고 복잡하면 어떡하지?’ 라는 생각이 들어 굉장히 비효율적이라는 생각이 들지만, React DOM은 기존에 이미 렌더링되어 있는 DOM과 새로이 전달받은 Element를 비교하여 업데이트가 필요한 부분만 업데이트해준다.

여기를 보면, 매 초마다 시간이 바뀌는데 업데이트 되는 특정 element만 업데이트 되고 있음을 알 수 있다.


Component

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

위에서 설명한 element의 형식으로만 UI를 구성한다면, 길고 복잡한 마크업의 경우 복잡하고 구조가 한눈에 들어오기 아주 어려울 것이다. 따라서 리액트에서는 Component 형식을 제공해 리액트가 제공하는 장점인 독립적이고 재사용 할 수 있는 UI를 가능하게 해준다.

위의 영문 설명과 같이, React.js는 Component 를 통해 UI를 구성하여 독립적이고 재사용 가능하게 만들어준다. Component 안에 앞서 설명한 Element 를 넣어 구성하면 된다.

Component의 정의

Component는 ES6의 class문법을 사용하여 정의할 수 있고 React.createClass 문법을 통하여 정의할 수 있고, stateless한 Component에 대하여 functional Component 방식으로 정의할 수 있다.

만약 소스 안에 state나 refs가 있으면, React.createClass 보다는 class extends React.Component 를 사용하자. (이에 대한 자세한 설명은 후술하겠다.)


Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.

ES6이 본격화 되기 전에는 component를 선언하기 위해 props 을 인수로 갖는 function을 사용하였다.

// ES5 : 데이터를 담고 있는 props를 전달받고, React elements를 리턴하니 올바른 컴포넌트의 형태가 맞다.
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// ES6
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

하지만 ES6이 본격화 되었기 때문에, React.js의 ComponentClass 로 정의하고 구성한다. 그리고 이 컴포넌트는 기본적으로 React Component 를 상속받는다. 기본적인 구조는 다음과 같고, 결과 화면도 다음과 같이 출력된다.

class Codelab extends React.Component{ // 클래스명의 시작은 대문자로 써주는게 코딩컨벤션
    render(){
        let style={
            backgroundColor:'aqua',
        };

        return(
            <div>
                <h1 style={style}>Hello {this.props.name}</h1>
                <div>{this.props.children}</div>
            </div>
        );
    }
}

class App extends React.Component{
    render(){
        return(
            <Codelab name="shinye">이 사이에 있는게 this.props.Children 으로 감.</Codelab>
        );
    }
}

ReactDOM.render(<APP />, document.getElementById('root'));
export default App;

https://68.media.tumblr.com/350bcb8c9b1ddda6dd873612df7e123e/tumblr_ox14kc1A6w1v80c66o1_1280.png

Previously, we only encountered React elements that represent DOM tags.
However, elements can also represent user-defined components:

위의 예시를 보면 render함수 내부의 태그에 component의 이름이 들어가 있는걸 확인할 수 있다.

이전의 element 예시 까지만 해도 기존의 우리가 알고 있는 DOM태그만을 요소로 넣었다.
하지만 React의 elements는 사용자가 정의한 component 역시도 elements로 가질 수 있다. 다시 위의 예시를 언급하며 정확한 예를 들어보자. (더 직관적으로 원리를 보기 위해 클래스버전이 아닌 함수 버전으로 작성하겠다.)

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Shinye" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

When React sees an element representing a user-defined component, it passes JSX attributes to this component as a single object. We call this object “props”.

리액트는 render시에 사용자가 정의한 컴포넌트를 element로 전달한 것을 확인하게 된다면, 이 element 내의 JSX attribute들을(위의 예시에선 name="shinye" 부분) 하나의 객체로 만든다. 그리고 우리는 이것을 props 라고 부른다. (props에 대한 설명은 뒤에서 다시…)

또한 모든 리액트의 컴포넌트에는 render 메소드가 존재한다.
이 render메소드는 해당 컴포넌트가 어떻게 생길지 정의해준다. 다시 말해, 컴포넌트를 통해 어떤 view를 보여줄 것인지 JSX 형태로 작성하여 return 해주면 된다. (JSX에 대한 자세한 설명은 후술할 것이다.)
또한, render() 는 하나의 컴포넌트만을 반환해야한다. 복수의 컴포넌트를 반환할 수 없다.

// NO : 두 개의 컴포넌트
render() {
   return (
     <div>title</div>
     <div>contents</div>
   );
}

// OK
render() {
  return (
    <div>
      <div>title</div>
      <div>contents</div>
    </div>
  );
}

Class와 생성자 메소드

클래스에 대한 설명은 여기서 확인할 수 있다.

(그래도 강의에서 들은 내용을 다시 정리해보자면)

JSX

This funny tag syntax is neither a string nor HTML.

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript.

JSX produces React “elements”. We will explore rendering them to the DOM

Component import 관련

지금까지의 예시에서 컴포넌트를 정의할 때 class ComponentName extends React.Component 와 같은 형식으로 정의하였다. 하지만 react의 boilerplate를 다운받아서 사용할 때 해당 코드를 보면 class ComponentName extends Component 와 같이 정의되어 있기도 하다.

그 이유는 코드 상단을 확인해보면 알 수 있다.

// ... extends React.Component 라고 사용하는 경우
import React, { Component } from 'react';

// ... extends Component 라고 사용하는 경우
import React from 'react';

이 둘의 차이가 무엇인지 몰라 찾아보았고 여기(When should I use curly braces for ES6 import?) 에 아주 잘 나와있다. 그리고 나의 TIL에도…잘 나와 있었다…^^;……엉엉…

참고URL

inflearn - React & Express 를 이용한 웹 어플리케이션 개발하기

[React] 2. Elements and Component
Components and Props
Rendering Elements
Introducing JSX
coderifleman - React.js를 이해하다(4)
coderifleman - React.js를 이해하다(1)
NAVER D2 - React 적용 가이드 - React 작동 방법
프레임워크와 라이브러리의 차이점
프레임워크와 라이브러리의 차이
React Without JSX