[TIL #17] 231102_불변성, Component & Rendering

Bora.K | 권보라·2023년 11월 2일
2

TIL

목록 보기
17/51
post-thumbnail

오늘 한 일


  • [내배캠] React 입문 1주차
    • 불변성과 순수함수, Component & Rendering


학습 내용


불변성

1. 불변성이란?

메모리에 있는 값을 변경할 수 없는 것

(1) 원시데이터: 숫자, 문자, 불리언 등

  • 같은 값이면 같은 메모리 주소값을 참조
  • 새로운 값을 할당하면 새로운 메모리 주소값을 생성하여 참조

불변성이 있다! 즉, 메모리 주소에 할당된 값이 바뀌지 않음

(2) 원시데이터가 아닌 데이터: 배열, 객체, 함수 등

  • 같은 값이어도 별도의 공간에 생성하여 다른 메모리 주소값을 바라봄
  • 새로운 값을 할당하면 기존 메모리 주소값이 바라보는 별도의 공간에서 변경

불변성이 없다! 즉, 메모리 주소에 할당된 값 자체를 변경

2. 리액트에서 데이터 불변성 지키기

(1) 데이터의 불변성을 지켜주어야 하는 이유

리액트는 화면을 렌더링 할지를 state의 변화에 따라서 결정한다. 이 때 state가 변했는지 여부는 메모리의 주소를 비교하여 확인한다. 그래서 원시데이터가 아닌 데이터를 수정할 때 불변성을 지켜주지 않는다면, 값을 바꿔도 리액트는 state가 변경되었다고 인지하지 못하고, 리렌더링이 일어나지 않게 된다.

원시데이터가 아닌 데이터를 수정하면 메모리 주소값은 그대로이기 때문에!

(2) {…obj} 불변성 지키기 위한 방법! 전개 연산자 사용

불변성을 지켜주기 위해 직접 수정을 가하지 않고 전개 연산자를 사용하여 기존 값을 복사(새로운 객체 생성)하여 완전히 새로운 주소값으로 할당한다. 그 이후에 수정한다.

3. 순수함수

이 부분은 어제 수준별 학습 강의(React 환경에서의 배열메서드 활용)를 들으며 내가 헷갈렸던 부분이었다. 어제 궁금했던 내용이 오늘 바로 강의 내용으로 나와 신기했다. 순수함수라는 개념이었구나…

배열 메서드를 사용할 때
a. 매개변수(배열)를 전개연산자로 깊은 복사한 후 새로운 객체로 할당하여 사용하는 경우
b. 매개변수(배열)로 받은 배열 값을 직접 변경하는 경우

a와 b를 각각 어떤 상황에서 사용해야하는지에 대해 궁금했는데, 매개변수에 대한 직접 변경은 피하는 것이 좋다고 한다. 그 이유는 이 매개변수가 또 어디에 쓰일지 모르기 때문이다.

(1) 순수함수
매개변수의 복사한 값을 변경하는 순수함수

const num_arr = [1, 2, 3, 4, 5];

const addSixPure = (arr) => {
  const newArr = [...arr, 6];
  return newArr;
};

(2) 불순함수
매개변수의 값을 직접 변경하는 불순함수

const num_arr = [1, 2, 3, 4, 5];

const addSixInpure= (arr) => {
  arr.push(6);
  return arr;
};

Component & Rendering

1. Component

리액트의 핵심 빌딩 블록 중 하나이자 UI 요소를 표현하는 최소한의 단위

  • 선언체: 보여지고자 하는 UI 요소를 컴포넌트 내부에서 JSX를 통해 선언!

(1) DOM (명령형 프로그래밍)

리액트 개발 이전에는 UI를 표현하기 위해 DOM 객체를 조작하는 명령형 프로그래밍 방식으로 구현했다. 명령형은 어떻게(How)를 중요시 여겨서 제어의 흐름을 제시하고 목표를 명시하지 않는 형태이다.

// 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);

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

선언형은 무엇(What)을 중요시 여겨서 제어의 흐름보다는 목적을 중요시 여기는 형태이다. 직관적이고 관리가 용이하다.

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

2. 렌더링

컴포넌트가 현재의 propsstate의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다.

  • Trigger: UI를 주문하고 전달하여 렌더링을 일으키는 것
  • Rendering: 컴포넌트가 UI를 만들고 준비하는 것
  • Commit: Done의 의미, 리액트가 준비된 실제 UI를 손님 테이블에 올려놓는 것

(1) 렌더링 트리거

  • 첫 리액트 앱이 실행됐을 때
  • state에 변경이 발생했을 때
    • 컴포넌트 내부 state 변경
    • 컴포넌트에 새로운 props가 들어올 때
    • 부모 컴포넌트에서 위의 두 이유로 렌더링이 발생했을 때

(2) 리렌더링

  • setState를 통해 상태를 변경
  • 변경된 UI를 새롭게 반영

Styling

1. map, filter로 반복되는 함수 처리하기

기존 배열을 가공하는 map 함수는 기존 배열의 요소 갯수와 동일한 갯수의 배열을 반환한다. 이에 반해 filter는 조건에 맞는 값만 반환한다. map 함수의 이런 특징을 활용하여 React에서 중복되는 스타일링을 처리할 수 있다.

  • 기존: 중복되는 내용이 많음
function App() {

  return (
    <div className="app-style">
      <div className="component-style">감자</div>
      <div className="component-style">고구마</div>
      <div className="component-style">오이</div>
      <div className="component-style">가지</div>
      <div className="component-style">옥수수</div>
    </div>
  );
}
  • map 활용
    testArr 배열이 map 함수를 통해 각각 component-style 속성을 가진 div 생성
function App() {
  const testArr = ["감자", "고구마", "오이", "가지", "옥수수"];

  return (
    <div className="app-style">
      {testArr.map((item) => {
        <div className="component-style">{item}</div>;
      })}
    </div>
  );
}

💡 map 함수를 사용하면서 화살표 함수에 오류가 발생했다.
한참을 뭐가 문제인지 잘 몰랐다. 구글링도 해 보고, 강의에 나오는 튜터님 코드와 내 코드를 비교해 보고 나서야 return을 안 써서 생긴 오류인 것을 확인했다. 화살표 함수에서 리턴값이 한 줄일 때 return을 생략 가능하다고 배웠던 것을 착각했다. 멀티라인인 경우에는 () ⇒ {return} 중괄호 안에 return을 꼭 써야 한다!

function App() {
  const testArr = ["감자", "고구마", "오이", "가지", "옥수수"];

  return (
    <div className="app-style">
      {testArr.map((item) => {
        return <div className="component-style">{item}</div>;
      })}
    </div>
  );
}
  • filter 활용
    “오이”가 아닌 것을 filter로 거른 다음 map을 통해 스타일 적용
import React from "react";
import "./App.css";

function App() {
  const testArr = ["감자", "고구마", "오이", "가지", "옥수수"];

  return (
    <div className="app-style">
      {testArr
        .filter((item) => {
          return item !== "오이";
        })
        .map((item) => {
          return <div className="component-style">{item}</div>;
        })}
    </div>
  );
}

export default App;

오늘의 회고


  1. React를 배우면서 Javascript 문법도 한 번씩 더 정리하고 있다. 리액트 강의를 들으면서 배열 메서드가 계속해서 나오고 있어서, 생각난 김에 수준별 수업 때 배웠던 배열 메서드를 하나 하나 찾아가면서 다시 정리했다. 기존 배열을 수정, 변경하는 것과 새로운 배열을 반환하는 것으로 카테고리를 나누고 배열 메서드를 정리하고 나니 이제야 좀 이해가 되는 것 같다.

  2. 코드 치는 것에 익숙해 지기 위해 강의를 들으면서 나오는 모든 예제들은 VSCode로 따라 치면서 수업을 듣고 있다. 그런데도 내 코드만 자꾸 오류가 난다. 한 두개의 오타가 꼭 있다. 오늘도 오류가 나서 한참을 찾아보다가 틀린 부분을 찾았는데, 이렇게 오류들을 해결하면서 몸소 체험하면서 배우는 것이 많다. 시간이 많이 걸려서 문제지... 허허

내일 할 일


  • [내배캠] Javascript 문법 5주차
  • [발제] 개인과제
  • [수준별 수업] JS문법 정리 Zoom 강의 참석
profile
Frontend Engineers

0개의 댓글