React 기술 문제

게으른개발자·2020년 6월 26일
0

면접준비

목록 보기
5/6

1. Real DOM 과 Virtual DOM 개념을 설명하라

DOM: Document Object Model로 HTML 문서를 프로그래밍적으로 접근 가능하게 해주는 인터페이스

"변화(Mutation)"라는것은 상당히 복잡한 작업:
특정 이벤트가 발생했을때, 모델에 변화를 일으키고, 변화를 일으킴에 따라 어떤 DOM 을 가져와서 어떠한 방식으로 뷰를 업데이트 해줄 지 로직을 정해줘야 하는데 페이스북은 변화를 주는 것이 아니라 뷰를 날려버리고 새로 만드는 것을 고려했다.

변화를 줄 때 마다 뷰를 새로 만들어버리면 성능적으로 엄청난 문제가 있을 것...

그래서 등장하는 것이 Virtual DOM이다.

Virtual DOM: 말 그대로 가상의 DOM이다. 변화가 일어나면, 실제로 브라우저의 DOM 에 새로운걸 넣는것이 아니라, 자바스크립트로 이뤄진 가상 DOM 에 한번 렌더링을 하고, 기존의 DOM 과 비교를 한 다음에 정말 변화가 필요한 곳에만 업데이트를 해주는 것

즉, 데이터가 바뀌었을 때 어떻게 업데이트를 할 지를 고려하는 것이 아닌, 일단 바뀐 데이터로 그려놓고 비교를 한 다음, 바뀐 부분만 바꾸는 것이다.

2. React 의 주요 특징은 무엇인가?

  • RealDOM 을 조작하는데 많은 비용이 들어간다는 점을 고려하여 리액트는 RealDOM 대신 VirtualDOM을 사용한다

  • 단방향 데이터 흐름으로 데이터를 추적하기 쉽고 디버깅을 하기 쉽다

    단방향 데이터 흐름이란, 데이터는 항상 일정한 장소에 위치해있고, 그 장소에서만 변경이 가능하다. 반면 양방향 데이터 흐름일 경우에 데이터는 view나 model로 변한다. 즉, Data가 UI를 변경시키는 것이다. 반대로 UI가 Data를 변경시킬 수는 없다.

  • UI Component 기반으로, UI를 component로 쪼개서 사용하여 재사용성 및 유지보수의 이점이 있다

3. JSX 란 무엇인가?

JSX 는 JavaScript XML (ECMAScript로 XML 유사 구문 확장) 의 구문 표기법이다. HTML과 같은 문법과 함께 JavaScript를 표현할 수 있다.

아래의 h1 태그안에 text 는 render 함수에 의해 JS 함수로 반환된다.

render() {
  return (
    <div>
      <h1> Welcome to React world!!</h1>
    </div>
  );
}

4. Element 와 Component 의 차이점은 무엇인가?

Element

DOM 노드, 또는 다른 component들과 관련하여 화면에 표시 할 내용을 표현하는 일반 객체다. 가볍고, stateless 하고, 불변하며 가상 DOM 안에 포함되어 있다.
Element는 바로 사용되지는 않으며, Component에서 리턴 받아서 사용 되곤 한다.

Component

function 혹은 class이며, state를 가지고 있다. props를 받아 Elements를 출력하는 함수와 같다.

Componentstate가 바뀌면, Component를 리턴 받아서 가상 DOM에 만든다(Element를 만드는 비용은 저렴하다). 가상 DOMReal DOM을 비교하여 Real DOM에서 Component의 바뀐 부분을 업데이트 한다.

5. React 에서 Component 를 어떻게 생성하는가?

두가지의 방법이 있다.

Functional Components

Component를 생성하는 가장 간단한 방법이며 stateLifeCycle이 없다. 대신 props를 받을 수 있고 React elements를 리턴할 수 있다. 초기 마운트가 빠르고 메모리 자원을 덜 쓴다.

import React from 'react';

function Hello(props) {
    return (
        <div>Hello {props.name}</div>
    );
}

export default Hello;

Class Components

EcmaScipt 6에 도입된 class 문법을 사용한다. 컴포넌트에서 LifeCycle API 를 사용해야 하거나, state 를 사용하는 경우에는 꼭 이렇게 정의를 해야한다.

import React, { Component } from 'react';

class Hello extends React.Component {
  render() {
    return (
      <div>Hello {this.props.name}</div>
    );
  }
}

export default Hello;

6. Pure Component는 무엇인가?

결론만 말하자면 두 개는 shouldComponentUpdate 라이프 사이클 메소드를 다루는 방식을 제외하곤 같다. 즉, PureComponentshouldComponentUpdate 라이프 사이클 메소드가 이미 적용 된 버전의 React.Component 클래스라고 보면 된다.

React.Component를 확장(extends)해서 컴포넌트를 만들 때, shouldComponentUpdate 메서드를 별도로 선언하지 않았다면, 컴포넌트는 props, state 값이 변경되면 항상 리렌더링(re-render) 하도록 되어 있다.

하지만, React.PureComponent를 확장해서 컴포넌트를 만들면, shouldComponentUpdate 메서드를 선언하지 않았다고 하더라도, PureComponent 내부에서 propsstate를 shallow level 안에서 비교 하여, 변경된 값이 있을 시에만 리렌더링 하도록 되어 있다.

7. State 와 Props 의 차이는?

props 는 부모 컴포넌트가 자식 컴포넌트에게 주는 값입니다. 자식 컴포넌트에서는 props 를 받아오기만하고, 받아온 props 를 직접 수정 할 수 는 없습니다.

반면에 state 는 컴포넌트 내부에서 선언하며 내부에서 값을 변경 할 수 있습니다.

  1. props스마트폰의 볼륨버튼이라면 사용자가 볼륨버튼을 누르면 state는 스마트폰안에서 스스로의 상태인 볼륨이 바뀌게 해놓은 모든 조치(회로,프로그래밍 등등)라고 할 수 있습니다.
  2. 상위 컴포넌트는 하위 컴포넌트에게 props를 통해 값을 전달해 내부의 state를 바꾸기 때문에 컴포넌트 스스로 외부에서 전달되는 props를 변경하는 것은 금지되어 있습니다. 또한, 하위 컴포넌트가 상위 컴포넌트를 동작시키려면 props를 전달하는 것이 아니라 상위 컴포넌트 안에 이벤트를 심고 그 안에 setState로 값을 바꿔야 합니다.

8. React 의 LifeCycle에 대해서 설명하라

LifeCycle API 는 Component 가 브라우저에서 나타날때, 사라질때, 그리고 업데이트 될 때, 호출되는 API 이다. Component 가 생성 되고 소멸 될 동안 단계별로 Component 를 컨트롤 할 수 있도록 이 API를 오버라이드 해서 사용 할 수 있다.

호출순서

컴포넌트가 생성될 때: constructor - getDerivedStateFromProps - render - componentDidMount

컴포넌트의 Props가 변경될 때: getDerivedStateFromProps -shouldComponentUpdate - render - getSnapshotBeforeUpdate - componentDidUpdate

컴포넌트의 State가 변경될 때: shouldComponentUpdate - render - getSnapshotBeforeUpdate -componentDidUpdate

Component 초기 생성

constructor

constructor(props) {
  super(props);
}

컴포넌트가 새로 만들어질 때마다 이 함수가 호출된다.

위 코드의 constructor 에서 super(props) 를 호출 한 이유는, 컴포넌트를 만들게 되면서, Component 를 상속했으며, 이렇게 constructor 를 작성하게 되면 기존의 클래스 생성자를 덮어쓰게 된다. 그렇기에, 리액트 컴포넌트가 지니고있던 생성자를 super 를 통하여 미리 실행하고, 그 다음에 우리가 할 작업 (state 설정) 을 해주는 것이다.

componentDidMount

componentDidMount(nextProps) {
  // 외부 라이브러리 연동: D3, masonry, etc
  // 컴포넌트에서 필요한 데이터 요청: Ajax, GraphQL, etc
  // DOM 에 관련된 작업: 스크롤 설정, 크기 읽어오기 등
}

이 API 는 컴포넌트가 화면에 나타나게 됐을 때 호출된다. 여기선 주로 D3, masonry 처럼 DOM 을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 통하여 ajax 요청을 하거나, DOM 의 속성을 읽거나 직접 변경하는 작업을 진행한다.

Component 업데이트

static getDerivedStateFromProps(nextProps, prevState)

static getDerivedStateFromProps(nextProps, prevState) {
  // 여기서는 setState 를 하는 것이 아니라
  // 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로
  // 사용됩니다.
  /*
  if (nextProps.value !== prevState.value) {
    return { value: nextProps.value };
  }
  return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
  */
}

v16.3 이후에 만들어진 LifeCycle API
이 API 는 props 로 받아온 값을 state 로 동기화 하는 작업을 해줘야 하는 경우에 사용된다.

shouldComponentUpdate(nextProps, nextState)

shouldComponentUpdate(nextProps, nextState) {
  // return false 하면 업데이트를 안함
  // return this.props.checked !== nextProps.checked
  return true;
}

리액트에서는 변화가 발생하는 부분만 업데이트를 해줘서 성능이 잘나온다. 하지만, 변화가 발생한 부분만 감지해내기 위해서는 Virtual DOM 에 한번 그려줘야한다.

즉, 현재 컴포넌트의 상태가 업데이트되지 않아도, 부모 컴포넌트가 리렌더링되면, 자식 컴포넌트들도 렌더링 된다.

변화가 없으면 물론 DOM 조작은 하지 않게 된다. 그저 Virutal DOM 에만 렌더링 할 뿐. 이 작업은 그렇게 부하가 많은 작업은 아니지만, 컴포넌트가 무수히 많이 렌더링 된다면 얘기가 조금 달라진다. CPU 자원을 어느정도 사용하고 있는것은 명백한 사실!

쓸데 없이 낭비되고 있는 이 CPU 처리량을 줄여주기 위해서 shouldComponentUpdate를 작성 하여 Virtual DOM 에 불필요한 리렌더링을 방지한다.

이 함수는 기본적으로 true 를 반환한다. 따로 작성을 해주어서 조건에 따라 false 를 반환하면 해당 조건에는 render 함수를 호출하지 않는다.

getSnapshotBeforeUpdate(prevProps, prevState)

이 API 가 발생하는 시점은 다음과 같다.

  1. render()
  2. getSnapshotBeforeUpdate()
  3. 실제 DOM 에 변화 발생
  4. componentDidUpdate

이 API를 통해서, DOM 변화가 일어나기 직전의 DOM 상태를 가져오고, 여기서 리턴하는 값은 componentDidUpdate 에서 3번째 파라미터로 받아올 수 있게 된다.

이 라이프 사이클 함수는 많이 활용 되지는 않지만, 화면을 갱신하는 동안 수동으로 스크롤 위치를 고정하는 경우 등에 사용될 수 있다.

componentDidUpdate(prevProps, prevState, snapshot)

이 API는 컴포넌트에서 render()를 호출하고난 다음에 발생하게 된다. 이 시점에선 this.propsthis.state가 바뀌었다. 그리고 파라미터를 통해 이전의 값인 prevPropsprevState를 조회 할 수 있다. 그리고, getSnapshotBeforeUpdate에서 반환한 snapshot 값은 세번째 값으로 받아온다.

잘 활용되지 않지만 getSnapshotBeforeUpdate 함수와 함께 사용하여 스크롤을 수동으로 고정시킬 때 활용되기도 한다.

Component 제거

componentWillUnmount

이벤트, setTimeout, 외부 라이브러리 인스턴스 제거

profile
딩코딩코딩

0개의 댓글