기술면접 1주차(3)

강연주·2024년 10월 4일

🙋‍♀️ 기술면접

목록 보기
4/112

1. 상태관리를 왜 할까요? 그리고 평소 state 관리는 어떻게 하시나요?

상태 = state
바닐라 JS만 배울 때는 state가 없었는데, React에서의 주요 개념 같다.

정의 - 어떠한 의미를 지닌 값.
애플리케이션의 시나리오에 따라 지속적으로 변경될 수 있는 값.

  • UI : 기본적으로 웹 에플리케이션에서 상태는, 상호 작용이 가능한 모든 요소의 현재 값을 의미한다. 다크/라이트 모드, 라디오를 비롯한 각종 input, 알림창의 노출 여부 등 각종 상태가 존재한다.
  • URL : 브라우저에서 관리되고 있는 상태값.
    예를 들어 https://www.airbnb.co.kr/rooms/1212?adults=2 에는, roomId=1212와 adults=2 라는 상태가 존재하고,
    이 상태는 사용자의 라우팅에 따라 변경된다.
  • form : loading(로딩 중인지), submit(현재 제출됐는지), disabled(접근이 불가능한지), validation(값이 유효한지) 등이 모두 상태로 관리된다.
  • 서버에서 가져온 값 : 클라이언트에서 서버로 요청을 통해 가져온 값도 상태로 볼 수 있다. 대표적으로 API 요청이 있다.

React에서 상태가 변하면 화면이 리렌더링되는 것은 아주 중요한 핵심 원리.
화면에 보여지는 값이나 데이터 등을 상태로 지정해야,
유저 상호 작용이나 시간의 흐름 등에 따라
그 초기값과 업데이트값 등을 적절하게 보여줄 수 있다.

useState로 초기값과 변화 함수를 지정.

( 출처 : 모던 리액트 deep dive, 김용찬, 위키북스 )


2. Redux가 무엇인가요, 왜 Redux를 사용하시나요?

  • Redux Toolkit은 Redux 로직을 작성하기 위해 저희가 공식적으로 추천하는 방법입니다. RTK는 Redux 앱을 만들기에 필수적으로 여기는 패키지와 함수들을 포함합니다. 대부분의 Redux 작업을 단순화하고, 흔한 실수를 방지하며, Redux 앱을 만들기
    쉽게 해주는 모범 사례를 통해 만들어졌습니다.

  • Can I use Redux without Redux toolkit?
    : Note that you are not required to use Redux Toolkit to use Redux. There are many existing applications that use other Redux wrapper libraries, or write all Redux logic "by hand", and if you still prefer to use a different approach, go ahead! However, we strongly recommend using Redux Toolkit for all Redux apps

https://ko.redux.js.org/tutorials/essentials/part-1-overview-concepts
https://ko.redux.js.org/tutorials/essentials/part-1-overview-concepts

리덕스란?
: JS앱을 위한 예측 가능한 상태 컨테이너.
'액션'이라고 불리는 이벤트들을 사용해 애플리케이션의 상태를 관리하고 업데이트하는 패턴이자 도구. 애플리케이션 전역에서 필요한 상태들을 관리하기 위해 중앙화된 store(저장소?) 역할을 한다. 상태들이 예측가능한 상황에서만 업데이트되도록 보장한다.

리덕스를 왜 사용할까?
: 애플리케이션의 여러 부분에서 필요한 상태들을 전역적으로 관리할 수 있다. 언제, 어디서, 왜, 어떻게 상태가 업데이트되는지 파악하기 용이.

리덕스를 언제 사용할까?
: 리덕스의 단점으로는, 학습 내용 증가, 길어지는 코드, indirection 추가 (참조, In computer programming, an indirection (also called a reference) is a way of referring to something using a name, reference, or container instead of the value itself), 따라야 하는 제한 사항들을 들 수 있는데,
이러한 리덕스가 유용하게 사용되는 경우는 다음과 같다.

  • 여러 군데에서 많은 상태들이 쓰일 때
  • 애플리케이션 상태가 시간 흐름에 따라 빈번히 업데이트될 때
  • 상태 업데이트의 로직이 복잡할 때
  • 애플리케이션이 중간 또는 대규모의 코드베이스를 가지거나
    다수의 인원이 작업할 때

3. Redux 말고 다른 전역 상태관리 아는 것 하나와 차이점을 말해주세요

다른 전역 상태 관리 : zustand(useStore로 로컬에서의 상태 및 변화를 관리), TanstackQuery(데이터 페칭, 로딩, 에러 처리와 로컬에서의 상태 및 변화 관리), recoil? zotai?


4. 버츄얼 돔과 리얼 돔의 차이를 설명해주세요.

버츄얼 돔은 실제로 실행되기 전에 그 미리 한번 그려보고
그러는 걸로 아는데요 어..


5. useRef에 대해 설명해주세요.

useRef는 useState와 동일하게 컴포넌트 내부에서 렌더링이 일어나도
변경 가능한 상태값을 저장한다는 공통점이 있다.

그러나 useState와 구별되는 큰 차이점 두 개가 있다.

  • useRef는 반환값인 객체 내부에 있는 current로 값에 접근 또는 변경할 수 있다.
  • useRef는 그 값이 변하더라도 렌더링을 발생시키지 않는다.

왜 useRef가 필요할까?

렌더링에 영향을 미치지 않는 고정된 값을 관리하게 위해서라면, 함수 외부에서 값을 선언해 관리하는 것이 동일한 기능을 수행할 수 있지 않을까?

🖥️
let value = 0;
function Component() {
  function handleClick() {
    value += 1
  }
  //...
}

이 방식에는 몇 가지 단점이 있다.

  • 컴포넌트가 실행되어 렌더링되지 않았음에도 value라는 값이 기본적으로 존재하여, 메모리에 불필요한 값을 갖게 하는 악영향.
  • Component가 여러 번 생성된다면 각 컴포넌트가 가리키는 값이 모두 value로 동일하다. 컴포넌트가 초기화되는 지점이 다르더라도 하나의 값을 봐야 하는 경우라면 유효할 수도 있지만, 대부분의 경우 컴포넌트 인스턴스 하나 당 하나의 값을 필요로 하는 것이 일반적이다.

➡️ useRef는 상기 두 가지 문제를 극복할 수 있는 리액트식 접근법.
컴포넌트가 렌더링될 때만 생성되며, 컴포넌트 인스턴스가 여러 개라도
각각 별개의 값을 바라본다.


🖥️ useRef를 사용한 DOM 접근 예제

function RefComponent() {
  const inputRef = useRef()

  //이때는 렌더링이 실행되기 전(반환 전)이므로 undefined를 반환
  console.log(inputRef.current) //undefined

  useEffect(() => {
    console.log(inputRef.current) //<input type="text"></input>
  }, [inputRef])

  return <input ref={inputRef} type="text" />
} 

useRef는 최초에 넘겨받은 기본값을 가지고 있다.
명심할 것은, useRef의 최초 기본값은 return문에 정의해 둔 DOM이 아니고 useRef()로 넘겨받은 인수라는 점이다.
useRef가 선언된 당시에는 아직 컴포넌트가 렌더링되기 전이라, return으로 컴포넌트의 DOM이 반환되기 전이므로 undefined다.

useRef를 사용할 수 있는 유용한 경우는, 렌더링을 발생시키지 않고 원하는 상태값을 저장할 수 있다는 특징을 활용해 useState의 이전 값을 저장하는 userPrevious() 같은 훅을 구현할 때다.


🖥️ useRef를 활용한 usePrevious 훅 구현


function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]); //value가 변경되면 그 값을 ref에 넣어둔다

  function SomeComponent() {
    const [counter, setCounter] = useState(0);
    const previousCounter = usePrevious(counter);

    function handleClick() {
      setCounter((prev) => prev + 1);
    }

    // 0 (undefined)
    // 1, 0
    // 2, 1
    // 3, 2

    return (
      <button onClick={handleClick}>
        {counter}
        {previousCounter}
      </button>
    );
  }
}

➡️ 이렇게 개발자가 원하는 시점의 값을, 렌더링에 영향을 미치지 않고 보관해두고 싶다면 useRef를 사용하는 것이 좋다.


그렇다면 useRef는 어떻게 구현되어 있을까?

🖥️ React에서의 useRef 구현

export function useRef(initialValue) {
  currentHook = 5
  return useMemo(() => ({current: initialValue}), [])
} 

값이 변경되어도 렌더링되면 안 된다는 점, 실제 값은 {current: value}와 같은 객체 형태로 있다는 점을 떠올려 보자. 렌더링에 영향을 미치면 안 되기 때문에 useMemo에 의도적으로 빈 배열을 선언해 뒀고, 이는 각 렌더링마다 동일한 객체를 가리키는 결과를 낳을 것이다. 자바스크립트의 특징, 객체의 값을 변경해도 객체를 가리키는 주소가 변경되지 않는다는 것을 떠올리면 useMemo로 useRef를 구현할 수 있다.

( 출처 : 모던 리액트 deep dive, 김용찬, 위키북스 )


6. useEffect의 실행 순서에 대해 설명해주세요.

마운트 - useEffect... 으어어엉

7. var, let, const의 차이에 대해 알려주세요.

var : 쓰지 마세요
let : 가변적 변수 선언, 재할당 가능, 코드 어디선가 이 변수의 값이 다르게 할당될 가능성
const : 불변성 유지 변수 선언, 재할당 불가능, 근데 상수라고 불러야만 정확한 건가?

var : 스코프 내 중복 선언 가능, 재할당 가능, 변수 선언이 무조건 상위로 끌어올려지는 호이스팅 발생 (런타임 이전에 변수 선언과 초기화 단계를 실행), 선언과 초기화 동시에 이루어짐, 함수 레벨 스코프

let : 스코프 내 중복 선언 불가능(Syantax Error 발생), 재할당 가능, 호이스팅 발생하지 않는 것처럼 동작 (엄밀히 따지면 호이스팅 O), 선언과 초기화 따로 이루어짐, 블록 레벨 스코프 : 블록 (중괄호로 나뉘는 for문, if문, switch문 등)을 다 지역 스코프로 취급해 동명의 변수가 스코프에 따라 다르게 사용될 수 있음, 값 재할당 가능,

const : 중복 선언, 재할당 불가능한 상수 (값의 불변을 의미
하지는 않는다)

( 출처 : 모던 자바스립트 deep dive, 이웅모, 위키북스 )

profile
아무튼, 개발자

0개의 댓글