[React/NomadCoders] ReactJS로 영화 웹 서비스 만들기 (CP 1차시)

ReactJS로 영화 웹 서비스 만들기 (CP 1차시)

CP 프론트 스터디 1차시 내용 정리

💪 React.js는 킹갓엠페러제너럴충무공마제스티이다!

#1

들어가며

리액트도 초창기에는 굉장히 적은 사람들이 사용했다.

하지만 2022년 지금! 리액트는 프론트를 대표하는 프레임워크로 자리매김하고 있다.

왜 많은 사람들이 다른 프레임워크를 두고 어썸한 리액트를 사용했는지 알아보고 공부해 보자.

왜 리액트인가?

새로운 기술을 배우고자 할 때 주의해야 할 점

  1. 누가 해당 기술을 사용하고 있는지

  2. 그들(새로운 기술을 사용하는 개발자)의 규모가 큰지

  3. 그들에게 중요한 기술인지

리액트는 전세계 상위 1만 개의 사이트 중, 무려 약 45%가 사용하고 있는 기술이다.

넷플릭스, 페이스북, 에어비앤비 등등 웹 사이트로 사용자를 유치하는 대형 회사들도 리액트를 사용하고 있다.

→ 이런 기술을 배우는 게 좋은 선택 👍

페이스북의 경우, 리액트를 만들고 그냥 방치해 두는 게 아니라 직접 활용하고 있다.

페이스북 페이지도 다시 리액트로 만들고 개발자도 채용하며 지속적인 투자 및 업데이트를 진행하고 있다.

기술을 배울 때 커뮤니티나 생태계가 매우 중요한데, 리액트 커뮤니티가 엄청 크다.

→ 거의 대부분의 Javascript 커뮤니티를 가져왔다고 봐도 무방하다. (리액트가 JS 기반이기 때문)

리액트를 활용한 기술도 늘어나고 있다.

  • 대표적으로 RN(React Native)이 있고, 최근에는 VR도 리액트로 제작하려는 사람도 있다.

npm 기준, 일주일 동안의 다운로드 수가 천만 회를 넘어가는 프레임워크

따라서, 프론트 프레임워크로 리액트를 공부하는 건 아주 좋은 선택이다!

준비물

JS 기본 지식, 브라우저, VS Code

#2

왜 리액트를 사용하는가?

리액트는 UI와 상호작용하는 기술이다.

  • HTML, JS를 interactive 하게 만들어 준다.

바닐라 JS vs. 리액트

바닐라 JS

<!-- react-for-beginners/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 = counter + 1;
      span.innerText = `Total clicks: ${counter}`;
    }
    button.addEventListener("click", handleClick);
  </script>
</html>
  1. HTML 코드를 작성해 버튼 하나를 만든다.

  2. 만든 버튼을 JS로 가져온다.

  3. 해당 버튼의 click event 를 감지한다.

  4. click 할 때 마다 숫자 1씩 증가되는 기능을 넣어준다.

  5. HTML span 태그에 카운터가 업데이트 되도록 수정한다.

리액트

<!-- react-for-beginners/index.html -->

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <!-- 리액트는 앱의 interactive를 높여주는 라이브러리이고, -->
  <!-- react-dom은 모든 리액트 element를 HTML 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>
  1. 리액트를 CDN으로 가져온다.

  2. JS와 리액트를 활용해 HTML 코드를 작성한다.

    1. React.createElement 로 span 태그를 생성한다.

    2. ReactDOM 으로 HTML 코드에 만든 리액트 element를 렌더링 한다.

      1. root라는 id를 가진 div 태그에 span 태그를 렌더링 한다.
    3. React.createElement 는 첫 번째 인자로 HTML 태그를, 두 번째 인자로 property를, 세 번째 인자로 content를 받는다.

    4. (여기부터는 아래의 리액트로 버튼 만들기 참고) span 태그와 동일한 방법으로 버튼을 생성한다.

    5. span 태그와 버튼을 한번에 렌더링 한다.

      1. React.createElement 의 세 번째 인자에 array 형태로 span 태그와 버튼을 넣어주고, 이렇게 만든 리액트 element를 렌더링 한다.
    6. h3 태그 컴포넌트에도 두 번째 인자로 mouse enter event listener 등록한다.

    7. span 태그를 h3 태그로 변경한다.

    8. 버튼 컴포넌트(React.createElement)의 두 번째 인자로 click event listener 를 등록한다.

      1. 바닐라 JS에서 click event는 click 이지만, 리액트에서 click event는 onClick 이다.

바닐라 JS는 HTML을 먼저 만들고, JS로 가져와서 HTML을 수정해서 사용한다.

리액트는 JS로 시작해 HTML을 만든다.

  • 즉, 리액트는 HTML을 JS로 업데이트 하기 때문에 사용자에게 보여지는 내용을 컨트롤할 수 있다.

리액트로 버튼 만들기

<!-- react-for-beginners/index.html -->

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <!-- 리액트는 앱의 interactive를 높여주는 라이브러리이고, -->
  <!-- react-dom은 모든 리액트 element를 HTML 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("I'm clicked"),
      style: {
        backgroundColor: "tomato",
      }}, "Click me"
    );
    const container = React.createElement("div", null, [h3, btn]);
    ReactDOM.render(container, root);
  </script>
</html>

interactive한 앱에서 하는 작업 모두 event를 감지하는 작업이다. → 리액트가 동작하는 방법

React.createElement 의 두 번째 인자로 property를 줬을 때는 HTML 태그에 보이지만, event listener를 줬을 때는 보이지 않는 이유

  • 두 번째 인자로 property(ex. id, class, style …)를 줬을 때, 리액트가 해당 값들이 HTML 태그 안에 들어가야 하는 것을 알기 때문이다.

  • 두 번째 인자로 event listener를 줬을 때, 리액트가 해당 값 들이 JS에서 돌아가는 이벤트인 것을 알기 때문이다.

복습

  1. 리액트와 react-dom을 CDN으로 가져온다.

    1. 리액트는 element를 생성하고 event listener 추가하는 것을 도와준다. → interactive power를 가지고 있다.

    2. react-dom은 리액트 element를 HTML 코드로 바꿔준다.

      1. 코드 상으로 <div id="root"></div> 부분에 ReactDOM 리액트 element를 넣는다.

      2. ReactDOM.render 은 리액트 element를 root div 안에서 보여주라는 것을 의미한다.

      3. ReactDOM.render 의 첫 번째 인자는 렌더링 할 리액트 element를, 두 번째 인자는 타겟팅되는 HTML 태그를 받는다.

  2. React.createElement 의 첫 번째 인자는 root에 들어갈 HTML 태그를, 두 번째 인자는 id나 class, event listener 등의 props object를, 세 번째 인자는 리액트 element 등을 받는다.

    1. 리액트 개발자들은 interactive한 앱을 만들기 위해서 event listener가 필요하다고 생각하고, element에 event listener를 달고자 했다. → 리액트가 훌륭한 이유

    2. 원하는 만큼 props에 event listener를 추가할 수 있다.

JSX (createElement를 대체할 수 있는 방법)

왜 React.createElement 를 대체하는가?

조금 더 편리하게 사용하기 위해

JSX란?

  • Javascript를 확장한 문법

HTML과 비슷한 문법으로 리액트 element를 만들 수 있게 해준다.

...
// React.createElement
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("I'm clicked"),
  style: {
    backgroundColor: "tomato",
  }}, "Click me"
);

// JSX
const Title = (
  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I'm a title
  </h3>
);
const Button = (
  <button
    style=
    onClick={() => console.log("I'm clicked")}
  >Click me</button>
);
...

위의 코드처럼 변환한 코드를 바로 사용하려면 에러가 발생한다. → 브라우저가 이해하지 못하기 때문

Babel 을 사용해 브라우저가 이해할 수 있는 React.createElement 의 형태로 변환해야 한다.

// JSX
const Title = (
  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I'm a title
  </h3>
);
const Button = (
  <button
    style=
    onClick={() => console.log("I'm clicked")}
  >
    Click me
  </button>
);

// Babel로 변환한 코드
("use strict");

const Title = /*#__PURE__*/ React.createElement(
  "h3",
  {
    id: "title",
    onMouseEnter: () => console.log("mouse enter")
  },
  "Hello I'm a title"
);
const Button = /*#__PURE__*/ React.createElement(
  "button",
  {
    style: {
      backgroundColor: "tomato"
    },
    onClick: () => console.log("I'm clicked")
  },
  "Click me"
);
  • Babel을 CDN 형태로 가져와서 사용
<!-- react-for-beginners/index.html -->

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <!-- 리액트는 앱의 interactive를 높여주는 라이브러리이고, -->
  <!-- react-dom은 모든 리액트 element를 HTML 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>
  <!-- jsx 문법을 변환하기 위해 Babel을 가져옴 (이 방식은 느려서 선호되는 방식은 아님) -->
  <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=
        onClick={() => console.log("I'm clicked")}
      >
        Click me
      </button>
    );
    const container = React.createElement("div", null, [Title, Button]);
    ReactDOM.render(container, root);
  </script>
</html>

해당 HTML 파일을 로컬 환경에서 실행한 후,

개발자 도구의 Elements 탭에서 JSX로 작성한 script와 Babel이 변환한 script가 모두 존재하는 것을 확인할 수 있다.

컴포넌트 in 컴포넌트 (JSX)

컴포넌트를 JSX 문법으로 가져올 때, 단순히 div 태그 안에 컴포넌트명을 텍스트로 작성해서 가져올 수는 없다.

  • <div>Title Button</div> 과 같은 형태는 불가능
  1. 가져올 컴포넌트를 함수 형태로 바꿔준다.

    • 익명함수의 형태로 변경해도 좋고, 일반적인 함수 표현식으로 변경해도 좋다.

    • 일반적인 함수 표현식으로 변경하려면 반드시 JSX 문법을 return 해야 한다.

    ...
    // arrow function (익명함수)
    const Title = () => (
      <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
        Hello I'm a title
      </h3>
    );
    const Button = () => (
      <button
        style=
        onClick={() => console.log("I'm clicked")}
      >Click me</button>
    );
    
    // same as
    function Title() {
      return (
    	  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    	    Hello I'm a title
    	  </h3>
    	);
    }
    function Button() {
      return (
    	  <button
    	    style=
    	    onClick={() => console.log("I'm clicked")}
    	  >Click me</button>
    	);
    }
    ...
    
  2. JSX 문법의 형태로 리액트 컴포넌트를 가져온다.

    • 일반적인 HTML 태그를 사용할 때와 동일한 방법을 사용한다.
    ...
    const Container = (
      <div>
        <Title />
        <Button />
      </div>
    );
    
    // same as
    const Container = (
      <div>
    	  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    	    Hello I'm a title
    	  </h3>
        <button
    	    style=
    	    onClick={() => console.log("I'm clicked")}
    	  >Click me</button>
      </div>
    );
    
    ...
    
    • 위의 코드는 div를 렌더링 하는 컴포넌트가 Title, Button에 관련된 코드를 포함시키고 있는 형태라고 생각하면 된다.

    • 컴포넌트의 첫글자는 반드시 대문자여야 한다.

      • 만약 소문자면, 리액트와 JSX 문법은 <button /> 태그가 일반적인 HTML의 버튼 태그라고 생각할 것
    • JSX는 앱을 여러 작은 요소로 나눠 관리할 수 있도록 도와준다.

    • 마찬가지로 개발자 도구의 Elements 탭에서 확인해 보면, JSX로 작성한 부분이 React.CreateElement 로 변환된 것을 확인할 수 있다.

  3. Container까지 함수로 변경한 후, ReactDOM 코드도 JSX 문법으로 변경해 준다.

    <!-- react-for-beginners/index.html -->
    
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <!-- 리액트는 앱의 interactive를 높여주는 라이브러리이고, -->
      <!-- react-dom은 모든 리액트 element를 HTML 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>
      <!-- jsx 문법을 변환하기 위해 Babel을 가져옴 (이 방식은 느려서 선호되는 방식은 아님) -->
      <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=
            onClick={() => console.log("I'm clicked")}
          >
            Click me
          </button>
        );
        const Container = () => (
          <div>
            <Title />
            <Button />
          </div>
        );
        ReactDOM.render(<Container />, root);
      </script>
    </html>
    

끝!

이 글의 저작권은 Attribution-NonCommercial 4.0 International 라이센스를 따릅니다. Attribution-NonCommercial 4.0 International