본문 바로가기

프론트엔드/ReactJS 시작하기

[React] 리액트 작동원리 이해하기(1) - JSX

 

#React란?

React는 interactive한 어플리케이션을 만들기 위한 자바스크립트 라이브러리입니다. 

 

#왜 React를 사용할까?

React는 많은 HTML 요소들이 addEventListner를 사용해서 동작을 제어한다는 것을 알고 있었습니다.  addEventListner를 사용하는 방법은 우선 이벤트를 적용할 요소를 html에서 작성하고 JavaScript에서 querySelector로 html 요소를 찾고 그 요소에 addEventListner로 event를 등록하는 방법입니다.

이 방법을 React JS에서는 단 한줄로 실행시킬 수 있습니다. 또한 style, placeholder와 같은 여러가지 속성들도 한 줄의 코드에서 같이 적용시킬 수 있습니다. 

 


 

#예제를 통해 리액트의 원리 이해하기

리액트의 원리를 이해하기 위해서 버튼을 눌렀을 때 숫자가 증가하는 예제를 리액트 이전 방법과 리액트 사용한 방법으로  만들어보겠습니다. 이번시간에는 리액트를 사용한 예제는 버튼을 눌렀을 때 브라우저가 아닌 콘솔창에 출력되는 과정까지만 진행하고 다음 시간에 리액트 이전 방법과 같은 결과를 출력하는 예제를 온전한 리액트 방법으로 작성해보겠습니다. 오늘은 JSX의 장점과 리액트의 원리를 이해해주시기 바랍니다. 

 

리액트 이전 방법 - 버튼을 눌렀을 때 숫자가 증가하는 예제

리액트를 사용한 어려운 방법 - 버튼을 눌렀을 때 콘솔창에 출력되는 예제

리액트를 사용한 쉬운 방법 - 버튼을 눌렀을 때 콘솔창에 출력되는 예제

 

리액트를 사용한 어려운 방법은 앞으로 프론트엔드 개발자로서 절대 사용하지 않을 방법입니다. 단지 예제를 통해서 리액트의 원리를 이해해보겠습니다. 이것을 이해한다면 JSX의 유용함도 알게될 것입니다.

 

 


 

 

#리액트 이전 방법

<!DOCTYPE html>
<html>
    <body>
        <span>Total clicks: 0</span>
        <button id="btn">Click me</button>
    </body>
    <script>
    	let counter = 0;
        const span = document.querySelector('span');
        const button = document.getElementById('btn');
        function handleClick() {
            counter = counter + 1;
            span.innerText = `Total Clicks: ${counter}`; 
        }
        button.addEventListener('click', handleClick);
    </script>
</html>

리액트 이전 프론트엔드에서는 html에 span태그와 button태그를 직접 작성하고 javascript를 사용해서 html 태그를 찾고 click시 적용할 이벤트를 작성한 후에 addEventListner를 사용해서 찾은 html 태그에 이벤트를 등록해주는 방법입니다. 

결과

 

 

#리액트를 사용한 어려운 방법 - React.createElement()

우선 React Application을 만들기 위해서는 React와 ReactDOM 라이브러리를 설치해주셔야 합니다. cdn을 통해서 라이브러리를 설치하겠습니다.

/* react 설치 */
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
/* react dom 설치 */
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

React의 규칙 중 하나는 html을 직접 작성하지 않는 다는 것입니다.  그 대신에 우리는 Javascript를 사용합니다. 그것을 가능하게 해주는 것이 React와 ReactDOM 라이브러리입니다.

React로 react element를 만들고, ReactDOM은 element를 가져다가 html로 바꾸는 역할을 합니다.

<!DOCTYPE html>
<html>
    <body>
        <!-- 유일한 html -->
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script>
        const root = document.getElementById("root");
        const h3 = React.createElement(
            "h3",
            {
                id: "title",
                onMouseEnter: () => console.log("mouse enter"),
            },
            "Hello i'm a title"
         );
         const btn = React.createElement(
            "button",
            {
                onClick: ()=> console.log("i'm clicked"),
                style: {
                backgroundColor: "tomato",
                },
           },
           "Click me"
         );
         const container = React.createElement("div", null, [h3, btn])
         ReactDOM.render(container, root);
    </script>
</html>

 

다음과 같이 화면에 잘 출력되었고 console창에도 잘 출력되고 있습니다.

 

console창

 

 

#리액트를 사용한 쉬운 방법 - JSX

리액트를 사용한 어려운 방법에서 프론트엔드 개발자는 절대 사용하지 않는 createElement를 사용해서 react요소를 만들었었습니다. 이것을 쉽게 해주는 일반적인 html이랑 거의 비슷하게 생 개발자들이 주로 사용하는 JSX를 사용해서 createElement를 대체하도록 하겠습니다.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script>
        const root = document.getElementById("root");
      
        const Title = (
            <h3 id="title" onMouseEnter={()=>console.log("mouse enter")}>
            Hello i'm a title
            </h3>
        );
        const Button = (
        <button 
        style={{
            backgroundColor: "tomato",
        }} 
        onClick={()=>console.log("i'm clicked")}
        >
        Click me
        </button>
        );
        
         const container = React.createElement("div", null, [Title, Button])
         ReactDOM.render(container, root);
    </script>
</html>

 

JSX로 작성해서 코드가 한결 가벼워졌습니다. 그런데 아래와 같은 에러가 발생합니다. 

error

왜냐면 브라우저는 JSX 문법을 이해하지 못하기 때문입니다. 즉, 브라우저는 JSX 문법을 모릅니다.따라서 브라우저가 JSX를 이해할 수 있게 무언가를 설치해줘야합니다.

JSX 문법을 아래와 같이 브라우저가 이해할 수 있는 어려운 리액트 방법으로 변환시켜줄 수 있는 Babel을 설치해야합니다. Babel은 우리가 적은 JSX코드를 브라우저가 이해할 수 있는 형태로 변해주는 녀석입니다. 다음은 babel을 설치하는 cdn입니다. babel을 설치하고 script type="text/babel"로 변경해줘야 실행됩니다.

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
        const root = document.getElementById("root");
      
        const Title = (
            <h3 id="title" onMouseEnter={()=>console.log("mouse enter")}>
            Hello i'm a title
            </h3>
        );
        const Button = (
        <button 
        style={{
            backgroundColor: "tomato",
        }} 
        onClick={()=>console.log("i'm clicked")}
        >
        Click me
        </button>
        );
        
         const container = React.createElement("div", null, [h3, btn])
         ReactDOM.render(container, root);
    </script>
</html>

 

이제 새로고침해주면 전부 잘 동작할 것이고 아래와 같은 결과를 출력할 것입니다.

브라우저 출력결과

 

script

스크립트에서 Babel에게 우리가 작성한 코드를 확인할 수 있고 Babel은 그 코드를 브라우저가 읽을 수 있는 코드(리액트로 어려운 방법)로 바꿔서 다음과 같이 head에 담아놨습니다.

head

 

 

마지막으로 쉬운방법에서 container를 만들 때 사용한 createElement()도 JSX로 수정하는 방법을 배워보겠습니다. 우선 Title과 Button을 함수로 바꿔야 합니다. 즉, 컴포넌트로 만드는 것입니다. 따라서

JSX는 어플리케이션을 여러 작은 요소로 나누어 관리할 수 있게 해주어 유지보수를 용이하 합니다.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
        const root = document.getElementById("root");
      
        function Title () {
            return ( 
            <h3 id="title" onMouseEnter={()=>console.log("mouse enter")}>
            Hello i'm a title
            </h3>
            );
        }
            

        const Button = () => (
        <button 
        style={{
            backgroundColor: "tomato",
        }} 
        onClick={()=>console.log("i'm clicked")}
        >
        Click me
        </button>
        );
        
        // const container = React.createElement("div", null, [Title, Button]);
        // 컴포넌트는 반드시 대문자로 시작해야 한다. 그렇지 않으면서 html요소로 인식한다
        const Container =() => (
        <div>
            <Title/> 
            <Button/>
        </div>
        );
         ReactDOM.render(<Container/>, root);
    </script>
</html>

createElement()는 사용하지 않고 전부 훨씬 이해하기 쉬운 JSX문법으로 변경한 코드입니다. 컴포넌트를 다른 컴포넌트 안에 넣는 방법을 사용했습니다.

Babel이 브라우저가 이해할 수 있는 문법으로 변환시킨 코드는 head 태그에 담겨있는데 이것은 전부 createElement 투성입니다. 우리는 JSX 문법을 사용해서 우리가 이해하기 쉬운 코드로 작성하고 브라우저가 이해할 수 있는 문법은 Babel 자동으로 변환시켜 주기 때문에 쉽게 코드를 작성할 수 있습니다. 

 

컴포넌트는 재사용할 수 있습니다. 우리가 만든 Button 컴포넌트를 재사용해서 브라우저에서 여러번 출력해보겠습니다. 

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
        const root = document.getElementById("root");
      
        function Title () {
            return ( 
            <h3 id="title" onMouseEnter={()=>console.log("mouse enter")}>
            Hello i'm a title
            </h3>
            );
        }
            

        const Button = () => (
        <button 
        style={{
            backgroundColor: "tomato",
        }} 
        onClick={()=>console.log("i'm clicked")}
        >
        Click me
        </button>
        );
        
        // const container = React.createElement("div", null, [Title, Button]);
        // 컴포넌트는 반드시 대문자로 시작해야 한다. 그렇지 않으면서 html요소로 인식한다
        const Container =() => (
        <div>
            <Title/> 
            <Button/>
            <Button />
            <Button />
            <Button />
        </div>
        );
         ReactDOM.render(<Container/>, root);
    </script>
</html>

 

브라우저 결과

각각의 버튼은 각각의 이벤트리스너를 가집니다. 이것이 컴포넌트를 사용하는 장점입니다. 

 

다음시간부터는 React JS의 State를 배워보도록 하겠습니다.