리액트 보고서 (19, 오리앤테이션)

윤도훈·2025년 3월 30일

React Orientation

🛠️ 리액트의 특징

1. 컴포넌트 기반

리액트는 UI를 컴포넌트라는 독립적인 조각으로 나누어 개발합니다. 이를 통해 코드의 재사용성과 유지 보수성을 높입니다.

2. 가상 DOM(Virtual DOM)

리액트는 가상 DOM을 사용하여 실제 DOM 조작을 최소화합니다. 상태가 변경될 때마다 가상 DOM에서 업데이트를 수행한 후, 변경된 부분만 실제 DOM에 적용하여 성능을 향상시킵니다.

3. 단방향 데이터 흐름

데이터가 부모 컴포넌트에서 자식 컴포넌트로 전달되고, 자식 컴포넌트에서 부모 컴포넌트의 상태를 직접 변경할 수 없습니다.

4. JSX

리액트는 JSX(JavaScript XML)라는 문법을 사용하여 HTML과 JavaScript를 함께 작성할 수 있습니다.

const element = <h1>Hello, World!</h1>;

5. 상태 관리(State Management)

리액트는 각 컴포넌트의 상태(state)를 관리할 수 있는 기능을 제공합니다. 상태가 변경되면 해당 컴포넌트가 다시 렌더링되어 UI가 자동으로 업데이트됩니다.

6. Hook 을 이용한 관리

함수형 컴포넌트에서 상태와 생명주기를 쉽게 관리할 수 있도록 해줍니다. 기본적으로 제공되는 Hook 외에도 사용자 정의 Hook을 만들어 복잡한 상태 로직을 관리할 수 있습니다.

7. 풍부한 생태계

리액트는 리액트 라우터(React Router), 리덕스(Redux) 등 다양한 라이브러리와 함께 사용되어 애플리케이션의 구조와 상태 관리를 보다 쉽게 할 수 있습니다. 또한 많은 사람들이 사용하는 라이브러리 입니다.


🔂 리액트 18 → 19 에서 달라진점

Auto Batching

리액트 18: 자동 배치 기능이 도입되어 여러 상태 업데이트를 한 번의 렌더링으로 처리할 수 있게 되었습니다.

리액트 19: 자동 배치가 더욱 강화되어 비동기 작업에서도 상태 업데이트가 자동으로 배치됩니다. 이로 인해 성능이 개선되고, 불필요한 렌더링이 줄어듭니다.

→ 이제는 비동기 작업에서도 상태 업데이트가 자동으로 배치되어 불필요한 렌더링이 줄어듭니다.

Concurrent Rendering

리액트 18: Concurrent Mode의 기초가 도입되었으며, startTransition API가 추가되었습니다.

리액트 19: Concurrent Rendering이 더욱 발전하여, 더 많은 기능과 최적화가 추가되었습니다. 이로 인해 더 나은 사용자 경험을 제공할 수 있습니다.

→ startTransition API를 통해 비동기 업데이트의 우선 순위를 조정할 수 있어, 애플리케이션의 반응성을 높일 수 있습니다.

새로추가된 Hook

  • useId 훅

컴포넌트의 고유한 ID를 생성하여 클라이언트와 서버 간에 일관성을 유지할 수 있도록 돕습니다.

import React, { useId } from 'react';

const MyComponent = () => {
  const id = useId(); // 고유한 ID 생성

  return (
    <div>
      <label htmlFor={id}>Name:</label>
      <input id={id} type="text" />
    </div>
  );
};

export default MyComponent;
  • useSyncExternalStore 훅

리액트 애플리케이션에서 외부 데이터 소스와 동기화하여 상태를 관리하는 데 사용됩니다. 이를 통해 외부 저장소의 상태를 React 상태처럼 관리할 수 있습니다.

import React, { useSyncExternalStore } from 'react';

// 예시 외부 저장소
const store = {
  subscribers: new Set(),
  state: { count: 0 },
  
  subscribe(callback) {
    this.subscribers.add(callback);
    return () => this.subscribers.delete(callback);
  },
  
  getSnapshot() {
    return this.state;
  },
  
  setCount(newCount) {
    this.state.count = newCount;
    this.subscribers.forEach(callback => callback());
  }
};

const Counter = () => {
  // 외부 저장소와 동기화된 상태 사용
  const { count } = useSyncExternalStore(store.subscribe, store.getSnapshot);

  return (
    <div>
      <h1>Count: {count.count}</h1>
      <button onClick={() => store.setCount(count.count + 1)}>Increment</button>
      <button onClick={() => store.setCount(count.count - 1)}>Decrement</button>
    </div>
  );
};

export default Counter;

Suspense

액트 18: Suspense의 사용이 개선되어 비동기 작업에서의 대기 상태를 더 잘 처리할 수 있게 되었습니다.

리액트 19: Suspense의 기능이 추가적으로 확장되어, 더 많은 상황에서 사용할 수 있으며, 서버 컴포넌트와의 통합이 개선되었습니다.

→ 이를 통해 비동기 데이터 로딩 시 UI를 더욱 매끄럽게 처리할 수 있습니다.

이외에도 다양한 기능들이 개선되고 추가되었습니다.


🎯 jsx의 기본 규칙 작성 후 예제

jsx 의 규칙

  1. 모든 태그는 반드시 닫혀 있어야 하며, 빈 태그는 /로 닫아야 합니다.
  2. JSX는 항상 단일 루트 엘리먼트를 반환해야 합니다. 여러 요소를 반환하려면 하나의 부모 엘리먼트로 감싸야 합니다.
  3. JSX 내부에서는 중괄호 {}를 사용하여 JavaScript 표현식을 포함할 수 있습니다. 이를 통해 변수나 함수 결과를 동적으로 렌더링할 수 있습니다.
  4. JSX에서 HTML 속성은 camelCase로 작성해야 합니다. 예를 들어, class는 className으로, tabindex는 tabIndex로 작성해야 합니다.
  5. JSX 내에서 조건부 렌더링을 사용할 수 있습니다. 일반적으로 && 또는 삼항 연산자를 사용하여 조건부로 요소를 렌더링합니다.

예제

  • 모든 태그는 닫힌 태그
// 올바른 빈 태그
const element = <br />; 

// 잘못된 예
const element = <br>; 
  • JSX는 항상 단일 루트 엘리먼트를 반환
// 올바른 예
const element = (
  <div>
    <h1>Hello</h1>
    <p>Welcome to JSX</p>
  </div>
);

// 잘못된 예
const element = (
  <h1>Hello</h1>
  <p>Welcome to JSX</p> // 오류 발생
);
  • javascript 표현식 포함
const name = "React";
const element = <h1>Hello, {name}!</h1>; // "Hello, React!" 출력
  • camelCase 로 작성하기
const element = <div className="container" tabIndex={0}>Hello</div>;
  • 조건부 렌더링
const isLoggedIn = true;
const element = (
  <div>
    {isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please log in.</h1>}
  </div>
);

🪞 리액트에서 렌더링의 정의와 초기렌더링과 리렌더링의 차이점

렌더링이란?

리액트에서 컴포넌트를 화면에 표시하는 과정입니다.

즉, React가 상태나 속성이 변경될 때 UI를 업데이트하여 사용자가 볼 수 있도록 하는 것을 의미합니다.

렌더링과정

  1. 컴포넌트 호출: React 컴포넌트가 호출되면 JSX 코드가 실행됩니다.
  2. 가상 DOM 생성: JSX 코드에 따라 가상 DOM이 생성됩니다. 가상 DOM은 실제 DOM의 메모리 내 표현입니다.
  3. 변경 사항 감지: 상태(state)나 속성(props)이 변경되면, React는 새로운 가상 DOM을 생성하여 이전 가상 DOM과 비교합니다.
  4. Diffing: React는 두 가상 DOM을 비교하여 변경된 부분을 찾습니다. 이를 통해 최소한의 변경 사항만 실제 DOM에 적용할 수 있습니다.
  5. 실제 DOM 업데이트: 변경된 부분만 실제 DOM에 적용하여 사용자에게 새로운 UI를 보여줍니다.

초기렌더링과 리렌더링의 차이점

초기 렌더링 : 컴포넌트가 처음으로 화면에 나타나는 과정으로 컴포넌트의 초기 상태와 속성(props)에 따라 UI가 설정됩니다.

리렌더링 : 상태(state)나 속성(props)이 변경되어 컴포넌트가 다시 렌더링되는 과정으로 변경된 데이터에 따라 UI가 업데이트됩니다.

초기렌더링은 초기 상태와 속성(props)에 따라 UI가 설정되는데 리렌더링은 렌더링과정 3번부터 실행되어 새로운 가상 DOM을 생성하여 이전 가상돔과 비교하여 실제 DOM 을 업데이트합니다.

Props 와 State

📖 Props 의 개념과 특징

Props란?

React 의 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는데 사용되는 객체입니다.

특징 : 읽기전용, 데이터 전송, 컴포넌트 재사용성

부모 컴포넌트로부터 데이터 전송받아서 사용할 수 있습니다.

props의 값은 변경하지 못하고 읽기 전용입니다.

각각의 컴포넌트에 다른 값을 줄 수 있어서 코드의 중복성을 줄일 수 있습니다.

사용법

  • 기본
    // Profile 컴포넌트에서 Avatar 컴포넌트로 Props 보내기
    export default function Profile() {
     return (
       <Avatar
         person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
         size={100}
       />
     );
    }
    
    // Avatar 컴포넌트에서 Props 읽기
    function Avatar(props) {
     // props.size, props.name 으로 사용가능
    }
    
    function Avatar({ person, size = 100 }) {
     // 구조분해할당으로 사용가능
     // 기본값은 size prop이 없거나 size={undefined}로 전달될 때 사용됩니다.
    }
  • 모든 props
    function Profile({ person, size, isSepia, thickBorder }) { //계속 반복해서 전달하는 경우
     return (
       <div className="card">
         <Avatar
           person={person}
           size={size}
           isSepia={isSepia}
           thickBorder={thickBorder}
         />
       </div>
     );
    }
    
    모든 Props 전달가능
    
    function Profile(props) {
     return (
       <div className="card">
         <Avatar {...props} />
       </div>
     );
    }
  • jsx
    import Avatar from './Avatar.js';
    
    // 자식으로 jsx를 보낼때
    
    function Card({ children }) {
      return (
        <div className="card">
          {children}
        </div>
      );
    }
    
    export default function Profile() {
      return (
        <Card>
          <Avatar
            size={100}
            person={{
              name: 'Katsuko Saruhashi',
              imageId: 'YfeOqp2'
            }}
          />
        </Card>
      )
    }

리하면

Props는 부모컴포넌트에서 자식 컴포넌트로 데이터를 전달할때 사용되는 객체로, 자식컴포넌트에서 데이터를 읽고 사용할 수 있지만 데이터의 값을 수정할 수 는 없습니다.


🔗 Hook 의 개념과 규칙, 종류

개념 : Hook은 함수형 컴포넌트에서 상태와 생명주기 기능을 사용할 수 있게 해주는 특별한 함수들입니다. 

규칙 :

  1. 최상위 컴포넌트에서 호출

    1. Hook은 컴포넌트에서만 호출가능하고 최상위에서 호출해야 합니다. (if문, for문 안에서 호출불가능)
  2. 함수형 컴포넌트에서만 사용가능

    1. Hook은 함수형 컴포넌트 내에서만 사용할 수 있습니다. class 형 X
  3. use 로 시작하기

    1. Hook은 use로 시작하는 이름을 가져야 합니다.

종류

  • 내장 Hook
    • useState, useEffect, useRef 등등등
  • 사용자 정의 Hook
    • use로 시작하는 함수로, 기본 Hook을 조합하여 특정한 로직을 캡슐화할 수 있습니다.

정리하면

Hook은 함수형 컴포넌트에서 상태와 생명주기 기능을 사용할 수 있게해주는 특별한 함수로

use로 시작하여 함수형컴포넌트의 최상위에서만 호출가능합니다.

종류로는 내장 Hook 과 사용자 정의 Hook 이있는데 때에 따라서 상황에 맞는 Hook을 사용하면됩니다.


🤪 useState 사용문법과 사용예제

사용하는법

리액트 라이브러리에서 useState 를 불러와줍니다.

함수형 컴포넌트의 최상위에서 useState를 이용해서 값을 설정해줍니다.

자료형을 설정해주고 대괄호, 첫번째 요소는 값을 담을 변수, 두번째 요소는 값을 변경할 함수를 설정해줍니다.

예제

input 박스의 값을 관리한다고 가정했을때

import {useState} from 'react'

export default function Login(){
	const [id, setId] = useState('');
	//'' 는 초기값
	return(
		<input type='text' value = id onChange={e=>setId(e.target.value)} />
	)
}

🧱 함수를 이용하여 컴포넌트 작성하기

  1. 기본 함수형컴포넌트

기본사용법

function MyComponent() {
  return (
    <div>
      <h1>Hello, Function Component!</h1>
    </div>
  );
}

export default MyComponent;

함수형은 export default 를 function 앞에 붙일 수 있습니다.

export default function MyComponent() {
  return (
    <div>
      <h1>Hello, Function Component!</h1>
    </div>
  );
}
  1. 화살표함수형 컴포넌트

기본사용법

const MyComponent = () => {
  return (
    <div>
      <h1>Hello, Arrow Function Component!</h1>
    </div>
  );
};

export default MyComponent;
```![](https://velog.velcdn.com/images/dohun_08/post/7f89ec8d-e6c5-417e-af96-0867ac372b46/image.png)

0개의 댓글