ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리액트 입문(1) - 모던 리액트 | 김민준
    Front-end/React.js 2020. 6. 26. 23:33
    반응형

    [출처 : https://react.vlpt.us]

    1. 리액트는 어쩌다 만들어졌을까?

    리액트 학습을 본격적으로 하기 전에, 리액트라는 라이브러리가 어쩌다가 만들어졌는지 알면 리액트를 이해하는데 도움이 될 것입니다.

     

    JavaScript를 사용하여 HTML 로 구성한 UI 를 제어해보셨다면, DOM 을 변형시키기 위하여 우리가 어떤 작업을 해야하는지 익숙 할 것입니다. 브라우저의 DOM Selector API 를 사용해서 특정 DOM 을 선택한뒤, 특정 이벤트가 발생하면 변화를 주도록 설정해야되지요.

     

    한번 HTML/JS 로 만들어진 카운터 예시를 확인해봅시다.

    <h2 id="number">0</h2>
    <div>
      <button id="increase">+1</button>
      <button id="decrease">-1</button>
    </div>

    위와 같이 HTML 이 구성되어 있고, id 를 사용하여 각 DOM 을 선택한뒤, 원하는 이벤트가 발생하면 DOM 의 특정 속성을 바꾸어주어야 하죠.

    const number = document.getElementById('number');
    const increase = document.getElementById('increase');
    const decrease = document.getElementById('decrease');
    
    increase.onclick = () => {
      const current = parseInt(number.innerText, 10);
      number.innerText = current + 1;
    };
    
    decrease.onclick = () => {
      const current = parseInt(number.innerText, 10);
      number.innerText = current - 1;
    };

    현재 위 코드를 보면 "+1 버튼이 눌리면, id 가 number 인 DOM 을 선택해서 innerText 속성을 1씩 더해줘라" 라는 규칙이 있지요. 사용자와의 인터랙션이 별로 없는 웹페이지라면 상관없겠지만, 만약에 인터랙션이 자주 발생하고, 이에 따라 동적으로 UI 를 표현해야된다면, 이러한 규칙이 정말 다양해질것이고, 그러면 관리하기도 힘들어질것입니다. 숙련된 JavaScript 개발자라면, 코드를 최대한 깔끔하게 정리하여 쉽게 유지보수를 할 수도 있겠지만, 대부분의 경우 웹 애플리케이션의 규모가 커지면, DOM 을 직접 건드리면서 작업을 하면 코드가 난잡해지기 쉽습니다.

    처리해야 할 이벤트도 다양해지고, 관리해야 할 상태값도 다양해지고, DOM 도 다양해지게 된다면, 이에 따라 업데이트를 하는 규칙도 많이 복잡해지기 때문에, 조금 과장을 많이 하자면 코드가 다음과 같은 형태가 됩니다.

     

    그래서, Ember, Backbone, AngularJS 등의 프레임워크가 만들어졌었는데, 이 프레임워크들은 작동방식이 각각 다르지만, 쉽게 설명하자면 자바스크립트의 특정 값이 바뀌면 특정 DOM의 속성이 바뀌도록 연결을 해주어서, 업데이트 하는 작업을 간소화해주는 방식으로 웹개발의 어려움을 해결해주었습니다.

    하지만 리액트의 경우에는 조금 다른 발상에서 만들어졌습니다. 리액트는 어떠한 상태가 바뀌었을때, 그 상태에 따라 DOM 을 어떻게 업데이트 할 지 규칙을 정하는 것이 아니라, 아예 다 날려버리고 처음부터 모든걸 새로 만들어서 보여준다면 어떨까? 라는 아이디어에서 개발이 시작되었습니다.

     

    그러면 "업데이트를 어떻게 해야 할 지" 에 대한 고민을 전혀 안해도 되기 때문에 개발이 정말 쉬워질 것입니다. 하지만, 정말로 동적인 UI 를 보여주기 위해서 모든걸 다 날려버리고 모든걸 새로 만들게 된다면, 속도가 굉장히 느릴 것입니다. 작은 웹애플리케이션이라면 상관없겠지만 규모가 큰 웹애플리케이션이라면 상상도 할 수 없는 일이죠.

    하지만, 리액트에서는 Virtual DOM 이라는 것을 사용해서 이를 가능케 했습니다.

    Virtual DOM 은 가상의 DOM 인데요, 브라우저에 실제로 보여지는 DOM 이 아니라 그냥 메모리에 가상으로 존재하는 DOM 으로서 그냥 JavaScript 객체이기 때문에 작동 성능이 실제로 브라우저에서 DOM 을 보여주는 것 보다 속도가 훨씬 빠릅니다. 리액트는 상태가 업데이트 되면, 업데이트가 필요한 곳의 UI 를 Virtual DOM 을 통해서 렌더링합니다. 그리고 나서 리액트 개발팀이 만든 매우 효율적인 비교 알고리즘을 통하여 실제 브라우저에 보여지고 있는 DOM 과 비교를 한 후, 차이가 있는 곳을 감지하여 이를 실제 DOM 에 패치시켜줍니다. 이를 통하여, "업데이트를 어떻게 할 지" 에 대한 고민을 하지 않고 UI를 "어떻게 보여줘야 하는 지"를 집중하여 프로젝트를 개발한다. 또한 리액트에서 UI는 컴포넌트를 사용해서 선언하며, 컴포넌트는 인풋을 통해 아웃풋을 만들어내는 UI 조각이다.


    2. 작업환경 준비

    · Node.js: Webpack 과 Babel 같은 도구들이 자바스크립트 런타임인 Node.js 를 기반으로 만들어져있습니다. 그렇기에 해당 도구들을 사용하기 위해서 Node.js 를 설치합니다.

    · Yarn: Yarn 은 조금 개선된 버전의 npm 이라고 생각하시면 됩니다. npm 은 Node.js 를 설치하게 될 때 같이 딸려오는 패키지 매니저 도구입니다. 프로젝트에서 사용되는 라이브러리를 설치하고 해당 라이브러리들의 버전 관리를 하게 될 때 사용하죠. 우리가 Yarn 을 사용하는 이유는, 더 나은 속도, 더 나은 캐싱 시스템을 사용하기 위함입니다.

    · 코드 에디터: 그리고, 코드 에디터를 준비하세요. 여러분이 좋아하는 에디터가 있다면, 따로 새로 설치하지 않고 기존에 사용하시던걸 사용하셔도 됩니다. 저는 주로 VSCode 를 사용합니다. 이 외에도, Atom, WebStorm, Sublime 같은 훌륭한 선택지가 있습니다.

    · Git bash: 윈도우의 경우, Git for Windows 를 설치해서 앞으로 터미널에 무엇을 입력하라는 내용이 있으면 함께 설치되는 Git Bash 를 사용하세요. 윈도우가 아니라면 설치하지 않으셔도 상관없습니다. 설치는 기본 옵션으로 진행하시면 됩니다.

    Webpack, Babel 은 무슨 용도인가요?
    리액트 프로젝트를 만들게 되면서, 컴포넌트 를 여러가지 파일로 분리해서 저장 할 것이고, 또 이 컴포넌트는 일반 자바스크립트가 아닌 JSX 라는 문법으로 작성하게 됩니다. 여러가지의 파일을 한개로 결합하기 위해서 우리는 Webpack 이라는 도구를 사용하고, JSX 를 비롯한 새로운 자바스크립트 문법들을 사용하기 위해서 우리는 Babel 이라는 도구를 사용합니다.

    Node.js

    Windows 의 경우엔, Node.js 공식 홈페이지 에서 좌측에 나타나는 LTS 버전을 설치해주세요.

    macOS / Linux 의 경우엔, nvm 이라는 도구를 사용하여 Node.js 를 설치하시는 것을 권장드립니다.

     

    $ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

    $ nvm install --lts

     

    Yarn

    만약 npm 이 이미 익숙하고, yarn 을 설치하기 귀찮다면 생략을 하셔도 상관없습니다.

    yarn 설치는 Yarn 공식 홈페이지의 Install Yarn 페이지를 참고하세요.

     

    VS Code

    VS Code 를 설치 할 땐 VS Code 공식 홈페이지 를 참고하세요.

     

    새 프로젝트 만들어보기

    새로운 리액트 프로젝트를 만들어봅시다. 터미널을 열은 뒤, 다음 명령어를 실행해보세요. (윈도우 사용자는 Git Bash 를 사용하세요)

     

    $ npx create-react-app begin-react

     

    그러면 begin-react 라는 디렉터리가 생기고 그 안에 리액트 프로젝트가 생성됩니다. 생성이 끝나면 cd 명령어를 사용하여 해당 디렉터리에 들어간 다음 yarn start 명령어를 입력해보세요 (yarn 이 없다면 npm start).

     

    $ cd begin-react

    $ yarn start

     

    이 명령어를 실행하고 나면 다음과 같이 브라우저에 http://localhost:3000/ 이 열리고, 돌아가는 리액트 아이콘이 보일 것입니다. 자동으로 페이지가 열리지 않는다면 브라우저에 주소를 직접 입력하여 들어가세요.

     

    VS Code 에서 터미널 띄우기

    VS Code 내부에서 터미널을 띄울 수도 있습니다. VS Code 로 해당 디렉터리를 열은 뒤, 상단 메뉴의 View > Terminal 을 열으세요. (한글 메뉴의 경우 보기 > 터미널).

     

    윈도우 사용자의 경우엔, 위 작업을 하기 전에 VS Code 에서 cmd 대신 Git Bash 를 사용하기 위하여 VS Code 에서 Ctrl + , 를 눌러 설정에 들어간 후, terminal 을 검색 후 Terminal > External > Windows Exec 부분에 Git Bash 의 경로인 C:\Program Files\Git\bin\bash.exe 를 넣어주세요.

     

    Git Bash 를 열었을 때 기본 경로

    Git Bash 에서의 ~/ 경로가 어디인지 모르신다면 pwd 명령어를 입력해보세요.


    3. 나의 첫번째 리액트 컴포넌트

    첫번째 리액트 컴포넌트를 만들어봅시다.

     

    src 디렉터리에 Hello.js 라는 파일을 다음과 같이 작성해보세요.

    Hello.js : 

    import React from 'react';
    
    function Hello() {
      return <div>안녕하세요</div>
    }
    
    export default Hello;

    리액트 컴포넌트를 만들 땐

    import React from 'react';

    를 통하여 리액트를 불러와주어야 합니다.

     

    리액트 컴포넌트는 함수형태로 작성 할 수도 있고 클래스형태로도 작성 할 수 있습니다. 지금 단계에서는 함수로 작성하는 방법에 대해서만 알아보겠습니다.

     

    리액트 컴포넌트에서는 XML 형식의 값을 반환해줄 수 있는데 이를 JSX 라고 부릅니다. 이에 대해선 다음번에 알아보도록 하겠습니다.

     

    코드의 최하단

    export default Hello;

    이 코드는 Hello 라는 컴포넌트를 내보내겠다는 의미입니다. 이렇게 해주면 다른 컴포넌트에서 불러와서 사용 할 수 있습니다.

     

    이 컴포넌트를 한번 App.js 에서 불러와서 사용해보겠습니다. 

    App.js : 

    import React from 'react';
    import Hello from './Hello';
    
    function App() {
      return (
        <div>
          <Hello />
        </div>
      );
    }
    
    export default App;

    상단에 있던

    import logo from './logo.svg';
    import './App.css';

    는 SVG 파일을 불러오고, CSS 를 적용하는 코드인데 이는 현재 불필요하므로 제거해주었습니다.

     

    컴포넌트는 일종의 UI 조각입니다. 그리고, 쉽게 재사용 할 수도 있습니다.

    App.js : 

    import React from 'react';
    import Hello from './Hello';
    
    
    function App() {
      return (
        <div>
          <Hello />
          <Hello />
          <Hello />
        </div>
      );
    }
    
    export default App;

    이제, index.js 를 열어보세요. 이런 코드가 보일 것입니다.

    index.js : 

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();

    여기서 ReactDOM.render 의 역할은 브라우저에 있는 실제 DOM 내부에 리액트 컴포넌트를 렌더링하겠다는 것을 의미합니다. id 가 root 인 DOM 을 선택하고 있는데, 이 DOM 이 어디있는지 볼까요?

     

    public/index.html 을 열어보시면 내부에

    public/index.html :

    <div id="root"></div>

    을 찾아보실 수 있습니다.

    결국, 리액트 컴포넌트가 렌더링 될 때에는, 렌더링된 결과물이 위 div 내부에 렌더링되는 것 입니다.


    4. JSX의 기본 규칙 알아보기

    JSX 는 리액트에서 생김새를 정의할 때, 사용하는 문법입니다. 얼핏보면 HTML 같이 생겼지만 실제로는 JavaScript 입니다.

     

    리액트 컴포넌트 파일에서 XML 형태로 코드를 작성하면 babel 이 JSX 를 JavaScript 로 변환을 해줍니다.

    Babel 은 자바스크립트의 문법을 확장해주는 도구입니다. 아직 지원되지 않는 최신 문법이나, 편의상 사용하거나 실험적인 자바스크립트 문법들을 정식 자바스크립트 형태로 변환해줌으로서 구형 브라우저같은 환경에서도 제대로 실행 할 수 있게 해주는 역할을 합니다.

     

    JSX 가 JavaScript 로 제대로 변환이 되려면 지켜주어야 하는 몇가지 규칙이 있습니다. 다음 문법들을 준수해주시면 앞으로 리액트 컴포넌트를 개발함에 있어서 큰 어려움이 없을 것입니다!

     

    꼭 닫혀야 하는 태그

    태그는 꼭 닫혀있어야 합니다. 태그를 열었으면 꼭, <div></div> 이렇게 닫아주어야 합니다.

    return <div>안녕하세요</div>;

    HTML 에서는 input 또는 br 태그를 사용 할 때 닫지 않고 사용하기도 합니다. 하지만 리액트에서는 그렇게 하면 안됩니다.

    return <input />

    태그와 태그 사이에 내용이 들어가지 않을 때에는, Self Closing 태그(ex. <input />) 라는 것을 사용해야 합니다.

    현재 Hello 컴포넌트를 사용 할 때에도 Self Closing 태그를 사용해주었는데요. <Hello /> 이렇게 열리고, 바로 닫히는 태그를 의미합니다.

     

    꼭 감싸져야하는 태그

    두가 이상의 태그는 무조건 하나의 태그로 감싸져있어야 합니다.

    return (
      <div>
        <Hello />
        <div></div>
      </div>
    )
    

    하지만, 이렇게 단순히 감싸기 위하여 불필요한 div 로 감싸는게 별로 좋지 않은 상황도 있습니다. 예를 들어서 스타일 관련 설정을 하다가 복잡해지게 되는 상황도 올 수 있고, table 관련 태그를 작성 할 때에도 내용을 div 같은걸로 감싸기엔 애매하죠. 그럴 땐, 리액트의 Fragment 라는 것을 사용하면 됩니다.

    return (
      <>
        <Hello />
        <div></div>
      </>
    )
    

    태그를 작성 할 때 이름 없이 작성을 하게 되면 Fragment 가 만들어지는데, Fragment 는 브라우저 상에서 따로 별도의 엘리먼트로 나타나지 않습니다.

     

    JSX 안에 자바스크립트 값 사용하기

    JSX 내부에 자바스크립트 변수를 보여줘야 할 때에는 {} 으로 감싸서 보여줍니다.

    function App() {
      const name = 'React';
      return (
        <>
          <Hello />
          <div>{name}</div>
        </>
      );
    }
    

    style 과 className

    JSX 에서 태그에 style 과 CSS class 를 설정하는 방법은 HTML 에서 설정하는 방법과 다릅니다.

    우선, 인라인 스타일은 객체 형태로 작성을 해야 하며, background-color 처럼 - 로 구분되어 있는 이름들은 backgroundColor 처럼 camelCase 형태로 네이밍 해주어야 합니다.

     

    그리고, CSS class 를 설정 할 때에는 class= 가 아닌 className= 으로 설정을 해주어야 합니다. 

     

    주석

    이제, JSX 에서 주석은 어떻게 작성하는지 알아봅시다. JSX 내부의 주석은 {/* 주석 내용 */} 이런 형태로 작성합니다.

     

    추가적으로, 열리는 태그 내부에서는 // 주석 내용 이런 형태로도 주석 작성이 가능합니다.

     return (
        {/* 주석은 화면에 보이지 않습니다 */}
        /* 중괄호로 감싸지 않으면 화면에 보입니다 */
        <Hello 
          // 열리는 태그 내부에서는 이렇게 주석을 작성 할 수 있습니다.
        />
      );

     

    반응형

    댓글

Luster Sun