본문 바로가기
우아한 테크코스

생각해보기🤔 - 페이먼츠

by 해-온 2023. 6. 20.

 

💳 컴포넌트를 어느 정도까지 분리해야 할까요? 

아래 기준에 따라 분리하는 것이 좋다.

 

1. 단일 책임 원칙

각 컴포넌트는 최대한 작은 기능적 단위를 가지도록 설계하는 것이 좋다.

이렇게 하면 재사용성이 높아지고, 각 컴포넌트의 역할을 명확히 할 수 있다.

 

2. 재사용성

공통적으로 사용되는 UI 요소나 로직이 있는 경우, 컴포넌트로 분리하면 여러 곳에서 재사용할 수 있다.

이렇게 하면 코드 중복을 줄이고 관리하기 편해진다.

 

3. 복잡성

컴포넌트 내부 로직이나 상태 관리가 복잡해진다면, 여러 하위 컴포넌트로 분리하여 복잡성을 줄일 수 있다.

 

 

 

💳 어떤 경우 컴포넌트를 그룹화해서 하나의 컴포넌트처럼 보이게 하는 것이 좋을까요?

1. 컴포넌트 간 의존성이 강한 경우

여러 컴포넌트들이 의존적이라면, 이를 그룹화하여 하나의 컴포넌트처럼 관리하는 것이 더 효율적일 수 있다.

 

2. 비슷한 기능을 가진 컴포넌트의 경우

동일한 목적을 갖는 컴포넌트라면 그룹화해서 관리할 수 있다.

이 경우 해당 그룹 안에서만 사용되는 공통 로직을 더 쉽게 관리할 수 있다.

 

 

💳 리액트에서 속성을 불변 객체로 다루는 이유는 무엇일까요? 

1. 상태 관리의 간소화

불변 객체를 사용하면 언제, 어떻게 상태가 변경되는지 명확하게 추적할 수 있다.

 

2. 성능 최적화

변경 감지가 쉽기 때문에 언제 컴포넌트를 다시 렌더링 할지 결정할 때, 얕은 비교만으로도 데이터 변경 여부를 판단할 수 있다.

이를 통해 불필요한 렌더링을 방지할 수 있다.

 

 

💳 불변 객체로 다루지 않았을 때 발생할 수 있는 이슈는 무엇일까요?

1. 상태 관리의 어려움

변하기 쉬운 객체를 사용하면, 예기치 않게 상태가 변경될 수 있다.

 

2. 의도하지 않은 버그 발생

상태를 변화시키는 부분에서 의도하지 않은 사이드 이펙트가 발생할 수 있다.

 

3. 성능 저하

불변 객체를 사용하지 않으면 변화 감지를 위해 깊은 비교를 수행해야 할 수 있다.

이로 인해 성능이 저하되고, 불필요한 렌더링이 발생할 가능성이 높아진다.

 

 

💳 하위 컴포넌트에서 상위 컴포넌트의 상태인 Props 를 직접 수정할 수 없는 이유는 무엇일까요?

1. 단방향 데이터 흐름

React는 단방향 데이터 흐름을 가지고 있다.

즉, 상위 컴포넌트에서 하위 컴포넌트로 데이터가 전달되는 방식이다.

이 구조를 통해 애플리케이션의 각 부분의 상호작용을 명확하게 파악할 수 있고, 데이터의 흐름이 예측 가능해진다.

 

2. 불변성

하위 컴포넌트에서 Props를 직접 수정하게 되면 상위 컴포넌트의 상태가 예기치 않게 변경될 수 있다.

따라서 관리가 어려워지고, 성능 최적화 측면에서도 이슈가 발생한다.

 

3. 캡슐화

하위 컴포넌트가 상위 컴포넌트의 상태를 직접 수정하게 되면, 캡슐화 원칙이 깨져 결합도가 높아지고, 코드 유지보수가 어려워진다.

 

 

💳 Prop Drilling을 해결할 수 있는 방법은 Context API 혹은 Redux 같은 State Container와 Store Management뿐일까요?

1. 컴포넌트 합성

상위 컴포넌트에 로직과 상태를 유지하고, 하위 컴포넌트는 렌더링에만 집중하는 방식으로 구조를 변경한다.

이렇게 하면 해당 상태와 로직을 사용하는 컴포넌트가 가까워지므로 props drilling을 줄일 수 있다.

 

2. Higher-Order Components(HOC)

HOC는 다른 컴포넌트를 감싸는 컴포넌트이다.

필요한 상태와 로직을 추가하는 역할을 하고, 감싸진 컴포넌트는 단순화된다.

 

3. Render Props

컴포넌트가 상태 및 로직을 전달할 수 있는 함수를 props로 받아 렌더링에 활용한다.

이렇게 하면 중간 컴포넌트를 거치지 않고 필요한 컴포넌트에 직접 상태와 로직을 제공할 수 있다.

 

 

💳 스토리북을 이용하면 특히 어떤 컴포넌트나 페이지를 테스트할 때 이점이 있을까요?

  • 상태가 다양한 컴포넌트
  • 재사용 가능한 컴포넌트
  • 상호 작용이 많은 컴포넌트
  • 복잡한 계층 구조를 가진 페이지

 

 

💳 class 컴포넌트는 더 이상 필요가 없을까요?

1. Error Boundary

class 컴포넌트는 생명주기 메서드인 componentDidCatch 또는 static getDerivedStateFromError를 사용하여 자식 컴포넌트에서 발생하는 오류를 처리할 수 있는 Error Boundary를 제공한다.

 

2. 기존 프로젝트 유지 및 보수

예전 class 컴포넌트를 사용하는 프로젝트가 있고, 이를 유지해야 한다면 class 컴포넌트를 사용해야 한다.

 

 

💳 class 기반으로 구현할 때 컴포넌트마다 반복되는 로직을 재사용할 수 있는 방법은 무엇이 있을까요? (꼭 리액트에서만이 아니라 좀 더 일반적인 방법들에 대해서도 고민해 볼까요?)

1. 상속

클래스 상속을 통해 기본 클래스에서 공통 로직을 정의하고 상속받은 클래스에서 해당 로직을 재사용할 수 있다.

 

2. 조합

컴포넌트를 작은 단위로 나누고 조합하는 방식을 통해 캡슐화하고 재사용할 수 있다.

React에서는 Higher-Order Components(HOC)를 사용해 조합을 구현할 수 있다.

 

3. 믹스인(Mixin)

특정 로직을 재사용하기 위해 클래스에 함께 섞이는 클래스의 일부이다.

믹스인을 통해 여러 클래스에서 공통 로직을 공유하고 재사용할 수 있다.

 

4. 유틸리티 함수 및 클래스

외부에 로직을 작성한 함수나 클래스로 여러 컴포넌트에서 공통적인 로직을 사용할 수 있다.

 

 

💳 '함수'가 어떻게 '상태'를 가질 수 있는 걸까요?

클로저 덕분에 함수는 상태를 가질 수 있다.

클로저는 함수와 함수가 선언된 렉시컬 환경이 결합된 특수한 객체로, 해당 함수가 생성된 환경의 변수 및 상태에 대한 참조를 유지한다.

클로저를 이용하면 함수가 상태를 만들고 관리할 수 있다.

 

function createCounter() {
  let count = 0;

  return function () {
    count += 1;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
 
위 예시에서 createCounter 함수는 내부 함수를 반환한다.
내부 함수는 count 변수를 참조하고 있는데, 이 변수에 접근할 수 있는 클로저가 생성된다.
createCounter 함수가 실행 완료되어 외부 스코프에 없어진 이후에도 내부 함수에서 클로저를 통해 count 변수에 접근할 수 있다.
클로저를 활용해 함수는 상태를 유지하고 관리할 수 있는 것이다.
 

 

💳 useEffect에서는 보통 어떤 작업들을 하게 될까요?

useEffect는 React에서 side effect를 추가할 때 사용하는 Hook이다.

여기서 side effect란 컴포넌트의 라이클 사이클 내에서 발생하는 외부 상태와 관련된 작업을 말한다.

주로 컴포넌트가 마운트 되거나 특정 상태 또는 속성이 변경될 때 수행한다.

  • API 호출
  • 타이머 관리
  • 브라우저 API 상호작용

 

 

💳 Hooks를 사용할 때 반드시 지켜야 하는 사용 규칙은 무엇인가요?

1. 최상위 수준에서 Hooks 호출

Hook은 반복문, 조건문, 중첩된 함수 내에서 호출되면 안 된다.

 

2. React 함수 컴포넌트 내에서만 Hooks 호출

Hooks는 오직 React 함수 컴포넌트 내에서 호출해야 한다.

그러나 custom hook을 생성하는 경우 일반 JavaScript 함수에서 호출할 수 있다.

 

 

💳 제어 컴포넌트를 지향하라는 의견이 많은 이유는 무엇일까요?

제어 컴포넌트란, 입출력 데이터와 상태를 React 컴포넌트 상태로 관리하는 요소이다.

사용자에 의한 입력값이나 변경 사항이 발생할 때, 상태를 업데이트하고 재렌더링하는 방식으로 동작한다.

제어 컴포넌트를 지향해야 하는 이유는 아래와 같다.

 

1. 일관성 있는 데이터 처리

제어 컴포넌트의 경우 form의 데이터 상태가 React 컴포넌트의 상태로 관리된다.

이로 인해 데이터의 흐름이 일관되게 유지되며, 신뢰성과 예측 가능성이 향상된다.

반면, 비제어 컴포넌트의 경우 DOM에 의해 직접적으로 관리되어, 프로그램에서 상태에 대한 완전한 통제가 어렵다.

 

2. 양방향 데이터 바인딩 지원

제어 컴포넌트를 사용하면 양방향 데이터 바인딩을 쉽게 구현할 수 있다.

이를 통해 사용자 입력을 실시간으로 반영하고 처리할 수 있고, 즉시 데이터의 유효성 검사와 같은 작업도 가능해진다.

 

3. 조건부 입력 제어

React 상태를 기반으로 입력 필드의 활성화 또는 비활성화, 입력 가능한 최대 길이와 같은 조건을 쉽게 구현할 수 있다.

 

4. 간결한 유효성 검사

제어 컴포넌트를 통해 입력값을 얻거나 유효성을 검사하는데 필요한 코드를 줄일 수 있다.

 

 

💳 useImperativeHandle 이 언급되는 이유가 무엇일까요?

useImperativeHandle은 아래 경우에 사용한다.

 

1. 자식 컴포넌트의 내부 메서드를 부모 컴포넌트에서 호출할 필요가 있을 때

2. 자식 컴포넌트에서 특정 값이나 메서드를 숨기고, 선택적으로 노출하고 싶을 때

 

import React, { useRef, useImperativeHandle, forwardRef } from "react";

const CustomInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));

  return (
    <div>
      <input type="text" ref={inputRef} />
    </div>
  );
});

function App() {
  const customInputRef = useRef();
  const handleClick = () => {
    customInputRef.current.focus();
  };

  return (
    <div>
      <CustomInput ref={customInputRef} />
      <button onClick={handleClick}>Focus</button>
    </div>
  );
}

 

 

💳 비제어 컴포넌트는 사용할 일이 없는 건가요?

상황에 따라 비제어 컴포넌트가 유용하게 사용될 수 있다.

비제어 컴포넌트가 적합한 경우는 아래와 같다.

 

1. 파일 입력과 같은 특정 상황

비제어 컴포넌트와 ref를 사용하여 파일을 더 쉽게 액세스 하고 처리할 수 있다.

 

2. 외부 라이브러리 사용

일부 외부 라이브러리는 DOM 요소에 직접 액세스 하거나 조작하는 방식으로 작동한다.

이런 경우 비제어 컴포넌트가 외부 라이브러리와의 연동이 더 원활할 수 있다.

 

+ 리액트 공식 문서

비제어 컴포넌트는 DOM에 신뢰 가능한 출처를 유지하므로 이를 사용할 때 React와 non-React 코드를 통합하는 것이 쉬울 수 있습니다.

빠르고 간편하게 적은 코드를 작성할 수 있지만, 그 외에는 일반적으로 제어된 컴포넌트를 사용해야 합니다.

 

 

💳 횡단 관심사는 무엇일까요?

횡단 관심사란 여러 컴포넌트 또는 함수에서 공통적으로 사용되는 기능이나 로직을 말한다.

횡단 관심사를 처리하여 추상화하고 모듈화 하면, 코드의 재사용성을 높이고 중복을 줄일 수 있다.

 

아래와 같은 방법으로 횡단 관심사를 관리할 수 있다.

 

1. Higher-Order Components(HOC)

HOC는 다른 컴포넌트를 감싸는 컴포넌트이다.

HOC를 사용하여 공통 기능을 여러 컴포넌트에서 재사용할 수 있게 모듈화 한다.

 

2. custom hooks

custom hooks을 이용해 횡단 관심사를 분리할 수 있다.

custom hooks을 사용할 경우, 동일한 로직을 여러 컴포넌트에서 재사용할 수 있다.

 

3. Context API

Context API를 사용하여 애플리케이션 전체에서 공유하는 데이터와 로직을 관리할 수 있다.

 

 

💳 Context API를 쓰면 Redux를 사용할 필요가 없다는 말이 있던데 사실인가요?

Context API와 Redux는 상태 관리를 위한 라이브러리이다.

그러나 각각의 특징과 적용 시나리오가 다르다.

Context API로 일부 Redux의 기능을 대체할 수 있고, 작고 간단한 애플리케이션에서는 Redux를 사용하지 않아도 충분하다.

그러나 모든 것을 대체하는 것은 아니다.

 

Context API와 Redux의 차이는 아래와 같다.

 

1. 사용 사례

Context API는 React 내에서 상태 관리를 처리하는 방법으로 사용된다.

주로 전역 상태에 영향을 주지 않는, 소규모 상태 관리에 적합하다.

반면, Redux는 큰 규모의 애플리케이션에서 전역 상태 관리를 위해 설계되었으며, 복잡한 상태 로직을 처리할 수 있다.

 

2. 미들웨어

Redux는 미들웨어를 사용하여 비동기 액션을 다루고, 사이드 이펙트를 관리한다.

반면, Context API는 미들웨어를 지원하지 않고, 별도의 커스텀 로직으로 구현해야 한다.

 

3. 복잡성

Context API는 React 라이브러리에 내장되어 있어 사용이 쉽고 직관적이다.

그러나 상태 관리가 복잡해질수록 Context API만으로 관리하기 어려워진다.

반면, Redux는 일관된 패턴과 구조를 제공하여 복잡한 상태 관리를 용이하게 한다.

 

 

💳 레벨 1에서 전역 변수를 지양해야 한다는 피드백이 많았는데 React에서는 전역 상태를 사용해도 되는 될까요?

전역 상태 사용은 지양하는 것이 좋다.

의도치 않은 사이드 이펙트를 유발할 수 있기 때문이다.

그러나 많은 작업이 필요한 현대 웹 애플리케이션의 경우, 전역 상태를 사용하지 않는 것은 불가능에 가깝다.

React에서는 상태 관리를 위한 도구를 제공하기 때문에 전역 상태를 사용해도 괜찮다.

 

  • Context API
  • 상태 관리 라이브러리(Redux, MobX 등)

상태 관리를 위한 도구를 사용한다면 안정적인 상태 관리가 가능하다.

 

 

댓글