[강의 복습] ReactJS로 영화 웹 서비스 만들기 : 2. The basic of react

박종배·2023년 3월 11일
0
post-thumbnail

서론

아래에 글은 참고 링크의 강의를 공부하며 overview한 내용입니다.

참고


2.0 Introduction

react는 interactive를 위한 것.

워크스페이스 만들기

$ mkdir react-for-beginners
  cd $_
  touch index.html

2.1 Before React

요약

  • html에서 <script> 태그로 JS 코드를 추가할 수 있음. JS에서 document는 웹 페이지를 나타내는 객체 모델(DOM, Document Object Model)의 최상위 객체로, 웹 페이지의 모든 요소에 대한 접근과 조작을 가능하게 해주는 객체임. document 객체는 다양한 속성과 메서드를 가지고 있기에 이를 이용하여 웹 페이지의 내용을 동적으로 조작할 수 있음.
  • element에 대해 .addEventListener()의 첫번째 인자는 click, mouseEnter 등 다양한 이벤트를 참조함.
  • JS로만 프론트를 작성하는 것은 꽤나 복잡해질 수 있음.
  • react를 사용하기 위해서 script 태그에 src 속성으로 url을 입력하여 설치할 수도 있음. (좋은 방법은 아님)

목표

  • 바닐라 JS 앱 만들기
  • 몇 번 클릭했는지 세는 앱.
  • 이를 통해 react로 개선할 수 있는 부분을 찾아보자.

vanilla.html

<!DOCTYPE html>
<html>
    <body>
        <span>Total clicks: 0</span>
        <button id="btn">Click me</button>
    </body>
    <script>
        let counter = 0;
        const button = document.getElementById("btn");
        const span = document.querySelector("span");
        function handleClick() {
            counter += 1;
            span.innerText = `Total clicks: ${counter}`;
        }
        button.addEventListener("click", handleClick)
    </script>
</html>
  • element에 대해 .addEventListener()의 첫번째 인자는 다양한 이벤트를 참조함.

확인

이 방법의 단점

  • 코드가 길다.
  • 클릭이 많아질수록 handle이 추가되므로 복잡해진다.

이제 react로 작성해보자.

index.html

<!DOCTYPE html>
<html>
    <body>
    </body>
    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
    <script>
    </script>
</html>
  • 먼저, react와 react-dom을 설치하고 임포트해주자. script 태그에 src 속성으로 url 을 적어주면 됨.

react 설치 확인

  • 설치가 제대로 됐으면 페이지에 아무것도 안 떠야하고 콘솔에서 React 입력 시에 위와 같이 출력돼야 함.

2.2 Our First React Element

요약

  • react는 React, ReactDOM 라이브러리를 사용함.
  • ReactDOM.render()로 react element를 html에 뿌려줌. 첫번째 인자로 뿌려줄 element 이름을, 두번째 인자로 뿌려질 곳인 body의 태그 하나를 정해줌.
  • react로 element를 만들 때 사용하는 React.createElement()의 인자로써 tag, property, content를 넣을 수 있음. 즉, React.createElement(, , ) 로 표현할 수 있음. 다시 말해, 각 html의 태그, 그 태그들의 속성, 그 태그로 뿌려줄 콘텐츠를 말함.
  • react 의 핵심은 html → js 가 아니라 js → html 이라는 것. 즉, react에서 element를 직접 유지보수 할 수 있다는 말.
  • 아래 방법은 react를 쓰는 방법에서도 꽤 복잡한 방법으로 일단 이해를 돕기위함. 더 간단한 방법은 추후에 배우자.

목표

  • 이제, vanilla.html을 react로 작성해보자.

react의 규칙 중 하나는 HTML을 index.html의 body 안에 직접 작성하지 않는다는 것. 대신에 javascript와 react를 사용해 element로 작성해야 함.

이제, react element를 작성해보자. 여기서 하는 방법은 좀더 근본적인 방법으로 이해를 위한 것이고 추후에는 좀더 쉬운 방법을 사용할 것임.

index.html

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
    <script>
        const root = document.getElementById("root");
        const span = React.createElement(
            "span", 
            { id: "sexy-span", style: { color: "red"} }, 
            "Hello I'm a span"
        );
        ReactDOM.render(span, root);
    </script>
</html>
  • react로 element를 생성할 때, React.createElement()의 인자는 만들려는 html의 태그 이름과 일치해야 함.
  • 이렇게 만든 react의 element를 화면에 뿌려주기 위해 html body에 넣어야할 텐데 이는 react-dom을 사용하면 됨. react-dom은 라이브러리 또는 패키지로써 모든 react element들을 html body에 둘 수 있도록 해줌. (c.f. reactJS 는 엔진과 같음.)
  • 아무튼 이 방법은 react 작동의 이해를 돕고자 하는 근본적인 방법으로 추후에 더 쉬운 방법을 사용해 다시 해볼 것임.
  • ReactDOM.render()는 react element를 가지고 html에 배치한다는 것. 즉, 사용자에게 보여준다는 것. 이 함수의 첫번째 인자로 span을, 두번째 인자로 root를 넣어서 span 엘리멘트를 root 에 뿌려주자는 것. 여기서 root는 html body 에서 id가 root인 div 태그를 말하며 우리가 body 에 적는 유일한 태그가 될 것임. 이런 root에 대해 react는 const를 만들어서 사용한 것.
  • React.createElement()의 두번째 인자에는 첫번째 인자로 들어간 해당 tag의 property를 넣을 수 있음. 예를 들면, id나 className이 있음. style color 도 추가해보자. 세번째 인자는 해당 태그의 내용이 됨.

확인

  • html body에서 root div에 대해 span이 생긴 것을 확인할 수 있음.

이 예제의 의미

  • 사실 단순히 span 을 넣는건데 생각보다 코드가 길어지고 복잡해짐.
  • 그럼에도 이 예제를 공부한 이유는 기존의 관점과 다르기 때문. 예를 들어, JS의 경우, HTML을 만들고 JS에 가져와 수정하는 식이었지만 React는 모든것이 JS로써 시작하고 그 다음 HTML이 됨. 이것이 핵심임.
  • 즉, React는 element를 직접 생성한다는 것이고 이 말은 react의 경우, 업데이트가 필요한 element를 직접 업데이트한다는 말.

2.3 Events in React

요약

  • React.createElement()의 두번째 인자 property에서 eventListener를 함수로 따로 만들어 사용하지 않고 바로 대체할 수 있음. 즉, eventListener 메서드를 반복해서 사용할 필요 없이 property에서 바로 사용 가능함. 또한 여기서 다른 property와 다르게 eventListener는 react가 알아서 HTML에 표시하지 않음.
  • 하지만, 아래 방식을 계속 사용하지는 않음. element를 생성하는 더 쉬운 방법을 추후에 알아보자.

목표

  • 이제, react를 사용해 버튼을 만들고 변경사항을 감지해보자.

index.html

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
    <script>
        const root = document.getElementById("root");
        const h3 = React.createElement(
            "h3", 
            {
                id: "title",
                onMouseEnter: () => console.log("mouse enter"),
            }, 
            "Hello I'm a span"
        );
        const btn = React.createElement(
            "button",
            {
                onClick: () => console.log("im clicked"),
                style: {
                    backgroundColor: "tomato",
                }
            },
            "Click me"
        );
        const container = React.createElement("div", null, [h3, btn])
        ReactDOM.render(container, root);
    </script>
</html>
  • 두 개 이상의 element를 render하고 싶을 경우, container element를 만들고 여기에 세번째 인자인 content로써 render할 element들을 array로 넣어준 뒤 이 container element를 ReactDOM.render() 의 첫번째 인자로 활용하자.
  • 이제, 클릭 시에 이벤트를 만들어보자. 기존에 vanillaJS에서는 handleClick() 함수를 만들어 해당 element에 대해 .addEventListener() 를 활용했지만 reactJS에서는 좀더 짧고 간단한 방법으로 할 수 있음. btn에 대한 React.createElement() 함수의 두번째 인자로 property를 줄 수 있다고 했는데 여기에 함수를 넣어서 클릭 시에 동작할 수 있도록 하자. 그리고 이 property에서 tag에 들어갈 property는 render된 HTML에 보이지만 on+이벤트의 경우에는 eventlistener인 것을 알고 HTML에 보여주지 않음.

확인

  • 두개 이상의 element를 render 했음.

  • h3 엘리멘트에는 onMouseEnter를, btn 엘리멘트에는 onClick을 적용함.

  • property들이 html에 보이지만 on+event는 eventListener인 것을 알고 html에 보이지 않음.

2.4 Recap

복습

  • react는 element를 생성하고 event listener를 더하는 것을 도와주기에 interactive power를 가지고 있음.
  • react dom은 react element들을 가져다가 html로 바꿔줌.
  • React.createElement()와 같이 앞서 살펴본 react 작성 방법은 앞으로 사용하지 않을 것임. 단순히 원리를 이해하기 위해 공부해봤음.

2.5 JSX

요약

  • React.createElement()는 react의 원리를 이해할 수 있지만 실제 개발자들이 사용하는 방식이 아님. 이 방법도 쉬운 방법이긴한데 좀더 개발자스럽고 쉽게 작성하는 방법인 JSX를 주로 사용함.
  • JSX는 기존 HTML 문법을 대체로 따르기 때문에 개발자 친화적이며 가독성이 뛰어남. 단지, 엘리멘트 이름을 대문자로 시작하고 값을 ()로 감싸주며 property를 적어줄 때 : 대신 = 를 쓰며 값에는 {} 로 한 번 더 감싸주기만하면 됨.
  • 브라우저는 JSX를 읽을줄 모르므로 Babel을 활용해 한 번 변환 과정을 거쳐줘야 함.
  • Babel을 설치하는 방법은 여러가지가 있음. 여기서는 Babel standalone을 활용하는데 이 방법이 권고되는 방법은 아니며 느린 편임.

목표

  • JSX를 활용해 createElement()를 좀더 react스럽고 편리하게 대체해보자.

JSX에 대해

  • JSX는 JavaScript를 확장한 문법. JavaScript XML.
  • JSX로 react element를 만들 수 있는데 좀더 HTML 문법에 가깝게 작성할 수 있어 편리함.

이제, JSX로 h3 엘리멘트를 대체해보자.

index.html

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.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 span</h3>
        );
        /*
        const h3 = React.createElement(
            "h3", 
            {
                id: "title",
                onMouseEnter: () => console.log("mouse enter"),
            }, 
            "Hello I'm a span"
        );
        */
        const Button = (
            <button
                style={{
                    backgroundColor: "tomato",
                }}
                onClick={() => console.log("im clicked")}
            >
                Click me
            </button>
        )
        /*
        const btn = React.createElement(
            "button",
            {
                onClick: () => console.log("im clicked"),
                style: {
                    backgroundColor: "tomato",
                }
            },
            "Click me"
        );
        */
        const container = React.createElement("div", null, [Title, Button])
        ReactDOM.render(container, root);
    </script>
</html>
  • JSX는 기존 HTML 문법을 대체로 따르기 때문에 개발자 친화적이며 가독성이 뛰어남. 단지, 엘리멘트 이름을 대문자로 시작하고 값을 ()로 감싸주며 property를 적어줄 때는 : 대신 = 를 쓰며 값에는 {} 로 한 번 더 감싸주기만하면 됨.
  • on+이벤트의 경우, property 같이 작성해주면 됨. 즉, 일반 HTML과 문법이 비슷함. 그래서 React.createElement()보다 개발자들이 보기 편함.
  • 하지만, 엘리멘트 코드만 변경해서는 브라우저에서 에러가 남. 브라우저가 온전히 JSX를 이해하는 것이 아니기 때문. JSX를 한 번 변환해줘야 함. Babel로 할 수 있음.
  • JSX와 React.createElement() 비교
  • Babel 사이트에서 JSX를 변환하기
  • babel 설치 방법
    • babel standalone : 학습 중에만 사용함. 실제 운영에서는 느려서 사용 안함.
  • 코드 작성에 크게 달라지는 것은 없음. 단지, on+이벤트에 대해서 : 대신에 = 를 사용하고 값에 {} 를 한 번 더 감싸줌.

2.6 JSX part Two

요약

  • Title과 Button 이라는 요소를 JSX로 정의하고 사용하는 것 또한 html 스럽게 태그로 사용할 수 있음. 근데 꼭 대문자로 시작해야 함. 소문자로 사용하면 일반 태그로 인식해서 에러가 남. 그리고 이런 요소를 JSX로 정의할 때, 태그로 사용하기 위해서 꼭 함수로 작성돼야 함.
  • JS에서 함수를 정의할 때, 두 가지 방법이 있음. 일반 방법과 화살표 함수 방법. 전자는 return을 갖고있고 후자는 없음.
  • 마지막에 div 태그에 render 하기 위해 React.render()의 첫번째 인자로 사용한 Container 요소 또한 함수로 만들고 html 스럽게 태그로 작성 가능함. (단 대문자로 시작함)
  • 즉, 어떻게하면 컴포넌트를 컴포넌트 안에 넣어서 더 개발자가 보기 쉽게 작성할 수 있을까에 대한 것.
  • JSX를 쓰면 브라우저 요소를 봤을 때, script에 JSX가 그대로 있으며 head에 보면 이런 JSX 코드들을 react.createElement()로 변환해주는 것을 확인할 수 있음.

목표

  • 실제 index.html 로 뿌려주는 div에 대한 container 엘리멘트를 JSX로 작성해보자.

index.html

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.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 span</h3>
        );

        /*
        const h3 = React.createElement(
            "h3",
            {
                id: "title",
                onMouseEnter: () => console.log("mouse enter"),
            },
            "Hello I'm a span"
        )
        */

        const Button = () => (
            <button
                style={{
                    backgroundColor: "tomato",
                }}
                onClick={() => console.log("im clicked")}
            >
                Click me
            </button>
        )

        /*
        const btn = React.createElement(
            "button",
            {   
                onClick: () => console.log("im clicked"),
                style: {
                    backgroundColor: "tomato",
                }
            },
            "Click me"
        );
        */

        const Container = () => (
            <div>
                <Title />
                <Button />
            </div>
        );
        /*
        const container = React.createElement("div", null, [Title, Button])
        */
        ReactDOM.render(<Container />, root);
    </script>
</html>
  • container 엘리멘트의 이름을 대문자로 시작하게 하고 JSX 문법으로 div를 작성하고 그 안에 Title과 Button 엘리멘트를 적어주자. 이렇게 하면 단순히 텍스트를 출력하기 때문에 에러가나는데 Title과 Button을 변수에서 함수로 만들어주고 대문자로 시작하게 하면 됨.
  • 함수로 만들어진 Title과 Button은 JSX 문법에 맞게 html 태그처럼 사용하면 됨. 예를 들어, <Button /> 로 쓰면 됨. 이는 결국, 함수에서 정의한 html 태그들을 복사해오는 것과 같음. 여기서 중요한 것은 일반적인 html 태그라면 소문자로 시작할 텐데 여기서는 element를 html 태그처럼 사용하므로 대문자로 써줘야 함!
  • 즉, JSX는 앱을 여러가지 작은 요소로 나누어 관리할 수 있게 해줌. 여러 요소로 잘게 쪼개서 만들어주고 합쳐주기만 하면 됨.
  • 마지막에 ReactDOM.render() 부분에서 Container 요소도 함수로 만들고 로 써보자.
  • 즉, 우리가 방금 배운 것은 어떻게 하면 특정 컴포넌트를 다른 컴포넌트 안에 넣는가를 배움.

일반 function 과 arrow function 차이

const Title = () => (
    <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>Hello I'm a span</h3>
);

function Title() {
    return (
        <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
        Hello I'm a span
        </h3>
    );
}
  • 두 함수는 같은 의미임.
  • 소괄호는 return이 없다는 것을, 중괄호는 return이 있다는 것을 전제함.

실제 랜더링된 babel 부분 보기

  • babel 쪽을 보면 작성한대로 React.createElement()가 아니라 JSX를 활용해 요소들을 정의하고 렌더링한 것을 확인할 수 있음.

실제 렌더링된 head 부분 보기

  • 그런데, head 부분을 보면 babel에 의해 해석된 내용이 있는데 Title이나 Button 요소에 대해서 React.createElement()로 변환된 것을 확인할 수 있음.
profile
기록하는 엔지니어 되기 💪

0개의 댓글