[기술면접] React 부분 3

Boyoung Lee·2024년 12월 30일

기술면접

목록 보기
36/49
post-thumbnail

<목차>

  1. React.Suspense
  2. 리액트에서 상태의 불변성
  3. 제어 컴포넌트와 비제어 컴포넌트

7. React.Suspense

  • 비동기 작업이 완료될 때까지 UI의 일부를 대처하거나 지연시킬 수 있도록 설계된 컴포넌트
  • 코드 스플리팅이나 데이터 페팅과 같은 비동기 작업과 함께 사용

주요 특징
1. 비동기 데이터 처리 지원 : 비동기 작업이 완료될 때까지 UI의 일부분을 대체 콘텐츠로 대체
2. Fallback UI 제공 : 비동기 작업이 진행 중일 때 표시할 대체UI(fallback) 설정 가능
3. React.lazy와 함께 사용 : 코드 스플리팅을 위해 React.lazy와 함께 컴포넌트를 동적으로 로드하는 경우 유용

동작 방식
1. Suspense 내부의 컴포넌트가 비동기 작업을 수행하는 동안 fallback으로 지정된 콘텐츠 표시
2. 작업이 완료되면 원래의 컴포넌트를 화면에 렌더링
3. 여러 Suspense 컴포넌트를 중첩하여 다양한 비동기 작업에 따른 다양한 UI상태 관리

주의 사항

  • Suspense는 클라이언트와 서버에서 모두 작동하지만, 데이터 로딩에 사용하는 경우 React18 이상의 기능과 함께 사용할 것을 권장
  • 데이터를 로드하려면 React 생태계의 라이브러리(ex:React Query, Relay 등)와 결합하여 사용 해야함

**fallback

  • React.Suspense에서 제공하는 속성
  • 비동기 작업이 완료될 때까지 보여줄 대체 UI를 의미
  • 어떤 작업이 로딩 중일 때 사용자에게 "잠깐만 기다려주세요" 같은 메시지와 같다.
  • 로딩중
import React, { Suspense } from "react";

const LazyComponent = React.lazy(() => import("./LazyComponent"));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

export default App;

**React.lazy

  • 레이지로딩을 구현하는 하나의 방법
  • 코드 스플리팅을 위해 제공되는 함수
  • 컴포넌트를 동적으로(import시점에 따라)로드 할 수 있게 함
  • 애플리케이션의 성능을 최적화하고 초기 로딩 시간을 줄이는데 유용
  • Webpack, Vite 같은 번들러와 함께 사용해야 제대로 동작

React.Suspense에 대해 설명해주세요.

8. 리액트에서 상태의 불변성

  • 리액트는 상태가 바뀌면 화면을 다시 그려야 한다고 약속 -> 상태가 바뀌었는지 쉽게 확인하려면 상태가 불변이어야 함

  • React의 작동 방식 및 성능 최적화와 밀접한 관련

    1. 상태 변경 감지를 단순화 하여 React의 효율성을 높임
    • 상태가 불변하다면 상태가 바뀌었는지 확인 하려면 매우 복잡한 작업 필요
    • 리액트는 "참조값(주소)"만 비교 => 참조값만 비교하면 되니까 React가 훨씬 더 빨리 상태 변경을 확인 가능
    1. 가상 돔과 연계된 렌더링 최적화를 가능하게 함
    • 화면을 빠르고 효율적으로 업데이트
    • "필요한 부분만 다시 그리는" 방식으로 화면을 업데이트
    • 참조값을 보고 바뀐것을 확인하면 바뀐부분만 다시 그려냄
    • 불변성을 유지하지 않으면 React는 상태 속성 하나하나를 확인해야하니 느리고 복잡해진다.
    1. 예측 가능한 상태 관리로 디버깅과 유지보수를 쉽게 함
    • 불변성을 유지하면 "예전 상태"와 "새 상태"를 쉽게 비교 가능
    • 문제가 생겼을 때 이전 상태로 돌아가거나 변경 과정을 추적하기 쉬움
    • 상태가 불변성을 유지하지 않으면 변경 이력을 추적하기 어려움
      ex) 리덕스 같은 상태 관리 라이브러리는 상태 변경 이력을 저장해놓고 "돌아가기(Undo)"같은 기능을 구현하기 쉬움
    1. 함수형 프로그래밍 철학과 일치
    • 리액트가 지향하는 철학 "상태를 직접 바꾸지 말고, 새로운 상태를 만들어라"는 방식 권장.
    • 함수형 프로그래밍의 "데이터는 불변이어야 한다"는 철학과 일치
    • 예측 가능
    • 버그가 적어짐
    1. 상태 관리 라이브러리와의 호환성 유지
    • 리덕스, 몹엑스, 주스탠드 등과 같은 상태 관리 라이브러리는 상태 변경 로직에서 불변성을 유지하는 것을 기본 전제로 설계

      ** 상태 관리 라이브러리에서 불변성이 중요한 이유
      - 상태 변경 감지 메커니즘 : 상태가 변경되었는지 감지하기 위해 "참조값 비교"를 사용, 상태가 불변성을 유지하면 변경된 상태와 기존 상태를 참조값만 비교하면 되므로 성능 향상

Q. 리액트의 상태가 불변성을 유지하는 이유는 무엇일까요?

9. 제어 컴포넌트와 비제어 컴포넌트

  • 리액트에서 폼(Form) 요소를 다룰 때 사용되는 두가지 주요한 방식
특성제어 컴포넌트비제어 컴포넌트
데이터 관리 위치React 상태(state)DOM
값 접근 방식상태를 통해 직접 접근ref를 통해 간접적으로 접근
폼 데이터 검증상태 기반으로 실시간 검증 가능제출 시 데이터 접근 후 검증 가능
초기값 설정React 상태를 통해 설정defaultValue 속성을 통해 설정
복잡성복잡한 폼에서는 코드가 길어질 수 있음간단한 폼에서는 코드가 더 간단함

[제어 컴포넌트]

  • React 상태(state)로 폼 요소의 값을 제어
  • 입력값의 변경은 항상 React 상태를 통해 관리, 상태가 변경되면 UI가 업데이트
  • 폼 요소의 값이 React의 상태로 완전히 제어
  • 값과 상태가 동기화
  • 리액트 상태를 통해 폼 데이터를 쉽게 조작하거나 검증
  • 모든 변경 사항은 명시적으로 관리
import React, { useState } from "react";

function ControlledComponent() {
  const [value, setValue] = useState("");

  const handleChange = (event) => {
    setValue(event.target.value); // React 상태 업데이트
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`Submitted value: ${value}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={value} onChange={handleChange} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default ControlledComponent;

장점

  • React 상태와 연결되어 있어 값의 검증, 포맷팅, 로직 처리 등이 간편
  • 상태 기반으로 값을 쉽게 초기화하거나 업데이트
    단점
  • 폼이 복잡할 경우 코드가 길어지고 관리 복잡

[비제어 컴포넌트]

  • 폼 요소의 값을 React상태가 아닌 DOM 자체에서 관리
  • React는 폼 요소에 대한 직접적인 제어권이 없으며, 값은 필요할 때 참조를 통해 읽어온다.
  • 값은 DOM에서 관리 되며 React 상태와 동기화되지 않음
  • 폼 데이터를 참조(ref)를 통해 가져옴
  • 값의 변경은 React 상태와 무관하게 DOM이 직접 처리
import React, { useRef } from "react";

function UncontrolledComponent() {
  const inputRef = useRef(null);

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`Submitted value: ${inputRef.current.value}`); // DOM에서 값 읽기
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={inputRef} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default UncontrolledComponent;

장점

  • 코드가 간결, 간단한 폼에서는 구현이 더 쉬움
  • 초기 값 설정이 DOM 속성을 통해 간단히 가능 (defaultValue)

단점

  • 값 검증이나 상태 기반 로직 처리에는 적합하지 않음
  • React와 DOM 간의 데이터 흐름이 끊어져 관리가 어려울 수 있음

** 언제 어떤 것을 사용해야 할까?
1. 제어 컴포넌트가 적합한 경우

  • 실시간으로 폼 데이터를 검증하거나 로직을 추가해야 할 때
  • React 상태와 폼 데이터를 동기화해야 할 때
  • 폼 데이터가 복잡하고 많은 입력 요소를 포함할 때
  1. 비제어 컴포넌트가 적합한 경우
  • 간단한 폼이나 값 검증이 필요 없는 경우
  • 기존 HTML 폼을 빠르게 React로 전환해야 할 때
  • 성능 최적화가 중요한 경우(React 상태와의 동기화 부담이 적음)

Q. 리액트의 제어 컴포넌트와 비제어 컴포넌트의 차이에 대해 설명해주세요.

profile
정리정돈을 잘하는 개발자가 꿈

0개의 댓글