그럼에도 불구하고

👨‍💻

[면접 준비] React 본문

이모저모/면접 준비

[면접 준비] React

zenghyun 2023. 9. 27. 22:17

Start!

🧑🏻‍💻 라이브러리와 프레임워크의 차이를 알고 있나요? 

  • 라이브러리는 특정 기능 개발을 도와주는 도구들을 모아놓은 개념이고, 프레임워크는 프로그램을 개발하기 위한 구조를 제공하는 개념입니다. 
  • 프레임워크를 사용하면 개발에 대한 전체적인 기능을 제공하고, 프로그램 제어 흐름을 프레임워크에서 관리하는 차이점이 있습니다. 이런 특징을 제어의 역전이라고 합니다.

🧑🏻‍💻 React에 대해 설명해 주세요.

React는 UI를 만들기 위한 JavaScript 라이브러리입니다.

React는 스스로 상태를 관리하는 캡슐화된 컴포넌트를 조합해 복잡한 UI를 만들 수 있도록 지원하며, 데이터가 변경됨에 따라 적절한 컴포넌트만 효율적으로 갱신하고 렌더링 합니다.

🧑🏻‍💻 React의 원리, 특징이 무엇인가요?

React의 큰 특징으로는 Virtual DOM 개념과, 단방향 데이터 바인딩이 있습니다.

  • 리액트는 단방향 데이터 플로우를 가지고 있습니다. 부모에서 자식 컴포넌트로 props를 전달하는 방식으로 작동합니다.
  • 리액트는 가장 많은 사용자가 사용하는 라이브러리로, 생태계가 넓어서 많은 문서와 라이브러리가 존재합니다. 
  • 리액트는 컴포넌트라는 단위로 개발을 진행합니다. 독립적인 컴포넌트 단위로 나눠서 개발하고 관리하기 때문에 유지보수가 용이합니다. 그리고 반복되는 기능을 컴포넌트를 재사용하여 해결할 수 있습니다. 
  • 가상 돔(Virtual DOM)을 사용합니다. 리액트를 사용하면 메모리 상에 가상의 돔 오브젝트를 생성하고 관리합니다. 

🧑🏻‍💻 리액트는 어떻게 화면을 변경하나요?

  • 리액트는 Virtual DOM이라는 개념을 통해 UI를 관리하고, 실제 DOM과 동기화해서 화면을 변경합니다.
  • 조금 더 자세하게 설명드리면, 변경사항들을 메모리 상의 Virtual DOM에 먼저 적용하고, 바뀐 부분만 실제 DOM에 적용합니다.

📌 가상 돔을 사용하는 이유가 있을까요?

  • 자바스크립트 코드를 통해 화면을 나타내는 DOM을 수정하면 렌더링 과정 중 레이아웃이나 페인트 과정이 다시 발생하게 됩니다. 이 과정을 리플로우와 리페인트라고 합니다.
  • 반응형 웹에서 이런 수정이 많이 발생해서 리플로우와 리페인트, 특히 리플로우 과정이 많이 발생하면 브라우저 성능이 떨어지게 됩니다.
  • 그래서 리액트는 Virtual DOM에 변경 사항을 적용하고, 실제로 변경된 부분을 계산해서 DOM에 일괄로 적용하는 Batch Update를 적용해서 성능을 최적화했습니다.
  • 그리고 개발자는 선언적으로 코드를 작성할 수 있습니다. 어떤 부분을 어떻게 실제 DOM에 적용하는지와 같은 과정을 Virtual DOM에게 위임할 수 있습니다.

📌 리액트에서 가상 작동 방식을 설명해 주세요.

리액트는 재조정이라는 과정을 통해 Virtual DOM을 이용해서 실제 DOM 을 조작합니다.

  • 리액트는 항상 두 개의 Virtual DOM을 가지고 있습니다. 하나는 업데이트를 위한 Virtual DOM, 다른 하나는 업데이트가 되지 않은 Virtual DOM입니다.
  • 일정 시간 동안 컴포넌트의 상태가 변경되면 변경사항을 업데이트를 위한 Virtual DOM 트리에 적용합니다.
    • (참고) Virtual DOM에 변경사항을 적용하는 부분은 오래 걸리지 않습니다.
  • 그리고 시간이 지나면 업데이트된 Virtual DOM과 업데이트 전의 Virtual DOM을 diffing 알고리즘을 사용해서 비교합니다.
  • diffing 알고리즘의 결과로 실제로 변경된 부분을 알 수 있고, 그 부분을 일괄적으로 실제 DOM에 적용합니다.
  • 이렇게 Virtual DOM을 사용해 여러 개의 상태 변경을 일괄적으로 실제 DOM에 적용하는 것을 Batch Update라고 합니다.

📌 리액트에서는 가상 돔의 변경점을 어떻게 알아내나요? (diffing 알고리즘)

  • 리액트는 두 개의 가상돔을 가지고 있고, 업데이트된 가상돔과 업데이트 전 가상돔을 비교해서 변경사항을 찾고 있습니다.
  • 모든 DOM 트리를 비교하는 알고리즘은 O(n^3) 시간이 들어서, 리액트에서는 특정 조건에서 휴리스틱한 O(n) 알고리즘을 사용합니다.
    • 첫 번째 조건은 타입이 다른 Element는 다른 트리를 만든다는 가정이고, 두 번째 조건은 개발자가 key라는 Props를 통해 트리의 변경 사항을 알려준다는 가정입니다.
  • 그래서 비교 과정에서 각 Virtual DOM 트리의 루트부터 비교를 시작하는데, 다른 Element로 변경됐을 경우 해당 서브트리를 제거하고 새로운 서브트리를 적용합니다.
  • 만약 같은 Element 라면 className이나 다른 props 들을 비교하여 변경사항만 적용합니다.
  • 그리고 이 과정을 재귀적으로 하위 Element에 대해 반복합니다.

📌  fiber (파이버) 무엇인가요?

  • fiber는 리액트 가상 돔 변경 과정에서 발생하는 동시성, 애니메이션과 같은 문제점들을 해결하기 위해 적용한 알고리즘입니다.

🧑🏻‍💻 컴포넌트의 key에 대해 설명해 주세요.

  • key 은 리액트에서 Element의 고유성을 부여하기 위한 값으로, 리액트에서 Element를 식별하고, 변경하거나 제거할 때 사용합니다.
  • 그래서 Element 리스트를 표현할 때에는 각 Element 마다 항목을 고유하게 식별할 수 있는 id를 key로 전달하게 됩니다.
  • 이렇게 전달된 key는 리액트에서 변경을 감지할 때 사용합니다. key가 없다면 자식 Element를 비교할 때, 하나라도 다르면 트리를 다시 구성해서 나쁜 성능을 보입니다.
  • 하지만 key을 통해, key 값을 기준으로 추가되거나 삭제된 Element를 식별하고, 이를 기반으로 갱신합니다.
    • (그래서 변경될 수 있는 index와 같은 값을 key로 사용하는 것보다는 고유한 id를 사용해야 합니다.)

🧑🏻‍💻 JSX에 대해 설명해 주세요.

JSX는 JavaScript를 확장한 문법으로, 공식문서에서 React와 함께 사용할 것을 권장하고 있는 문법입니다.

JSX는 JavaScript의 모든 기능이 포함되어 있으며, React Element를 생성하기 위해 사용됩니다.

📌 리액트에서 JSX를 사용하면 어떤 장점이 있나요?

HTML 문법을 알고 있다면 UI 작업 시 더 직관적으로 코드를 이해할 수 있습니다. 

그리고 리액트는 마크업 파일과 여러 가지 로직을 담고 있는 파일을 분리하지 않고 컴포넌트라는 개념으로 하나의 파일에 코드를 작성합니다. 그래서 높은 응집도의 코드를 작성할 수 있습니다.

📌 리액트에서 JSX 어떻게 작동하나요?

리액트에서 JSX는 리액트 라이브러리의 createElement를 Syntax Sugar 한 개념입니다. 

JSX 문법이 적용된 코드는 babel을 통해 React.createElement라는 함수 호출로 변경됩니다.

📌  React 직접 호출되지 않는데 import React 해야 하는 이유를 알고 있나요?

  • 리액트는 JSX라는 문법을 사용하는데, 리액트 17 이전에는 JSX 문법으로 작성된 코드를 babel을 통해 React.createElement라는 함수 호출로 변경했습니다.
  • 그래서 JSX로 작성된 코드에서는 보이지 않지만, 실제로 실행할 때에는 React 가 import 되어야 합니다.
  • 하지만 리액트 17 버전 이후부터는 babel에서 빌드 시점에 따로 처리해 주기 때문에 import 할 필요가 없게 되었습니다.

📌 리액트에서 JSX 사용 주의해야 점이 있을까요?

  • 컴포넌트를 JSX 문법으로 호출할 때, 컴포넌트 이름은 반드시 대문자로 시작해야 합니다.
    • (이유) 왜냐하면 소문자로 시작하는 Element는 내장 컴포넌트로 인식합니다. 내장 컴포넌트는 createElement에서 ‘div’나 ‘span’ 같은 문자열 형태로 전달하고 처리하기 때문에 문제가 발생합니다.
  • 그리고 HTML에서 Element의 속성으로 class 속성을 많이 사용하는데, JSX도 자바스크립트 문법을 확장한 문법이기 때문에 class라는 키워드를 사용할 수 없습니다. 대신에 className이라는 속성을 사용합니다. (추가적으로 몇몇 속성들도 camelCase를 사용해야 합니다.)

🧑🏻‍💻 엘리먼트와 컴포넌트의 차이에 대해 설명해 주세요.

엘리먼트는 자바스크립트 객체고, 리액트로 화면을 그려내는 데에 가장 기본적인 요소입니다. 엘리먼트는 한 번 생성되면 다시는 변형되지 않습니다.

반면 컴포넌트는 엘리먼트를 반환하는 함수 혹은 클래스를 의미합니다.

재사용성을 강조하여, 엘리먼트를 좀 더 자유롭게 다룰 수 있으며, 컴포넌트의 이름을 사용하여 하나의 태그처럼 사용할 수 있습니다.

🧑🏻‍💻 리액트에서 컴포넌트를 어떻게 생성하나요?

컴포넌트를 생성하는 방법으로는 함수형 컴포넌트와 클래스형 컴포넌트가 있습니다.

함수형 컴포넌트는 JavaScript 함수와 같은 방법으로 정의하며, 인자를 받아, React element를 반환하도록 만들 수 있습니다.

클래스형 컴포넌트는 ES6의 class를 사용하여 정의합니다. class안에서 render() 함수를 정의하고, 여기에서 React element를 반환하도록 만들 수 있습니다.

주의해야 할 점으로, 컴포넌트의 이름은 항상 대문자로 시작해야 합니다. React는 소문자로 시작하는 컴포넌트를 DOM 태그로 처리합니다. 이는 babel 컴파일을 진행할 때, 원시태그와 컴포넌트를 구분하기 위한 규칙으로, 지키지 않으면 에러가 발생합니다.

🧑🏻‍💻 랜더링(SPA, SSR 등)

⭐️ 🧑🏻‍💻 SPA 대해 설명해 주세요.

  • SPA는 싱글 페이지 애플리케이션의 약자로, 하나의 페이지로 이루어진 애플리케이션이라는 의미입니다.
  • 전통적인 멀티 페이지 어플리케이션 방식은 페이지가 변경될 때마다 서버에서 새로운 HTML 파일을 응답받아서 표시하는 방식을 사용했습니다.
  • 하지만 최근 클라이언트 환경의 성능이 높아져서 리액트와 같은 라이브러리를 통해 클라이언트가 뷰 구성을 담당할 수 있게 되었습니다. 그리고 AJAX 통신을 통해서 전체 페이지가 아닌 필요한 데이터에 대해서만 서버 API 호출을 통해서 받아오고, 그걸 적용해서 페이지 새로고침 없이 뷰를 수정할 수 있게 되었습니다.

📌 Client Side Routing에 대해 설명해 주세요.

CSR은 렌더링이 클라이언트 단에서 일어나는 방식으로, 서버가 클라이언트에 HTML과 JS를 보내고, 클라이언트는 이를 받아 렌더링을 시작합니다.

일반적으로 다음과 같은 순서로 진행됩니다.

  1. User가 웹사이트 요청을 보냅니다.
  2. CDN이 HTML파일과 JS로 접근할 수 있는 링크를 클라이언트로 보냅니다.
  3. 클라이언트는 HTML과 JS를 다운로드합니다.
  4. 다운로드된 JS를 실행하고, 데이터를 위한 API가 호출됩니다.
  5. 서버가 API로부터의 요청에 응답합니다.
  6. API로부터 받아온 데이터를 넣어줍니다. 이제 페이지가 상호작용해집니다.

📌 SPA 특징과 장점을 설명해 주세요.

  • 주로 싱글 페이지 애플리케이션은 클라이언트 사이드 렌더링 방식을 사용합니다.
  • 처음 요청에 따라서 서버에서 HTML 파일과 함께 렌더링에 필요한 자바스크립트, CSS 파일을 받아옵니다. HTML 파일을 받아오고 나서 자바스크립트를 통해 돔을 수정하는 방식으로 작동합니다.
  • 그래서 첫 페이지 로딩 이후에는 전체 페이지가 아닌 변경이 필요한 부분의 데이터만 서버와 통신하여 업데이트합니다. 그래서 로딩 이후 전체적인 트래픽을 줄일 수 있고, 인터렉티브 한 사용자 경험을 제공할 수 있습니다.
  • 그리고 부분적으로 업데이트하는 방식이기 때문에 컴포넌트별 개발 방식과 잘 맞습니다.

📌 SPA 단점을 설명해 주세요.

  • 싱글 페이지 애플리케이션은 처음 요청 시에 서버에서 렌더링 로직을 포함한 HTML, 자바스크립트, CSS 파일을 모두 가져옵니다. 많은 리소스를 한 번에 받아와야 하기 때문에 처음 로딩 속도가 상대적으로 느립니다.
  • 그리고 검색엔진 최적화 이슈가 발생할 수 있습니다. 일반적으로 싱글 페이지 애플리케이션은 클라이언트 사이드 렌더링 방식을 사용하는 경우가 많습니다. 그래서 구글 크롤러 봇처럼 자바스크립트를 실행할 수 있는 봇이 아니면, 아직 렌더링 되지 않은 비어있는 HTML을 크롤링하는 문제가 발생할 수 있습니다.

📌 SEO(검색엔진최적화)가 뭔가요?

  • 구글과 같은 사이트의 검색 엔진들이 서버에 등록된 사이트를 돌아다니면서 문서를 분석합니다. 분석한 데이터로 검색 결과를 표시하게 되는데, 이때 콘텐츠에 포함된 정보를 검색엔진이 잘 수집할 수 있도록 하는 게 검색엔진 최적화입니다.

📌 클라이언트 사이드 렌더링에서 검색엔진 최적화 이슈가 발생하는 이유가 있나요?

  • 클라이언트 사이드 렌더링으로 작성된 사이트들은 일반적으로 처음 접속하면 body가 비어있는 HTML 파일을 받아오고, 자바스크립트를 통해 동적으로 콘텐츠를 렌더링 합니다.
  • 검색엔진의 봇은 사이트를 돌아다니면서 HTML 문서 정보를 수집하는데, 싱글 페이지 애플리케이션에서는 body가 비어있는 HTML 문서를 수집하게 됩니다.
  • 구글의 봇은 자바스크립트를 실행하여 수집할 수 있지만, 대부분의 봇들은 싱글 페이지 애플리케이션의 비어있는 문서를 수집하기 때문에 검색엔진 최적화가 잘 되지 않습니다.

📌 검색엔진 최적화를 할 수 있는 방법을 설명해 주세요.

  • 서버 사이드 렌더링을 적용하는 방법이 있습니다. 서버 사이드 렌더링은 서버에서 HTML문서를 만들어서 응답하기 때문에 사용자도, 검색엔진도 완성된 HTML 파일을 응답받기 때문입니다.
  • 클라이언트 사이드 렌더링을 사용한다면, 사전 렌더링 방식을 적용할 수 있습니다. 검색 엔진이 빈 HTML 파일 대신 내용이 포함된 HTML을 가져갈 수 있도록 빌드타임에 데이터가 포함된 HTML 파일을 생성하는 방식을 사용할 수 있습니다.
  • 그리고 제목이나 헤드 태그 등 HTML 파일에 문서 정보를 잘 나타낼 수 있도록 설정해야 합니다.

🧑🏻‍💻 TTV, TTI를 알고 있나요? (time-to-view, time-to-interect)

  • TTV는 타임 투 뷰의 약자로, 콘텐츠가 화면에 보이는 시점이고, TTI는 타임 투 인터렉트로 사용자와 상호작용이 가능한 시점을 의미합니다.
  • 클라이언트 사이드 렌더링을 사용하면 TTV와 TTI가 동일합니다. 왜냐하면 서버에서 빈 HTML 파일을 받아오고, 자바스크립트 파일도 모두 가져온 이후에 렌더링 하기 때문에 보이는 시점과 상호작용 하는 시점이 동일합니다.
  • 하지만 서버 사이드 렌더링을 사용하면 TTV가 TTI보다 더 빠릅니다. 왜냐하면 서버에서 완성된 HTML 파일을 받아오면 콘텐츠가 화면에 먼저 보이게 됩니다. 그리고 나서 서버에 인터렉션을 위한 자바스크립트를 요청하게 되고, 응답받게 되면 그때부터 실제로 상호작용이 가능합니다.

⭐️ 🧑🏻‍💻 State에 대해 설명해 주세요.

State는 컴포넌트 내부적으로 관리하는 동적인 데이터입니다. 그리고 리액트에서 state가 변경되면 해당 컴포넌트가 다시 렌더링 됩니다.

📌 React에서 State를 어떻게 관리하나요?

배열을 사용하여 관리하고, 해당 배열의 인덱스와 state 값을 클로저 내에 관리하여 useState() 함수가 반환되고 나서도, 별도의 메모리 공간에 값들을 저장합니다.

📌 왜 state를 직접 바꾸지 않고 setState를 사용해야 하나요?

state는 일반적인 변수와 다르게 값이 변하면 리렌더링이 발생합니다. 즉, 값이 변하게 되면, 연관되어 있는 컴포넌트들이 다시 렌더링이 되어 화면이 바뀌게 됩니다.

그런데, React는 setState 호출에 의한 state의 주소 변경에만 반응하여 리렌더링이 발생하게 됩니다. 즉, 이런 방식으로 변경하지 않으면 React가 감지하지 못합니다.

📌 리액트 state 불변성에 대해 설명해 주세요.

  • 불변성은 값이나 상태를 변경할 수 없는 특성을 의미합니다. 이때 변경은 값이 아닌 메모리 영역에서의 변경을 의미합니다.
  • 리액트에서는 상태가 변경되면 다시 렌더링 되는데, 이 변경을 얕은 비교를 통해 수행합니다.
  • 즉 값 하나하나를 비교하는 것이 아니라, 이전 참조값과 현재 참조값을 비교하는 방식으로 변화를 감지합니다.
  • 그래서 상태를 업데이트할 때, 객체 그대로 업데이트하는 대신 의도적으로 스프레드 연산자 등을 통해 값은 같아도 새로운 참조 값을 가진 객체를 전달하는 방식으로 불변성을 유지할 수 있습니다.

📌 React에서 State의 불변성은 어떻게 유지할 수 있나요?

기본적으로 useState를 사용합니다. 만약, state값이 객체인 경우, useState를 통해 상태값을 업데이트할 때, spread 연산자인... 을 이용하여, 깊은 복사를 진행해주어야 합니다.

만약 객체나 배열의 내부가 중첩되어 있다면, immer 라이브러리를 사용하여, 불변성을 유지할 있습니다.

⭐️ 🧑🏻‍💻 Props에 대해 설명해 주세요.

props는 단방향 바인딩을 지원하는 리액트에서 부모 컴포넌트에서 자식 컴포넌트로 내려주는 데이터입니다.

⭐️ 🧑🏻‍💻 Props Drilling에 대해 설명해 주세요.

리액트는 데이터를 전달할 때 부모 컴포넌트에서 자식 컴포넌트로 Props를 통해 단방향으로 전달합니다.

이런 특성으로 인해 컴포넌트의 계층이 깊어지면, 상위 컴포넌트에서 하위 컴포넌트로 어떤 props를 전달하기 위해서 중간에 props를 전달하기 위한 컴포넌트가 생길 수 있습니다. 

 

이러한 전달 방식을 Props Drilling이라고 합니다. 

📌 Props Drilling을 어떻게 해결할 수 있나요?

리액트 자체적으로 제공하는 Context API를 사용할 수 있고, 아니면 Redux 같은 서드파티 상태관리 라이브러리를 사용할 수도 있습니다.

🧑🏻‍💻  컴포넌트는 언제 다시 렌더링 되나요?

  • 다시 호출되면서 props가 변경될 때
  • 컴포넌트 내부의 state가 변경될 때
  • 부모 컴포넌트가 다시 렌더링 될 때 

🧑🏻‍💻 데이터를 자식에서 부모로도 전달할 수 있나요?

props로 부모 컴포넌트의 상태를 변경하는 함수를 전달하고, 자식 컴포넌트에서 props로 넘겨받은 함수를 호출해서 부모 컴포넌트의 상태를 변경할 수 있습니다.

🧑🏻‍💻 Props와 State의 차이에 대해 설명해 주세요.

React legacy 공식문서에 의하면, props는 함수 매개변수처럼 컴포넌트에 전달되는 반면 state는 함수 내에 선언된 변수처럼 컴포넌트 안에서 관리됩니다.

🧑🏻‍💻 React에서 상태 변화가 생겼을 때, 변화를 어떻게 알아채는지에 대해 설명해 주세요.

React는 state를 immutable 하게 관리합니다. 그렇기 때문에 state가 변경되면, state의 주소값이 변경되게 되고, 이 변화를 알아채게 됩니다.

이것이, state가 배열의 형태로 존재할 때, 배열에 원소를 .push()를 이용해 추가하더라도, state 변화를 알아채지 못하는 이유입니다.

🧑🏻‍💻 HTML과 React의 이벤트 처리 차이점에 대해 설명해 주세요.

먼저 문법의 차이가 있습니다.

HTML은 전달할 함수를 문자열의 형태로 전달하지만, React는 함수 그 자체로 핸들러를 전달합니다.

또한 HTML은 이벤트를 소문자로 갖지만, React는 camelCase를 사용합니다. (ex. onClick)

다른 차이점으로는, HTML에서 false를 반환하는 식으로 이벤트의 기본동작을 방지하지만, React에서는 preventDefault를 명시적으로 호출하여 이벤트의 기본동작을 막아야 합니다.

🧑🏻‍💻 Hook

🧑🏻‍💻 훅이란 무엇인가요? (훅 종류에는 어떤 게 있나요?)

  • 리액트 16.8 버전에서 추가된 기능으로, 함수 컴포넌트에서 상태 관리를 포함한 클래스 컴포넌트의 여러 기능을 처리할 수 있도록 하는 기능입니다.
  • 훅 등장 이전에는 함수 컴포넌트에서 상태를 관리할 수 없어서 상태 관련된 로직을 재사용하기 어려웠습니다. 그리고 라이프사이클 메서드를 사용할 수 없어서 복잡한 로직을 처리할 수 없었습니다.
  • 리액트 훅을 통해 함수 컴포넌트에서 상태와 라이프사이클을 후킹할 수 있게 되었습니다.
  • 훅의 종류에는 사용자가 직접 정의하는 커스텀 훅과, 리액트에서 제공하는 훅이 있습니다.
  • 대표적인 리액트의 훅에는 useState, useEffect, useReducer, useContext, useRef, useMemo, useCallback 등이 있습니다.

🧑🏻‍💻 useState 훅을 설명해 주세요.

  • useState는 리액트 훅 중에서 가장 기본적인 훅으로, 상태를 관리하기 위한 훅입니다.
  • useState의 파라미터로 상태의 초기값을 전달할 수 있고, 첫 번째 반환값으로 상태, 두 번째 반환값으로 상태를 업데이트하는 함수를 반환합니다.
  • useState로 생성한 상태값을 함수로 변경하면 상태 값이 변경되고, 해당 상태를 가지고 있는 컴포넌트가 다시 렌더링 됩니다.

📌 useState는 동기적인가요? 비동기적인가요? 그 이유를 설명해 주세요.

useState는 비동기적으로 작동합니다.

  • 리액트에서 state는 변경될 때마다 다시 렌더링이 발생합니다. 만약 상태 변경이 동기적으로 작동한다면 하나의 상태가 변경될 때마다 다시 렌더링이 발생할 수 있습니다.
  • useState는 비동기적으로 작동합니다. 리액트에서는 state batch update라는 이름으로, 일정 기간 동안 변경된 상태를 실제 DOM에 일괄적으로 업데이트합니다. 리액트는 이를 통해 렌더링 횟수를 줄여서 성능을 최적화해 줍니다.

📌 왜 비동기적으로 동작하나요?

그 이유는 리액트의 리렌더링 원리가 비동기적으로 작동하기 때문입니다.

그리고 그 이유는 리액트가 가상돔을 사용하도록 설계되어 있기 때문입니다.

이는 리액트의 Fiber와 밀접한 관련이 있습니다.

 

fiber architecture는 재조정 알고리즘을 구현할 때, 변경된 부분을 찾고, 실제 돔에 변경사항하는 작업을 나누어 진행합니다.

그런데, 과정을 동기적으로 진행한다면, 메인스레드가 차단되고, 이는 프레임 드롭이나 응답지연으로 이어지기 때문에 UX 저해하게 됩니다.

🧑🏻‍💻 useEffect 훅을 설명해 주세요.

  • useEffect는 특정한 상황에서 사이드 이펙트를 실행시킬 수 있는 훅입니다.
  • useEffect의 첫 번째 파라미터에는 사이드 이펙트를 실행할 콜백함수, 두 번째 파라미터에는 배열을 입력합니다.
  • 이펙트 함수는 렌더링 이후 실행되는 함수면서, 만약 이펙트 함수의 반환값으로 콜백 함수가 있다면 컴포넌트가 원마운트 될 때 실행됩니다. 이때 실행되는 콜백 함수를 클린업 함수라고 합니다.
  • 두 번째 파라미터로 전달된 배열은 의존성 배열이라고 부르면서 렌더링 될 때뿐만 아니라 배열 내의 값 중 하나라도 업데이트가 되면 이펙트 함수가 실행됩니다.
  • useEffect 훅을 적절히 사용하면 클래스 컴포넌트에서 사용하는 생명주기 메서드와 비슷한 기능을 구현할 수 있습니다.

🧑🏻‍💻 useLayoutEffect 훅을 설명해 주세요.

  • useEffect 훅은 브라우저가 화면을 페인트 한 후 실행됩니다. 그래서 useEffect 훅을 통해 화면에 표시할 값을 변경할 경우 처음 그려진 화면이 먼저 표시되고, 그 이후에 한번 더 화면이 바뀌게 됩니다.
  • useLayoutEffect는 useEffect 훅과 다르게 리액트 돔이 업데이트된 직후 실행돼서 브라우저가 페인팅되기 전에 실행됩니다. useEffect 훅을 사용했을 때 발생하는 약간의 문제점을 해결할 수 있습니다.

🧑🏻‍💻 useEffect와 useLayoutEffect의 차이점에 대해 설명해 주세요.

제일 큰 차이점은 useEffect는 비동기적으로 동작하고, useLayoutEffect는 동기적으로 동작한다는 것입니다.

리액트에서 useEffect는 렌더링이 끝나고 특정 행동을 수행하고, useLayoutEffect는 렌더링 전에 특정 행동을 수행합니다.

따라서 성능 모니터링이나 애니메이션 구현 즉시 반응이 필요한 경우에 useLayoutEffect 사용하고, 네트워크 요청, DOM 접근, 비동기 작업을 하는 경우에는 useEffect 사용하는 것이 좋습니다.

🧑🏻‍💻 useReducer 훅을 설명해 주세요.

  • 먼저 reducer는 현재 상태와 액션 객체를 파라미터로 받아와서 다음 상태를 반환하는 순수 함수입니다.
  • useReducer 함수는 파라미터로 그런 리듀서함수와 초기 상태값을 입력합니다.
  • 그리고 첫 번째 반환값으로 상태 객체, 두 번째 반환값으로 디스패쳐 함수를 반환합니다.
  • 반환된 디스패쳐 함수에 정의한 액션 타입에 맞는 객체를 전달해서 상태를 변경시킬 수 있습니다.
  • useReducer 훅을 이용하면 상태를 정의하고, 상태를 업데이트하는 복잡한 로직을 조금 더 효율적으로 관리할 수 있습니다.

🧑🏻‍💻 useContext 훅을 설명해 주세요.

  • Context API는 리액트에서 일반적인 props를 통한 전달 대신에 전역적으로 값을 공유할 수 있도록 제공하는 기능입니다.
  • React.createContext 함수를 통해 공유할 콘텍스트 객체를 생성하고, 콘텍스트 객체의 Provider 컴포넌트를 이용해 하위 컴포넌트에 콘텍스트의 변화를 알릴 수 있습니다.
  • useContext는 이렇게 생성된 콘텍스트를 함수형 컴포넌트에서 사용하는 훅입니다.

📌 Context API는 어디에 사용되나요?

  • 데이터를 공유할 때 사용합니다. 대표적으로 프로그램 전체에서 사용하는 테마 정보를 공유할 수 있습니다.

📌 Context API를 상태관리 라이브러리처럼 사용할 수 있나요?

결과적으로 사용은 가능합니다.

  • 하지만 상태관리를 위해 사용했을 때 렌더링 이슈가 발생할 수 있습니다.
  • Context API는 상태관리를 위한 도구가 아니라 단순히 공유를 위한 도구입니다. 그래서 useState 훅 등으로 따로 공유할 상태를 설정하게 됩니다.
  • 이렇게 상태를 관리하면, 다른 상태관리 라이브러리와는 다르게 상태가 변경되면 Provider로 감싸진 컴포넌트의 재렌더링이 발생하게 됩니다.
  • 그래서 상태를 사용하지 않더라도 다시 렌더링이 발생하는 이슈가 있습니다.

🧑🏻‍💻 useRef 훅을 설명해 주세요.

  • 리액트에서 돔을 조작하는 방식과 다르게, ref는 돔 요소에 직접 접근하는 객체입니다.
  • useRef 훅을 사용하면 querySelector와 같은 방식으로 접근할 수 있는 ref 오브젝트를 반환합니다.
  • ref 오브젝트는 일종의 참조값이고, ref.current라는 속성에 실제로 값을 저장할 수 있습니다.
  • ref 에는 특정 값을 저장할 수도 있고, 필요에 따라 돔 요소의 ref 속성으로 전달하여 해당 돔 요소를 직접 접근할 수 있습니다.

🧑🏻‍💻 제어 컴포넌트와 비제어 컴포넌트에 대해 설명해 주세요.

  • 제어 컴포넌트는 리액트 안에서 state 등으로 렌더링과 같은 부분을 관리하는 컴포넌트를 의미합니다.
  • 비제어 컴포넌트는 리액트가 아닌 자바스크립트를 이용하여 관리하는 컴포넌트로, ref를 이용해서 값을 참조하여 관리합니다.

🧑🏻‍💻 ref에 대해 알고 있나요?

  • ref는 컴포넌트 라이프사이클과 별개로 유지되는 오브젝트입니다. 일반적으로 DOM Element에 직접 접근해서 조작할 때 사용합니다.
  • 생성된 ref는 힙 메모리에 자바스크립트 객체로 저장되고, 매번 렌더링 때마다 생성된 동일한 객체를 반환합니다. 그리고 객체 내부의 current 값이 변경되더라도 컴포넌트를 재렌더링 시키지 않는다는 특징이 있습니다.

📌 ref는 언제, 어떻게 사용하나요?

  • ref 오브젝트는 createRef 나 useRef를 호출해서 생성할 수 있습니다.
  • 이렇게 생성한 ref 오브젝트를 JSX로 표현한 Element의 ref 속성에 할당해서 그 Element를 참조할 수 있습니다.
  • 대표적으로 컴포넌트가 렌더링 될 때 input 태그에 focus가 되도록 하거나, 미디어 재생을 조작하거나 하는 부분에서 사용할 수 있습니다.

📌 callback ref에 대해 알고 있나요?

  • Element의 ref 속성에는 두 가지 타입을 입력할 수 있습니다. 하나는 RefObject 타입이고, 다른 하나가 RefCallback 타입입니다.
  • callback ref는 RefCallback 타입으로, ref 객체가 아닌 함수를 전달하는 방식입니다.
  • node라고 하는 Element를 파라미터로 받아서 실행되는 함수로, 컴포넌트가 렌더링 된 후에 실행됩니다.
    • node 파라미터에는 callback ref를 등록한 그 Element 가 전달됩니다.
    • (DOM Element가 렌더링 후에 상호작용 해야 하는 경우 사용합니다.)

📌 forwardRef에 대해 알고 있나요?

  • forwardRef는 ref를 컴포넌트 간 전달하기 위해 사용합니다.
  • 이때 리액트에서 ref는 key와 마찬가지로 props 가 아닌 다른 용도로 전달되도록 설정되어 있습니다.
  • 그래서 하위 컴포넌트의 props에서 전달받은 ref를 참조할 수 없습니다.
  • 이때 하위 컴포넌트를 forwardRef 함수로 감싸게 되면, 부모 컴포넌트에서 전달한 ref를 하위 컴포넌트에서 참조할 수 있습니다.

🧑🏻‍💻 메모이제이션에 대해 설명해 주세요.

메모이제이션이란 계산된 값을 자료구조에 저장하고 이후 같은 계산을 반복하지 않고 자료구조에서 꺼내 재사용하는 것을 말합니다.

🧑🏻‍💻 useMemo 훅을 설명해 주세요.

  • useMemo 훅은 말 그대로 이전에 저장된 값을 메모이제이션 하는 훅입니다.
  • useMemo 훅의 첫 번째 파라미터로 콜백 함수, 두 번째 파라미터로 배열을 저장합니다.
  • 콜백 함수에서는 실제로 저장할 값을 계산하는 로직을 포함합니다.
  • useEffect의 의존성 배열과 마찬가지로 useMemo의 두 번째 파라미터인 의존성 배열에 포함된 값이 업데이트될 때마다 해당 콜백 함수를 다시 실행해서 값을 업데이트합니다.
  • useMemo를 적절히 활용하면 오래 걸리는 복잡한 연산의 결괏값을 저장해 놓고 사용해서 최적화를 할 수 있습니다.

📌 React.memo와 useMemo의 차이에 대해 설명해 주세요.

React.memo는 HOC이고, useMemo는 훅입니다.

React.memo는 컴포넌트 자체를 메모이제이션한 용도로 사용하고, useMemo는 복잡한 계산의 결과 값을 메모이제이션하는 용도로 사용합니다. 물론 컴포넌트도 넣을 수는 있습니다.

 

👉 HOC (Higher-Order Components)

고차 컴포넌트는 컴포넌트를 인자로 받아 새로운 컴포넌트를 다시 return해주는 함수입니다.

🧑🏻‍💻 useCallback 훅을 설명해 주세요.

  • useCallback 훅은 useMemo 훅과 비슷한 기능으로, 함수를 메모이제이션 하는 훅입니다.
  • useCallback 훅도 첫 번째 파라미터로 저장할 콜백 함수, 두 번째 파라미터로 배열을 저장합니다.
  • 두 번째 파라미터로 제공된 의존성 배열에 포함된 값이 변경될 때마다 콜백 함수를 다시 생성합니다.

🧑🏻‍💻 리액트에서 성능 개선을 하는 방법을 설명해 주세요.

  • 첫 번째는 useMemo, useCallback으로 시간이 오래 걸리는 계산 결과를 메모이제이션하는 방법이 있습니다.
  • 두 번째로는 코드 스플리팅 방식이 있습니다. 리액트를 사용한 자바스크립트 코드를 하나로 묶어서 빌드하면 굉장히 크기가 크기 때문에 페이지를 로딩하는 속도가 느려지게 됩니다. 이를 해결하기 위해서 다이나믹 import를 사용하거나, React.Lazy를 사용해 컴포넌트를 비동기적으로 로딩할 수 있습니다. 또는 Next.js 프레임워크를 사용하면 프레임워크에서 코드 스플리팅을 지원합니다.

📌 useMemo와 useCallback 훅의 공통점과 차이점을 설명해 주세요.

  • 가장 큰 차이는 useMemo는 값을, useCallback은 함수를 저장한다는 점입니다.
  • 하지만 둘 다 기존에 저장하던 값을 계속 저장하면서 렌더링마다 다시 계산해야 하는 불필요한 과정을 최적화할 수 있습니다.
  • 그리고 useCallback은 단순히 useMemo 콜백 함수에 콜백 함수를 저장하는 것과 동일한 기능을 합니다.

📌 React.lazy Suspense 컴포넌트가 뭔가요?

👉 React.lazy

SPA는 index.html 파일 하나와 다수의 자바스크립트 코드, 그리고 CSS 파일로 구성됩니다. 이러한 구성 때문에 SPA는 약간의 문제점이 있습니다. 리액트 라우터를 적용한 수백에서 수천 개의 화면과 컴포넌트로 구성된 애플리케이션에서 파일들은 모두 빌드 과정을 거쳐서 하나 또는 몇 개의 .js 파일로 빌드됩니다. 빌드된 파일은 모든 컴포넌트를 묶은 것이므로 파일의 크기도 클 것입니다.

 

첫 화면을 로딩하는 과정을 간단하게 설명드리겠습니다.

  • 사용자는 / 경로로 웹 서버에 요청 정보를 전송합니다.
  • 웹 서버는 index.html과 필요한 모든 산출물(.js 포함)을 브라우저로 응답합니다.
  • 브라우저에서는 / 경로의 첫 화면만 렌더링합니다.
  • 만약, 다른 경로로 내비게이션하더라도 웹 서버에 요청하지 않습니다. 이미 다운로드한 .js 파일의 컴포넌트를 이용해 브라우저에서 렌더링합니다.

브라우저는 첫 화면을 로딩하기 위해 첫 화면뿐만 아니라 모든 화면을 위한 .js 파일을 로딩합니다. 이때 지연 시간이 발생해서 사용자는 첫 화면을 보기까지 기다리는 시간이 길어질 수 있습니다. 이때 사용하는 기법이 레이지 로딩 기법입니다.

 

레이지 로딩은 리액트 애플리케이션의 수많은 화면과 컴포넌트를 적절히 구분하여 화면, 컴포넌트 그룹 단위로 여러 개의 청크(chunk)라 부르는 .js 파일로 빌드하고 특정 컴포넌트가 필요한 시점에 서버에 요청해서 청크 파일을 응답받아 렌더링하는 방법입니다. 

 

즉, 레이지 로딩 기법의 핵심은 특정 화면이 필요할 때 관련된 컴포넌트를 포함하고 있는 .js 파일을 웹 서버에 요청하여 받아오는 것입니다.

 

이 방법을 사용하면 애플리케이션이 수많은 컴포넌트를 포함하더라도 첫 화면을 요청할 때는 작은 크기의 청크 파일을 요청하고 응답받으므로 사용자에게 첫 화면을 더 신속하게 보여 줄 수 있습니다.

 

👉 Suspense 컴포넌트

청크 파일을 필요할 때 로딩하다 보면 실행 중에 약간의 지연 시간이 발생할 수 있습니다. 지연 시간이 길어진다면 사용자에게 로딩 중임을 나타내는 화면을 보여주는 것이 좋습니다. 이런 화면을 fallback UI라고 부르며 이 기능을 손쉽게 구현할 수 있도록 도와주는 컴포넌트가 Suspense 컴포넌트입니다.

🧑🏻‍💻 Hook 라이프사이클

🧑🏻‍💻 클래스형 컴포넌트를 사용해 보셨나요?

아니요 ㅎ 

🧑🏻‍💻 클래스형 컴포넌트와 함수형 컴포넌트의 차이에 대해 설명해 주세요.

클래스형 컴포넌트는 LifeCycle API를 제공하나, 함수형 컴포넌트는 기본적으로는 제공되지 않습니다. (Hook을 사용하면 사용할 수 있습니다.)

반면, 함수형 컴포넌트는 메모리 자원을 클래스형 컴포넌트보다 덜 사용하며, 빌드한 결과물의 크기 역시 클래스형 컴포넌트보다 적습니다.

React 공식문서에서 클래스형 컴포넌트로 선언하는 방법을 아예 Legacy API로 분류해 놓을 정도로 함수형 컴포넌트는 강력합니다. 

⭐️ 🧑🏻‍💻 라이프사이클에 대해 설명해 주세요.

모든 리액트 컴포넌트에는 라이프 사이클이 있으며, 컴포넌트는 마운트 -> 업데이트 -> 언마운트의 라이프사이클을 갖습니다.

마운트는 컴포넌트가 생성되는 시점을 의미하며, constructor -> getDerivedStateFromProps -> render -> componentDidMount의 순서로 호출됩니다.

업데이트는 컴포넌트가 업데이트되는 시점을 의미하며, getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate 순서로 호출됩니다.

언마운트는 컴포넌트가 화면에서 사라지는 시점을 의미하며, 컴포넌트가 화면에서 사라지기 직전에 componentWillUnmount 가 호출됩니다.

📌 라이프 사이클 메서드에 대해 설명해 주세요.

getDerivedStateFromProps: props로 받아온 것을 state로 넣어주고 싶을 때 사용합니다.

componentDidMount: 컴포넌트의 첫 번째 렌더링이 마치고 나면 호출되는 메서드로, 이 메서드가 호출되는 시점에는 우리가 만든 컴포넌트가 화면에 나타난 상태입니다.

shouldComponentUpdate: 컴포넌트가 리렌더링 할지 말지를 결정하는 메서드로 주로 최적화를 할 때 사용하는 메서드입니다.

getSnapshotBeforeUpdate: 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면, 그다음 발생하게 되는 componentDidUpdate에서 받아와 사용할 수 있습니다.

componentDidUpdate: 리렌더링을 마치고, 화면에 우리가 원하는 변화가 모두 반영되고 난 뒤 호출되는 메서드입니다. 3번째 파라미터로 getSnapshotBeforeUpdate에서 반환한 값을 조회할 수 있습니다.

componentWillUnmount: 컴포넌트가 화면에서 사라지기 직전에 호출되는 메서드입니다.

📌 클래스 컴포넌트와 함수 컴포넌트를 비교하면서  설명해 주세요.

👉 클래스 컴포넌트

 

  • 컴포넌트는 크게 마운트, 업데이트, 언마운트 주기를 가집니다.
  • 마운트 단계는 컴포넌트가 처음 실행될 때를 의미합니다. 컴포넌트의 상태를 초기화하고, 컴포넌트가 돔에 설정되어 브라우저에 보이는 구간입니다.
  • 다음으로 업데이트는 props나 state가 변경되었을 때, 부모 컴포넌트가 다시 렌더링 될 때, forceUpdate 메서드를 통해 강제로 렌더링을 트리거할 때나, componentDidUpdate 메서드를 통해 업데이트 이후 컴포넌트가 추가로 업데이트됩니다.
  • 마지막으로 언마운트 과정을 통해 컴포넌트를 DOM에서 제거합니다.

👉 함수 컴포넌트

 

  • 함수 컴포넌트는 호출되었을 때 함수 내부가 먼저 실행됩니다.
  • 이후 함수의 반환값으로 반환하는 HTML과 컴포넌트들을 화면에 렌더링 합니다.
  • 이후 생명주기는 useEffect 훅을 통해 관리할 수 있습니다.
  • 렌더링 되면 useEffect가 마운팅 되면서 실행되고, 조건에 따라 useEffect를 통해 업데이트합니다.
  • 컴포넌트가 언마운트 될 때에는, 컴포넌트가 제거되기 전에 useEffect의 clean up 함수를 호출하게 됩니다.
  • 이후 DOM에서 컴포넌트를 제거합니다.

📌 componentDidMount, componentDidUpdate 등 클래스 컴포넌트에서 사용되던 생명주기 메서드를 함수 컴포넌트에서는 어떻게 구현하나요?

  • useEffect 훅을 통해 구현할 수 있습니다.
  • useEffect는 사용에 따라 컴포넌트가 마운트 되었을 때, 컴포넌트의 특정 상태가 업데이트될 때, 컴포넌트가 제거될 때 모두 처리할 수 있습니다.
  • 왜냐하면 useEffect 훅은 의존성이 변경될 때마다 등록된 effect 함수를 실행하는 훅입니다.
  • 의존성에 변경을 감지할 상태나 props를 등록하면 componentDidUpdate, getDerivedStateFromProps처럼 사용할 수 있습니다.
  • 그리고 의존성에 빈 배열을 등록하면 처음 마운트 되었을 때 실행되는 componentDidMount처럼 사용할 수 있습니다.
  • 마지막으로 effect 함수의 반환값으로 콜백 함수를 등록할 수 있습니다. 이 콜백 함수는 컴포넌트가 제거될 때 실행되는 함수로, clean up 함수라고 합니다. 이 clean up 함수를 통해 componentWillUnmount처럼 사용할 수 있습니다.

📌 클래스형 컴포넌트의 forceUpdate 알고 있나요?

  • forceUpdate는 리액트에서 공식적으로 제공하는 API로, 해당 컴포넌트를 상태의 변화가 없더라도 재렌더링 시키는 메서드입니다.

👉 함수 컴포넌트에서는 사용할 수 없나요?

  • 함수 컴포넌트에서는 공식적으로 지원하고 있지는 않지만, 약간의 트릭을 이용할 수 있습니다.
  • 상태가 변경되면 해당 컴포넌트가 다시 렌더링 되므로, useState를 통해 상태를 선언하고, forceUpdate라는 함수를 선언해서 상태를 변경하면, 호출 시 다시 렌더링 되게 됩니다.
  • 저는 필요하다면 커스텀 훅으로 정의해서 사용하고 있습니다.

🧑🏻‍💻 React.Fragment에 대해 설명해 주세요.

리액트 컴포넌트는 1개의 엘리먼트를 리턴해야 하며, 여러 개의 엘리먼트를 리턴할 경우, 에러가 발생합니다.

이러한 상황처럼, 여러 개의 엘리먼트를 단일 엘리먼트가 들어갈 수 있는 위치에 배치하고자 할 때, 사용할 수 있는 문법으로, Fragment는 엘리먼트들을 다른 컨테이너로 감싸지 않기 때문에 레이아웃이나 스타일에 영향을 주지 않습니다.

🧑🏻‍💻 Portal에 대해 설명해 주세요.

Portal을 사용하면, 컴포넌트가 일부 자식 컴포넌트를 DOM의 다른 위치로 렌더링 할 수 있습니다.

Portal은 오로지 DOM 노드의 물리적 배치만 변경하며, 다른 모든 면에서는 이를 렌더링 하는 React 컴포넌트의 자식 노드 역할을 합니다.

예를 들어, 자식은 부모 컴포넌트의 콘텍스트에 접근할 수 있으며, 이벤트는 자식에서 부모로 버블링 됩니다.

🧑🏻‍💻에러 바운더리에 대해 설명해 주세요.

에러 바운더리는 하위 컴포넌트에서 발생하는 에러를 잡아서 선언적으로 처리할 수 있는 컴포넌트입니다.

이는 try-catch와 비슷한 형식으로, getDerivedStateFromError를 사용하면 폴백 UI를 렌더링 할 수 있고, componentDidCatch를 사용하면 에러 정보를 기록할 수 있습니다.

🧑🏻‍💻 리액트의 렌더링 성능 향상을 위해 어떻게 해야 하나요?

state와 props의 변경을 최소화합니다.

React.Memo, useMemo, useCallback 등을 사용합니다.

🧑🏻‍💻 React 18 버전 업데이트 내용에 대해 말씀해 주세요.

  1. Automatic batching
  2. React 18부터 상태 업데이트를 하나로 통합해서 배치처리한 뒤, 리렌더링을 진행합니다.
  3. hydration error리액트는 서버 마크업을 일치시키기 위해 클라이언트 노드에 삽입이나 삭제를 함으로써 개별 노드를 수정해주지 않고, 트리에서 가장 가까운 <Suspense> 바운더리까지 클라이언트 렌더링으로 돌아갑니다.
  4. 텍스트 내용 누락, 불일치 등을 이제 경고가 아닌 오류로 처리합니다.
  5. Suspense
  6. 트리에 완전히 추가되기 전에 컴포넌트가 suspend 된 경우 리액트는 새 트리를 완전히 버리고, 비동기 작업이 완료될 때까지 기다린 다음, 다시 처음부터 렌더링을 시도합니다.
  7. 새로운 js 환경
  8. 이제 모던 브라우저 기능인 Promise, Symbol, Object.assign에 의존합니다. 따라서 인터넷 익스플로러 등 오래된 브라우저를 지원해야 하는 경우 글로벌 폴리필을 추가하는 것을 고려해야 합니다.

🧑🏻‍💻 Redux

🧑🏻‍💻 Redux에 대해 설명해 주세요.

Redux는 자바스크립트 상태관리 라이브러리입니다.

📌 Redux를 사용하는 이유에 대해 설명해 주세요.

Redux는 모든 상태의 업데이트를 액션으로 정의하고, 액션 정보에 기반하여 리듀서에서 상태를 업데이트하기 때문에, 상태를 더욱 쉽게 예측가능하게 하여 유지보수 측면에 긍정적인 효과가 있습니다.

또한 Redux-saga, Redux-thunk와 같은 미들웨어를 통해 비동기작업에 대해 더 디테일하고 편한 컨트롤을 할 수 있게 됩니다.

📌 Redux의 장단점에 대해 설명해 주세요.

👉 장점

 

리덕스를 잘 쓸 수 있게 되는 것의 가장 큰 장점은 상태관리가 쉽다는 것입니다.

프로젝트의 크기가 커지면, 상태가 굉장히 많고 다양해집니다.

그러나 Redux를 사용하면, 웹사이트의 상태를 어디서 관리해야 할지 고민하지 않아도 됩니다.

그리고, 어떤 액션을 통해 어떤 데이터가 변경되었는지 쉽게 알 수 있기 때문에, 상태를 좀 더 예측하기 쉽습니다.

 

👉 단점

 

가장 큰 단점은 어렵습니다. 리덕스의 기본 개념 자체를 이해하기 어렵습니다.

그리고, 리덕스를 유용하게 사용하려면 많은 패키지를 추가해야 합니다. 또한 리덕스 스토어 환경설정도 복잡하며, 보일러플레이트 코드를 너무 많이 요구합니다.

이는 Redux-toolkit을 사용하면, 어느 정도 해결되는 문제입니다.

🧑🏻‍💻 Flux 패턴에 대해 설명해 주세요.

Flux 패턴은 사용자 입력을 기반으로 Action을 만들고, Action을 Dispatcher에 전달하여, Store의 데이터를 변경한 뒤, View에 반영하는 단방향의 흐름으로 애플리케이션을 만드는 아키텍처입니다.

🧑🏻‍💻 Context API와 Redux를 비교해 주세요.

Context API는 상태관리 도구가 아닙니다.

Context API는 props drilling을 해결하기 위해 나온 도구이고, Redux는 상태를 좀 더 쉽게 관리하고자 나온 도구입니다.

즉, Context API와 Redux를 비교하는 것보다는 Context API와 useState, useReducer를 이용한 상태관리와 Redux를 비교하는 것이 옳습니다.

 

이 둘의 차이점은 다음과 같습니다.

Redux는 컴포넌트에 상태값을 종속시키지 않고 바깥에서 관리할 수 있습니다.

또한 Redux는 리렌더링을 최적화합니다. useReducer와 달리, Redux를 사용하면 특정 값이 변경될 때에만 re-render 할 수 있습니다. 이를 통해 성능 향상을 꾀할 수 있습니다.

그리고, useReducer는 미들웨어가 없습니다.

🧑🏻‍💻 Redux의 3대 원칙에 대해 설명해 주세요.

  • single source of truth: 앱 전체에서 상태 관리 저장소는 단일 저장소로 존재한다.
  • state is read-only: 상태를 변경하는 방법은 action을 reducer에 전파하는 것이 유일하다.
  • changes are made with pure functions: 상태 변경 로직을 정의하는 리듀서들은 순수함수로 작성되어야 한다.

🧑🏻‍💻 Redux-saga createAsyncThunk 공통점과 차이점에 대해 설명해 주세요.

redux-saga와 createAsyncThunk은 둘 다 Redux를 사용하여 비동기 작업을 처리하는 데 도움을 주는 라이브러리 또는 기능입니다. 그러나 각각의 라이브러리가 동작하는 방식과 목적에는 차이가 있습니다.

📌 redux-saga

  • 목적: redux-saga는 Redux 애플리케이션에서 사이드 이펙트 및 비동기 작업을 관리하기 위한 미들웨어입니다. 주로 네트워크 요청, 타이머, 브라우저 이벤트 및 기타 비동기 작업을 처리하는 데 사용됩니다.
  • 작동 방식: redux-saga는 제너레이터 함수(generator function)를 사용하여 비동기 작업을 수행합니다. Redux 액션을 모니터링하고 특정 액션을 감지하면 해당 액션과 관련된 비동기 작업을 시작합니다. 예를 들어, Redux 액션을 디스패치하여 네트워크 요청을 시작하고, 요청이 완료되면 다시 Redux 스토어에 액션을 디스패치하여 상태를 업데이트합니다.
  • 구성: redux-saga는 Redux 스토어에 미들웨어로 추가됩니다. redux-saga 미들웨어는 액션을 모니터링하고 처리할 제너레이터 함수를 실행합니다.

📌 createAsyncThunk

  • 목적: createAsyncThunk는 Redux Toolkit의 일부로 포함된 유틸리티 함수로, Redux를 사용하여 비동기 작업을 처리하는 데 특히 최적화되어 있습니다. 주로 네트워크 요청과 관련된 작업을 간소화하고, 비동기 작업의 상태를 관리하기 위해 사용됩니다.
  • 작동 방식: createAsyncThunk는 주로 비동기 작업의 세 가지 상태(진행 중, 성공, 실패)를 처리하고 관리하는 데 사용됩니다. 사용자는 비동기 작업을 시작하는 함수와 해당 작업이 완료되면 상태를 업데이트하는 리듀서를 정의합니다. 이렇게 정의한 createAsyncThunk 액션 생성자는 비동기 작업의 결과 및 상태를 자동으로 처리하며, 이로써 코드를 간소화하고 일관성을 유지할 수 있습니다.
  • 구성: createAsyncThunk는 Redux Toolkit의 createSlice 또는 createAsyncThunk와 함께 사용됩니다. 액션 생성자로 사용되며, 비동기 작업을 시작하는 함수를 받아서 세 가지 상태(진행 중, 성공, 실패)에 따른 액션을 자동으로 생성합니다.

📌 공통점

  • 둘 다 Redux를 사용하여 비동기 작업을 처리하고, Redux 액션을 통해 상태를 업데이트하는 데 사용됩니다.
  • 비동기 작업의 성공 및 실패를 처리하며, 비동기 작업의 진행 상태를 추적하는 데 유용합니다.
  • Redux Toolkit과 함께 사용될 때 코드를 더 간소화하고, 일관성을 유지하는 데 도움이 됩니다.

📌 차이점

  • redux-saga는 미들웨어로 추가되며, 제너레이터 함수를 사용하여 복잡한 비동기 로직을 처리합니다. 반면에 createAsyncThunk은 Redux Toolkit의 유틸리티 함수로, 간단한 사용 사례에 적합하며 코드를 더 간소화합니다.
  • redux-saga는 더 많은 컨트롤과 유연성을 제공하지만, 구현과 관리가 더 복잡할 수 있습니다. createAsyncThunk은 간단한 사용 사례에서 간소화된 해결책을 제공합니다
Comments