React 기술면접 1주차(0)

강연주·2024년 12월 11일

🙋‍♀️ 기술면접

목록 보기
80/112
  • 상태관리는 왜 할까요? 그리고 평소 상태관리는 어떻게 하시나요?

    • 답변)
      • 의도: 상태 관리의 목적과 평소 상태 관리 패턴 파악 및 전역 상태 관리에 대해서도 추가 답변(사용하는 라이브러리 등)을 기대하는 질문.
      • 모범 답안: 상태관리의 필요성은 리액트의 MVVM 패턴과 관련지어 설명할 수 있습니다. Model-View-ViewModel 패턴에 따라 상태는 Model에, 화면 UI는 View에 역할을 위임함으로써 서로의 독립성을 확보할 수 있습니다. 이에 따라 개발자는 각각을 다른 관점에서 파악함으로써 각자의 기능에 집중해 개발할 수 있는 환경을 구축할 수 있습니다.
        저의 경우에는 이를 실현하기 위한 방법의 하나로 커스텀 훅을 사용하여 Model 부분의 재사용성과 독립성을 향상시켰습니다. 또한 하나의 상태를 여러 컴포넌트가 바라볼 때 나타나는 props-drilling과 같은 문제를 해결하기 위해 Redux 등의 전역 상태 관리 도구를 사용한 경험이 있습니다.
  • Redux 말고 다른 전역 상태 관리 라이브러리를 사용해 본 적이 있으신가요?

    • 답변)
      • 의도: 다양한 상태관리 라이브러리에 대한 지식과 경험 소개 및 해당 라이브러리를 선택하게 된 구체적인 이유를 설명할 수 있는지 확인하는 질문
      • 모범 답안: 네 저는 Redux 외에 Zustand라는 전역 상태 관리 라이브러리를 사용한 경험이 있습니다. 기존 리덕스와는 다르게 Zustand는 보일러 플레이트가 단순하여 더욱 빠른 환경 설정이 가능하다는 장점이 있습니다. 예를 들어 리덕스에서 작성해야 했던 액션, 리듀서, 디스패치, 미들웨어 등 대신에, Zustand에서는 create 메서드를 통해 atomic 한 객체를 생성하는 것으로 앞선 과정을 단축할 수 있습니다.
        또한 Redux에서 채택했던 Flux 아키텍처를 그대로 가져와 사용하였기에 이 또한 저에게 아주 큰 매력으로 다가왔습니다. 왜냐하면 Redux Tool Kit을 포함해 리덕스를 사용할 때의 가장 큰 장점으로 체감할 수 있었던 것은 바로 개발자 도구(devtool)의 유용함 덕분이었습니다. Zustand는 리덕스의 Flux 아키텍처를 그대로 채택하였기에 기존 리덕스의 개발자 도구를 이어서 사용할 수 있게 되었고, 이는 곧 저에게 있어서 더 이상 리덕스를 사용해야 할 이유를 모두 잃은 것과 다름 없었습니다.

1. 리액트에서 가상 돔을 사용하는 이유에 대해 설명해주세요.

  • 답변)
    • 의도: 리액트의 기본 원리와 가상 돔의 핵심을 이해하고 있는지, 그리고 가능하면 useState와의 관계성도 설명할 수 있는지 확인하는 질문
    • 모범 답안: 실제 돔은 HTML의 요소를 트리로서 가지고 있는 객체 기반의 모델이며, 브라우저는 실제 돔을 기반으로 화면을 렌더링합니다. 반면에 가상 돔은 실제 돔을 경량화한 복사본으로, 리액트의 최적화를 위해 사용됩니다. 실제 돔을 직접 조작하는 것은 성능 비용이 큰 작업이기 때문에, 리액트는 상태가 업데이트 될 때마다 우선 빠르고 가벼운 가상 돔을 업데이트하고, 결과를 실제 돔과 비교합니다. 이후 변경된 부분만 실제 돔에 반영함으로써 불필요한 리소스 사용을 최소화하고 성능을 향상시킵니다.
      이 과정을 가장 쉽게 살펴볼 수 있는 리액트의 메서드는 바로 useState입니다. 이 상태관리 훅을 통해 상태를 업데이트하면 상태 값이 곧바로 반영되지 않습니다. 왜냐면 상태 업데이트는 그저 변수에 데이터를 담아내는 것이 아니라, 앞서 설명했던 가상 돔과 실제 돔의 비교 과정이 실행되기 때문입니다. 상태 값이 자기 자신을 참조하여 상태를 업데이트할 때 생기는 오류는 대부분 이 때문입니다. 이러한 문제를 해결하기 위해 useState 훅에 값이 아닌 콜백 함수의 참조를 인자로 전달할 수 있습니다.

2. useEffect의 실행 순서를 컴포넌트 라이프 사이클에 관련지어 설명해주세요.

  • 답변)
    • 의도: 컴포넌트 라이프 사이클과 useEffect의 이해도를 가지고 있는지, 각 라이프 사이클에서 어떤 작업을 처리해야 하는지 설명할 수 있는지 확인하는 질문.
    • 모범 답안: 컴포넌트 라이프 사이클을 간단하게 설명하자면 create-mount-update-unmount로 함축할 수 있습니다. create는 컴포넌트가 말 그대로 생성된 것입니다. 중요한 것은 이 다음부터입니다.
      mount는 컴포넌트가 생성된 후에 실제 돔에 렌더링 되는 순간을 뜻합니다. mount의 한글 뜻인 장착에서 유추할 수 있습니다. 그리고 이 순간이 바로 useEffect 내부의 코드가 실행되는 시기입니다. 컴포넌트가 화면에 렌더링 되었기 때문에 이때 HTML 태그를 가져와 이벤트를 등록하거나, 데이터를 fetching 해오는 등의 작업을 처리하게 됩니다.
      update는 컴포넌트에 변화가 생겼을 때를 뜻합니다. useEffect의 의존성 배열을 사용하면 특정 값이 변경될 때마다 내부의 작업을 실행할 수 있도록 조절할 수 있습니다.
      unmount는 컴포넌트가 실제 돔에서 사라지는 순간을 뜻합니다. mount의 반대라고 생각하시면 됩니다. useEffect에서는 내부의 return 값에 함수의 참조를 넘겨주어 unmount시 특정 작업이 실행되게 하는데, 이를 클린업 함수라고 합니다. 주로 mount시에 등록했던 이벤트를 제거하는 등 메모리 누수를 막기 위한 작업을 실행합니다.

3. 리액트의 리스트 렌더링에서 key는 왜 넣어줄까요? 그리고 key 값이 유니크해야 하는 이유는 뭘까요?

  • 답변)
    • 의도: 자칫 지나치기 쉬운 리액트의 기본 개념에 대해 확인하는 질문
    • 모범 답안: 네, 리스트 렌더링에서 key 속성은 리액트에게 있어서 각 요소를 식별하는 데에 사용되는 값입니다. 이 key 가 있어야 리액트는 가상 돔에서 어떤 요소가 어디에 있고, 어떻게 순서가 바뀌었는지 등의 순서와 변화를 제대로 감지할 수가 있습니다. 그래서 저의 경우에는 보통 유니크한 id 값을 key에 할당하는 편입니다.

4. 리액트의 개발 서버에서는 useEffect가 2번 실행되는 모습이 관찰되는데요. 그 이유가 무엇일까요?

  • 답변)
    • 의도: 자칫 지나치기 쉬운 리액트의 기본 개념을 확인하는 질문. 개발에 호기심이 많아야 알 수 있는 항목입니다.
    • 모범 답안: 단도직입적으로 말씀드리자면 바로 리액트의 StrictMode 때문입니다. 이 모드를 켜게 되면 오류를 피할 수 있도록 엄격한 개발 환경을 제공해주는데요. 여기서 useEffect가 2번 실행되는 이유가 있습니다.
      예를 들어서 개발자가 언마운트 상황을 테스트하려고 합니다. 언마운트 시에 클린업함수가 잘 작동하는지 여부를 확인하려고요. 이 상황을 테스트하려면 매번 컴포넌트를 마운트하고, 언마운트하고 수동으로 실행해줘야만 합니다. 당연히 번거롭겠죠. 그래서 리액트는 처음에 컴포넌트가 생성된 이후 마운트-언마운트-다시 마운트의 과정을 거치게 됩니다.
      이렇게 함으로써 개발자는 따로 수동으로 작동해주지 않아도 언마운트 상황을 테스트 할 수 있게 됩니다. 물론 개발 서버 한정이고, 배포 서버에서는 자연스럽게 마운트-언마운트 한 사이클만 진행이 됩니다.

5. 커스텀 훅을 사용해보셨나요? 사용해본 경험을 이야기해주세요.

  • 답변)
    • 의도: 커스텀 훅을 사용할 정도로 코드 퀄리티에 관심이 있는지 파악하려는 질문
    • 모범 답안: 네 저는 최근 프로젝트에서 커스텀 훅을 사용한 경험이 있습니다. 개인적으로도 정말 잘 사용하고 있는 기술이기도 합니다. 커스텀 훅을 사용한다면 기존의 컴포넌트 내부에 작성된 코드를 커스텀 훅을 만들어 정리하는 것으로 컴포넌트 내부를 좀 더 클린하게 정리할 수 있을 뿐더러 만들어진 커스텀 훅을 좀 더 보편적으로 개선하여 다른 컴포넌트에서도 재사용할 수 있습니다. 또한 비즈니스 로직의 분리를 실현하여 의존성을 줄이고 유지 보수성을 높일 수 있는 등 다양한 장점이 많습니다.
      사소한 단점으로는 커스텀 훅의 이름을 잘 지어줘야 다른 개발자들이 굳이 커스텀 훅의 내부를 들여다 보는 수고를 하지 않을 수 있다는 점이 있겠네요. 어찌보면 선언형 코드와 장단점을 공유하는 듯 합니다.
      저 같은 경우에는 useLocalStorage 훅을 작성하여 기존에 로컬 스토리지에 저장하고 읽어올 때 반복되는 로직을 통합하여 재사용성을 목적으로 구현한 바 있습니다. 기존에는 JSON.parseJSON.stringify 같은 메서드를 매번 호출해서 읽고, 저장해야 했지만 이 커스텀 훅을 구현함으로써 기존의 useState와 같은 사용감을 만들어냈습니다.

6. 리액트 컴포넌트의 렌더링 성능 향상에 쓰이는 React.memo에 대해 설명해주세요.

  • 답변)
    • 의도: 성능 최적화에 관심이 있는지 확인하는 질문
    • 팁: 사용 예시를 들면 좋습니다.
    • 모범 답안: 리액트에서 컴포넌트가 리렌더링 되는 기준을 살펴보자면 대표적으로 받아온 props의 변경이 있습니다. props가 변경되면 하위 컴포넌트 모두가 리렌더링됩니다. 그런데 만약 props의 변경과 하위 컴포넌트의 리렌더링과 관련이 없다면 어떨까요? 필요한 부분만 업데이트하고 나머지는 그대로 두기 위해 사용하는 것이 바로 React.memo입니다.
      예를 들어서 리스트 렌더링에서 리스트 아이템에 React.memo를 붙여주게 되면 리스트에서 변경된 부분의 아이템만 리렌더링할 수 있습니다. 리스트 전체를 리렌더링하지 않음으로써 성능을 최적화하는 것이 가능해진 겁니다.
profile
아무튼, 개발자

0개의 댓글