[항해99 리액트 입문] 12~14. 컴포넌트와 렌더링, 카운터 만들기, css 꾸미기

posinity·2022년 11월 28일

12. 컴포넌트와 렌더링

1. Component

컴포넌트란 리액트의 핵심 빌딩 블록 중 하나로, UI 요소를 표현하는 최소한의 단위이며 화면의 특정 부분이 어떻게 생길지 정하는 선언체입니다.

리액트의 컴포넌트기반 개발 이전에는 브라우저에서 동적으로 변하는 UI를 표현하기 위해 직접 DOM 객체를 조작하는 명령형 프로그래밍 방식으로 구현했습니다.

기존 명령형 프로그래밍과 리액트 컴포넌트의 선언적 프로그래밍은 어떻게 다른가?

💡 명령형은 어떻게(How)를 중요시 여겨서 프로그램의 제어의 흐름과 같은 방법을 제시하고 목표를 명시하지 않는 형태입니다. 선언형은 무엇(What)을 중요시 여겨서 제어의 흐름보다는 원하는 목적을 중요시 여기는 형태입니다.

DOM (명령형 프로그래밍)

// Hello, World! 화면에 출력하기
// 순수 javaScript 명령형 코드
const root = document.getElementById('root'); 
const header = document.createElement('h1'); 
const headerContent = document.createTextNode(
	'Hello, World!'
);

header.appendChild(headerContent); 
root.appendChild(header);

Hello, World!를 출력하기 위해 컴퓨터가 수행하는 절차를 일일히 코드로 작성해주어야 함.

리액트 (선언형 프로그래밍)

React 코드의 경우 내가 UI을 선언하고 render 함수를 호출하면 React가 알아서 절차를 수행해 화면에 출력해줌

// React 코드 (선언적인)
const header = <h1>Hello World</h1>; // jsx
ReactDOM.render(header, document.getElementById('root'));

2. 렌더링이란?

리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업

  • UI - 음식
  • 컴포넌트 - 음식을 만드는 주방장
  • 리액트 - 웨이터
    라고 가정했을 때,
  1. 렌더링 일으키는 것은 (triggering)- UI를 주문하고 주방으로 전달하는 것
  2. 렌더링한다는 것은 (rendering)- 주방에서 컴포넌트가 UI를 만들고 준비하는 것
  3. 렌더링 결과는 실제 DOM에 커밋한다는 것은 (commit) - 리액트가 준비된 UI를 손님 테이블에 올려놓는 것

1. 렌더링 트리거

렌더링이 발생하는 경우

  1. 첫 리액트 앱을 실행했을 때
  2. 현재 리액트 내부에 어떤 상태(state)에 변경이 발생했을 때.
    • 컴포넌트 내부 state가 변경되었을 때
    • 컴포넌트에 새로운 props가 들어올 때,
    • 상위 부모 컴포넌트에서 위에 두 이유로 렌더링이 발생했을 때

리액트 앱이 실행되고 첫 렌더링이 일어나면 리액트는 컴포넌트의 루트에서 시작하여 아래쪽으로 쭉 훑으며 컴포넌트가 반환하는 JSX 결과물을 DOM 요소에 반영합니다.

2. 리렌더링

리액트 앱이 실행되면 리액트는 전체 컴포넌트를 렌더링하고 결과물을 DOM에 반영해 브라우저상에 보여주죠. 첫 렌더링을 끝난 이후에 추가로 렌더링을 트리거 하려면 상태를 변경해주면 됩니다.

컴포넌트 상태에 변화가 생기면 리렌더링이 발생합니다. 이때 여러 상태가 변경됐다면 리액트는 이를 큐 자료구조에 넣어 순서를 관리합니다.

  1. 주방 예시를 다시 들어보면 리렌더링은 음식점 손님이 첫 주문 이후에 갈증이 생겨 추가로 음료를 주문하거나 처음 받은 음식이 마음에 들지 않아 새로운 메뉴를 주문하는 것과 같습니다.
  2. 새로운 UI주문(리렌더링)이 일어나면 리액트가 변경된 내용을 주방에 있는 요리사인 컴포넌트에 전달하고 컴포넌트는 새로운 변경된 주문을 토대로 새로운 요리(UI)를 만듭니다.
  3. 새롭게 만들어진 요리(렌러딩 결과)는 리액트에 의해 다시 손님 테이블에 올려집니다(DOM에 반영 - commit phase).

3. 브라우저 렌더링 = 페인팅

브라우저의 렌더링과 리액트의 렌더링은 엄연히 다른 독립적인 프로세스입니다. 렌더링이 완료되고 React가 DOM을 업데이트한 후 브라우저는 화면을 그립니다. 이 프로세스를 "브라우저 렌더링"이라고 하지만 혼동을 피하기 위해 "페인팅"이라고도 합니다.

더 읽어볼 자료 : 브라우저는 어떻게 동작하는가?

13. Counter 만들기

지금까지 배운 내용을 활용해서 counter 프로그램을 만들어봅시다.

구현해야 할 기능

  • App.js에 코드를 작성합니다.
  • + 1 버튼을 누를 때마다 숫자가 + 1 증가 합니다.
  • - 1 버튼을 누를 때마다 숫자가 - 1 감소 합니다.

구현 이미지

완성 코드

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);
  return (
    <div>
      {count}
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        +
      </button>
      <button
        onClick={() => {
          setCount(count - 1);
        }}
      >
        -
      </button>
    </div>
  );
}

export default App;

14. 컴포넌트 꾸미기

1. 컴포넌트 스타일링

(1) 새로운 프로젝트 생성하기

이번 챕터를 시작하기에 앞서 우리가 연습할 새로운 프로젝트를 하나 더 생성해봅시다.

yarn create react-app 프로젝트이름

(2) 컴포넌트 구현해보기

우선 아래 이미지와 같이 한번 구현해볼까요? 아래의 CSS 치트 시트를 활용해서, 화면과 최대한 똑같이 만들어봅시다!

CSS 치트시트

  • padding
  • display : flex
    • alignItems
    • justifyContent
  • gap
  • width, height
  • border
  • borderRadius

구현 결과

나의 코드

import React from "react";

function App() {
  const all = {
    marginTop: "20px",
    gap: "20px",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  };
  const styles = {
    border: "1px solid green",
    width: "100px",
    height: "100px",
    borderRadius: "10px",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  };
  return (
    <div style={all}>
      <div style={styles}>감자</div>
      <div style={styles}>고구마</div>
      <div style={styles}>오이</div>
      <div style={styles}>가지</div>
      <div style={styles}>옥수수</div>
    </div>
  );
}

export default App;

강의 정답 코드

import React from "react";

const App = () => {
  const style = {
    padding: "100px",
    display: "flex",
    gap: "12px",
  };

  const squareStyle = {
    width: "100px",
    height: "100px",
    border: "1px solid green",
    borderRadius: "10px",
		display: "flex",
    alignItems: "center",
    justifyContent: "center",
  };

  return (
    <div style={style}>
      <div style={squareStyle}>감자</div>
      <div style={squareStyle}>고구마</div>
      <div style={squareStyle}>오이</div>
      <div style={squareStyle}>가지</div>
      <div style={squareStyle}>옥수수</div>
    </div>
  );
};

export default App;

(3) 컴포넌트 파일에서 CSS 코드 분리하기

  1. css파일 import해주기

    import "./App.css";

  2. App.css에서 css코드 옮기기
    우리가 원래 사용하던 방식대로 쓰면 됌.
    - 없앤것도 다 넣어주고 뒤에 세미클론 붙혀주기
.app-style {
  border: 1px solid green;
  width: 100px;
  height: 100px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.all {
  margin-top: 20px;
  gap: 20px;
  display: flex;
  padding: 100px;
}
  1. className = "클래스이름" 으로 명명하기
  2. 최종 코드
import React from "react";
import "./App.css"; //css파일 임포트

function App() {
  return (
    <div className="all"> //
      <div className="app-style">감자</div>
      <div className="app-style">고구마</div>
      <div className="app-style">오이</div>
      <div className="app-style">가지</div>
      <div className="app-style">옥수수</div>
    </div>
  );
}

export default App;

더 알아보면 좋은 키워드

  • CSS 기초 더 알아보기 (링크)
  • display flex 속성에 관해 더 알아보기 (링크)
profile
문제를 해결하고 가치를 제공합니다

0개의 댓글