- 15 React Interview Questions with Solutions을 번역한 글입니다.
- Translated by Do Junggeun (도정근)
전 세계에서 개발자에 대한 수요가 공급을 앞지르고 있으며 리액트의 인기는 사그라들 기미가 보이지 않습니다. 경험이 적은 개발자(혹은 일정 기간 취업 시장을 떠나 있던 개발자)에게는 면접을 통해 자신의 지식을 인증하는 것이 부담스러울 수 있습니다.
이 글에서 우리는 리액트의 핵심을 이해하고 효율적으로 활용하기 위해 필요한 15가지 질문을 다룹니다. 각 질문에 대해 답변을 요약하고, 추가적인 자료를 찾아볼 수 있는 링크를 제공할 것입니다.
Virtual DOM은 애플리케이션의 UI를 구성하는 HTML 엘리먼트를 메모리 내에서 구현한 것입니다. 컴포넌트가 다시 렌더링될 때, virtual DOM은 업데이트할 요소의 목록을 만들기 위해 기존의 DOM 모델에서 변경되는 사항을 비교합니다. DOM 전체를 다시 렌더링할 필요 없이 실제 DOM에 필요한 최소한만 변경하여 효율성이 높다는 것이 큰 장점입니다.
JSX는 HTML처럼 보이는 코드를 작성할 수 있게 해주는 자바스크립트 문법의 확장입니다. JSX는 자바스크립트 함수 호출 방식으로 컴파일되어 컴포넌트에 대한 마크업을 만들 수 있는 더 좋은 방법을 제공합니다.
이 JSX를 보세요:
<div className="sidebar" />
이것은 아래의 자바스크립트로 변환됩니다:
React.createElement(
'div',
{className: 'sidebar'}
)
React 16.8(hooks 도입) 이전에는 내부 state를 유지하는 데 필요한 컴포넌트를 생성하거나 생명주기 메소드(lifecycle methods)(즉, componentDidMount
및 shouldComponentUpdate
)를 활용하기 위해 클래스 기반 컴포넌트를 사용했습니다. 클래스 기반 컴포넌트는 리액트의 Component
클래스를 확장하는 ES6 클래스입니다. 또한 최소한 render()
메서드를 포함해야 합니다.
클래스 컴포넌트:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
(hooks 도입 이전의) 함수형 컴포넌트는 state를 갖지 않으며 렌더링할 출력 결과를 리턴(반환)합니다. 함수형 컴포넌트는 클래스 기반 컴포넌트보다 심플하기 때문에 props에만 의존하는 UI을 렌더링하는데 선호됩니다.
함수형 컴포넌트:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Note: 리액트 16.8에서 도입된 hooks 덕분에 더 이상 이 차이는 의미가 없습니다. (질문 14와 15를 보세요)
리액트에서 collection을 렌더링할 때 엘리먼트와 데이터 사이의 관계를 추적하기 쉽도록 반복되는 각 엘리먼트에 key를 추가하는 것이 중요합니다. 키는 고유한 ID(이상적으로는 UUID 또는 기타 고유 문자열)를 사용해야 하지만, 마지막 수단으로 Array index가 될 수 있습니다.
<ul>
{todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
)};
</ul>
key를 사용하지 않으면 collection에 item을 추가하거나 제거할 때 예상치 못한 동작 결과가 발생할 수 있습니다.
props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 데이터입니다. props는 수정될 수 없으며 표시되거나 다른 값을 계산하는데만 사용됩니다. state는 컴포넌트의 생명 주기 동안 수정될 수 있는 내부 데이터로, 다시 렌더링해도 유지됩니다.
만약 컴포넌트의 state를 직접 변경하려고 시도한다면, 리액트는 컴포넌트를 다시 렌더링해야 하는지 알 수 있는 방법이 없습니다. setState()
메소드를 사용하면 리액트는 컴포넌트의 UI를 업데이트할 수 있습니다.
보너스로, 어떻게 state의 변경이 반드시 동기적으로 이루어진다고 보장되지 않는지 이야기해볼 수 있습니다. 컴포넌트의 state를 다른 state(또는 props)를 기반으로 변경해야 하는 경우, state
와 props
를 두 인자(arguments)로 사용하는 setState()
에 함수를 전달하면 됩니다:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
컴포넌트 props의 type을 확인하기 위해서는 prop-types
패키지(리액트 15.5까지는 리액트에 포함되어 있었습니다)를 이용하여 기대되는 값의 type과 prop이 필수적(require)인지 여부를 선언할 수 있습니다.
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
prop drilling은 부모 컴포넌트에서 하위 컴포넌트(자식 컴포넌트의 자식 컴포넌트 등으)로 데이터를 전달할 때 발생하는 것으로, props를 전달하는 것 외에는 props를 필요로 하지 않는 다른 컴포넌트를 통해 “drilling”(내리꽂기) 됩니다.
컴포넌트를 리팩토링하고, 컴포넌트를 더 작은 컴포넌트들로 쪼개지 않고, state를 가장 가까운 부모 컨포넌트와만 공유함으로써 prop drilling 회피할 수 있습니다. 위계상 멀리/깊게(deep/far)떨어진 컴포넌트와 state를 공유할 때, React의 Context API 혹은 Redux와 같은 state 관리 라이브러리를 사용할 수 있습니다.
리액트는 하나의 앱 안에서 복수의 컴포넌트들이 state를 공유할 때 발생하는 문제들을 해결하기 위해 context API를 제공합니다. context가 도입되기 전에는 Redex와 같은 별도의 상태 관리 라이브러리를 가져오는 것이 유일한 방법이었습니다. 그러나 많은 개발자들은 (특히 작은 앱에서) Redux가 불필요한 복잡성을 유발한다고 느꼈습니다.
Redux는 React를 위한 써드파티 state 관리 라이브러리로, context API가 개발되기 전부터 존재했습니다. Redux는 store라고 불리는 state 컨테이너의 개념을 기반으로 하는데, store 컴포넌트는 데이터를 props로 받을 수 있습니다. store를 업데이트하는 유일한 방법은 reducer를 통해 전달되는 store에 action을 보내는 것입니다. reducer는 action과 현재의 state를 받고, 새로운 state를 반환(return)하고, 구독된(subscribed) 컴포넌트를 다시 렌더링하게 만듭니다.
리액트 컴포넌트를 스타일링하는 다양한 방법이 있고, 각각은 장단점이 있습니다. 주로 사용되는 것들은 다음과 같습니다:
HTML 문서에서 많은 form 엘리먼트들(<select>
, <textarea>
, <input>
등)은 고유한 state를 유지합니다. 비제어 컴포넌트는 DOM을 이러한 input들의 state에 대한 진짜 근원(source of truth for the state of these inputs)으로 취급합니다. 제어 컴포넌트에서 내부 state는 엘리먼트의 값(value)를 추적하기 위해 사용됩니다. input의 값이 변경되면 리액트는 input을 다시 렌더링합니다. 비제어 컴포넌트는 non-React 코드와 합칠 때(예를 들어 jQuery 플러그인의 일부를 지원해야 할 때) 유용하게 사용될 수 있습니다.
클래스 기반 컴포넌트는 그들이 mount(DOM에 렌더링)되었을 때, unmount될 때 등과 같이 그들의 생명주기 중 특정한 시점에 호출되는 특별한 메소드를 선언할 수 있습니다. 이는 예를 들면 컴포넌트가 필요로 하는 것을 셋팅 및 해제하거나, 타이머를 설정하거나 브라우저 이벤트에 바인딩하는 데 유용합니다.
아래의 생명주기 메소드들은 컴포넌트를 불러오기 위해 사용할 수 있습니다.
shouldComponentUpdate
가 true
를 리턴할 때 호출됩니다.Hooks는 클래스 기반 컴포넌트의 장점(예를 들면 내부 state와 생명주기 메소드)을 함수형 컴포넌트로 가져오려는 리액트의 시도입니다.
React에 hooks를 도입해서 얻을 수 있는 여러 이점들은 다음과 같습니다:
this
의 필요성이 사라집니다비록 완벽하지는 않지만(React는 지속적으로 진화하고 있습니다), 이 질문들은 많은 내용을 다루고 있습니다. 이 주제들을 이해하면 React 라이브러리에 대한 훌륭한 실무 지식을 얻을 수 있을 것입니다. 제시된 참고 자료를 공부하면 더욱 깊게 이해하는데 도움이 될 것입니다.
우리는 React 인터뷰를 위한 코드 연습 가이드도 준비하고 있으니, 가까운 시일 내에 볼 수 있기를 바랍니다.
행운을 빕니다!
좋은 포스트 너무 감사합니다!!취뽀하고 올게요!!