도은
  • React는 UI를 렌더링하기 위한 자바스크립트 라이브러리이다.
  • UI는 버튼, 텍스트, 이미지와 같은 작은 요소로 구성
  • React를 통해 이 작은 요소들을 재사용 가능하고 첩할 수 있는 컴포넌트로 조합 가능하다.

Your first component

  • React는 컴포넌트라고 불리는 독립적인 UI 조각들로 구성
  • React 컴포넌트는 마크업을 포함할 수 있는 자바스크립트 함수이다.

컴포넌트: UI 구성 요소

  • 웹에서는 HTML을 통해 <h1>, <li>와 같은 태그를 사용하여 문서를 만들 수 있다.
  • 마크업은 스타일을 위한 CSS, 상호작용을 위한 JS와 결합 → UI의 기반
⭐️ React를 사용하면, 마크업 & CSS, JS를 재사용 가능한 UI 요소인 컴포넌트로 결합 가능하다
  • 프로젝트 규모가 커질수록, 이미 작성한 컴포넌트를 재사용 → 생산성 ⬆️

컴포넌트 정의하기

⭐️ React 컴포넌트는 마크업을 포함할 수 있는 자바스크립트 함수이다.

브라우저에 표시되는 내용

  • <section>은 소문자 → React는 HTML 태그를 가리킨다고 해석
  • <Profile />은 대문자로 시작 → React는 컴포넌트를 사용한다고 해석

컴포넌트 중첩 및 구성

  • 컴포넌트는 일반 자바스크립트 함수이므로 같은 파일에 여러 컴포넌트 포함 가능

Importing and exporting components

📖 DEEP DIVE ) Default와 Named Exports

  • 자바스크립트에서는 default exportnamed export 라는 2가지 방법으로 값을 export 하는 것이 가능
  • 한 파일에는 하나의 default export만 존재할 수 있고, named export는 여러 개 존재 가능성
  • 보편적으로는
    • 한 파일에서 하나의 컴포넌트만 export할 때는 default export 방식
    • 여러 컴포넌트를 export할 경우 named export를 사용
  • 어떤 방식을 사용하든, 컴포넌트와 파일의 이름을 의미있게 명명하는 것이 중요

Writing markup with JSX

⭐️ JSX는 자바스크립트를 확장한 문법, 자바스크립트 파일에서 HTML과 비슷하게 마크업을 작성할 수 있도록 해준다.

JSX: JavaScript에 마크업 포함하기

  • Web은 HTML, CSS, JavaScript를 기반으로 구성
  • 보통은 HTML, CSS, JavaScript를 분리된 파일로 관리
  • Web이 더욱 인터랙티브해지면서, 로직이 내용을 결정하는 경우가 많아졌다.
  • 렌더링 로직과 마크업이 함께 있다면
    • 매번 변화가 생길 때 마다 서로 동기화된 상태 유지
⭐️ React 컴포넌트는 React가 브라우저에 마크업을 렌더링할 수 있는 JavaScript 함수이다.

📖 DEEP DIVE ) 왜 여러 JSX 태그를 하나로 감싸줘야 할까?

  • JSX는 HTML처럼 보이지만, 내부적으로 일반 JavaScript 객체로 변환
  • 하나의 함수에서 객체 2개를 반환한다고 생각해보자, 이럴 떄 배열로 감싸야하지 않는가
  • 이것처럼 하나의 태그 또는 Fragmented로 감싸지 않으면, 두 개의 JSX 태그를 반환할 수 없다.

JavaScript in JSX with curly braces

중괄호 사용하기

  • 중괄호 { } 사이에 JavaScript를 사용할 수 있다.

이중 중괄호 사용하기

  • JSX는 문자열, 숫자 및 JS 뿐만 아니라 객체 전달 가능
  • JSX에 객체를 전달하려면 person={{ name: 'Hedy Lamarr' }}와 같이 가능

Conditional rendering

  • 컴포넌트는 조건에 따라 다른 항목을 표시해야 하는 경우가 많다.
  • React는 if문, &&? : 연산자와 같은 자바스크립트 문법을 사용하여 조건부로 JSX를 렌더링할 수 있다.

조건부로 null을 사용하여 아무것도 반환하지 않기

  • 어떤 경우에는 조건에 따라 아무것도 렌더링하고 싶지 않을 수 있는데
  • 이럴 때 null을 반환
if (isPacked) {
  return null;
}
return <li className="item">{name}</li>;

🤔 간혹 아무것도 렌더링하고 싶지 않을 때 <></>을 리턴하기도 하는데, 다른걸까?

역시 누가 비교해두었다 (opens in a new tab)

  • 공식문서 Fragment는 DOM에 별도의 노드를 추가힞 않고 여러 자식을 그룹화할 수 있다고 명시되어 있다.
  • 위와 같은 용도로 사용하고
  • 반환할 JSX가 없는 것의 의도한다면 null을 사용하는 것이 좋을 것 같다.

Keeping components pure

Purity

  • 순수 함수는 다음과 같은 특징을 가지고 있는 함수이다.
    • 같은 입력이 주어졌다면, 순수함수는 같은 결과를 반환
  • React는 순수 함수 컨셉을 기반으로 설계
    • React는 작성되는 모든 컴포넌트가 순수 함수일 것이라 가정
    • 즉, 같은 입력이 주어진다면 반드시 같은 JSX를 반환한다는 것을 의미

Side Effect

  • React의 렌더링 과정은 항상 순서해야 한다.
  • 컴포넌트는 렌더링하기 전에 존재했던 객체나 변수들을 변경하지 말고, JSX만 반환

📖 DEEP DIVE ) 엄격 모드에서 순수하지 않은 연산을 감지

  • React는 개발 중에 각 컴포넌트의 함수를 두 번 호출하는 "엄격 모드"를 제공
  • 컴포넌트 함수를 두 번 호출함으로써, 엄격 모드는 이러한 규칙을 위반하는 컴포넌트를 찾는데 도움
  • 순수함수 컴포넌트라면, 두 번 호출해도 아무 것도 변경되지 않는다.

부작용을 일으킬 수 있는 지점

  • 함수형 프로그래밍은 순수성에 크게 의존하지만
  • 언젠가는, 어딘가에서, 무언가가 바뀌어야 한다.
  • 이러한 변화들(화면 업데이트, 애니메이션 시작, 데이터 변경)을 사이드 이펙트라고 한다.
  • 렌더 중에 발생하는 것이 아니라, 사이드에서 발생하는 현상
⭐️ React에서는 사이드 이펙트는 보통 이벤트 핸들러에 포함된다.
  • 이벤트 핸들러가 컴포넌트 내부에 정의되어 있다고 하더라도
  • 렌더링 중에 실행 X → 이벤트 핸들러는 순수할 필요 X

Your UI as a tree

  • React는 서로 중첩된 많은 컴포넌트로 구성
  • React는 어떻게 컴포넌트 구조를 추적하는 것일까?

트리로서의 UI

  • 브라우저는 DOM과 CSSOM을 모델링 하기 위해 트리 구조를 사용

렌더트리

  • 컴포넌트를 중첩하면, 부모 컴포넌트와 자식 컴포넌트의 개념 → 각 부모 컴포넌트는 다른 컴포넌트의 자식이 될 수 있다.

📖 DEEP DIVE ) 렌더 트리에서 HTML 태그는 어디에?

  • 렌더 트리는 React 컴포넌트로만 구성되어 있다.
  • React는 모바일이나 데스크톱 플랫폼에서 렌더링될 수 있으며, 다른 UI 기본 요소를 사용할 수도 있는 것
  • React 렌더 트리는 렌더링되는 플랫폼에 관계 없이 제공되는 것

모듈 의존성 트리

  • 컴포넌트를 분리하고, 로직을 별도의 파일로 분리하면 → JS 모듈
  • 모듈 의존성 트리의 각 노드는 모듈

  • 의존성 트리는 React 앱을 실행하는 데 필요한 모듈을 결정
  • React 앱을 프로덕션용으로 빌드할 때, 클라이언트에 제공할 모든 JS를 번들로 묶는 빌드 단계 존재하는데
  • 이 작업을 수행하는 번들러, 번들러는 의존성 트리를 사용하여 포함해야 할 모듈을 결정

🤔 모듈 의존성 트리는 누가 생성하는 것?

  • 번들러
  • 번들러는 엔트리 포인트에서 시작해 필요한 모듈을 모두 탐색
  • 트리 형태로 의존성 관계를 분석

🤔 의존성 트리는 빌드 시에만 생성?

  • 개발 서버 실행 시에도 생성
  • 개발 중에는 파일이 변경될 때마다 이 트리를 다시 생성하거나 갱신(HMR, Hot Module Replacement)
    • vite의 경우
    • 파일 시스템 감지 라이브러리(chokidar)를 사용해, 파일의 변경을 실시간으로 감지
    • 파일이 변경되면, 모듈을 찾아내서 핫 리로드 메시지를 브라우저로 전송
    • 브라우저는 WebSocket을 통해 수신
    • 파일이 수정되면, 서버가 WebSocket을 통해 브라우저에 해당 모듈을 교체하라고
    • 브라우저는 WebSocket을 통해 받은 정보를 바탕으로, 변경된 모듈만 교체 & 나머지 페이지는 그대로 유지