티스토리 뷰

반응형

1. 성능 최적화는 어떻게 하고, 어떤 경험이 있나요?


2. 많은 JS 프레임워크 중 React를 왜 사용하는지, 어떤 장단점이 있는지 설명하세요.

리액트는 페이스북에서 주도하여 개발한 웹 어플리케이션의 UI를 효과적으로 구축하기 위해 사용하는 자바스크립트 기반 라이브러리입니다. 리액트 자체는 프레임워크라고 부를 수 있는 기준인 라우팅, 상태관리 기본 제공을 충족하지 못하기 때문에 '라이브러리'라고 하지만, React의 생태계는 프레임워크를 기반으로 합니다. 

📍프레임워크 vs 라이브러리
프레임워크는 원하는 기능 구현에 집중하여 개발할 수 있도록 일정한 형태와 필요한 기능을 갖추고 있는 골격,뼈대를 의미합니다.
반면, 라이브러리는 소프트웨어 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모임 즉  모아둔 코드, 함수들의 집합이며 코드 작성 시 활용 가능한 도구들을 의미합니다. 예를들어 프레임워크는 전체적인 흐름을 스스로가 쥐고 있으며 사용자는 그 안에서 필요한 코드를 짜 넣으며 반면에 라이브러리는 사용자가 전체적인 흐름을 만들며 라이브러리를 가져다 쓰는 것이라고 할 수 있습니다.

장점

1. virtual dom을 사용하여 브라우저 렌더링 속도가 빠릅니다.

📍Virtual DOM
가상의 DOM으로, 브라우저에 실제로 보여지는 DOM이 아니라 단순히 메모리에 가상으로 존재하는 DOM으로서, 단순한 Javascript객체이기 때문에 작동 성능이 브라우저에서 DOM을 보여주는 것보다 속도가 훨씬 빠르다고 합니다. 리액트는 상태가 업데이트 되면 업데이트가 필요한 곳의 UI를 가상의 DOM을 통해 렌더링합니다. 이때 리액트 내부의 엔진을 통해 실제 브라우저에서 보여지고 있는 DOM과 비교를 한 후, 차이가 있는 곳을 감지해서 실제 DOM에 패치를 시킵니다.

2. component 형식으로 페이지 구성을 하여 공통 컴포넌트를 만들어 놓아 재사용성이 좋고, 코드 가독성을 높일 수 있습니다.
3.
성능이 뛰어난 가비지 컬랙터, 메모리 관리 기능을 지원합니다.
4.다른 framework나 라이브러리와 병행해서 사용할 수 있습니다. 이는 개발이 이미 완료된 프로젝트에도 적절히 녹여낼 수 있어 확장성이 있습니다.

단점

1.IE8 이하 버전은 지원하지 않습니다. (IE8 이하 버전을 지원해야 할 경우 v0.14 버전을 사용 해야함)
2.spa환경으로 인해 빠르게 앱을 빌드 하되, 페이지에 담긴 모든 것들이 로드되어 보여줄 준비가 되지 않는 단점이 있습니다.
3.SEO에 어려움이 있습니다. 그리하여 리액트로 만든 웹사이트는 non-SEO friendly site라고 불리기도 합니다. 리액트는 하나의 HTML파일이 있으며, 렌더링 되기 이전에는 빈 상태의 HTML만 있으므로 검색 엔진에 올라가기에 어려움이 있습니다. 이러한 단점을 해결할 수 있는 방법에는 SSR,meta-tag,Pre-rendering 등이 있습니다. 

📍리액트에서 seo를 위한 meta-tag 설정

리액트는 SPA이라, 각 검색로봇(크롤러)들이 리액트로 만들어진 사이트를 읽을 때 단 하나의 index.html 만을 읽게 됩니다. 이는 각각의 페이지에 대한 정보를 읽지 못한다는 단점이 있습니다. 이러한 단점을 극복하기 위해 메타태그를 사용하는 것인데 이것을 사용하여 크롤러가 읽기 쉽도록 어떤 페이지인지 설명해주어 사이트 정보 제공을 하는 것입니다.

참고 : https://velog.io/@miyoni/noSSRyesSEO
📍리액트에서 seo를 위한 Pre-rendering 설정

사전 렌더링은 웹 크롤러가 볼 수 있도록 페이지의 모든 요소를 사전로드하는 프로세스를 의미합니다. prerender 서비스는 페이지 요청을 낚아채어 사용자가 크롤러인지 여부를 확인하여 크롤러인 경우 캐시 된 버전의 페이지를 전달하여 줍니다. 반대로 크롤러가 아니라면 일반적인 페이지를 전달해주게 되죠.
즉, 크롤러를 위한 최적화 작업을 하는 것이 prerender의 핵심이라고 할 수 있습니다.

참고 : https://ujeon.medium.com/react-react-snap%EC%9C%BC%EB%A1%9C-pre-rendered-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0-70fa56816d75


참고: https://velog.io/@jeromecheon/React%EB%9E%80-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EC%9E%A5%EB%8B%A8%EC%A0%90-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0


3. Virtual DOM이란 무엇이고 동작원리는 무엇인지, DOM과 어떤 차이를 가지고 있는지, Virtual DOM을 사용하면 어떤 장점을 가지고 있나요? (reflow, repaint)

Virtual DOM이란 가상의 DOM으로, 브라우저에 실제로 보여지는 DOM이 아니라 단순히 메모리에 가상으로 존재하는 DOM으로서,DOM의 조작을 최소한으로 유지하므로 렌더링 성능이 브라우저에서 DOM을 보여주는 것보다 속도가 훨씬 빠르기 때문에 압도적으로 DOM의 부담을 줄여줍니다.

또한 몇가지의 특수 키워드(ref, key, htmlFor)등 조금씩 다른부분이 존재하지만 실제 DOM Virtual Dom은 구조상 큰 차이가 없어 이해하기 편하다는 장점이 있습니다.

리액트는 상태가 업데이트 되면 업데이트가 필요한 곳의 UI를 가상의 DOM을 통해 렌더링합니다. 이때 리액트 내부의 엔진을 통해 실제 브라우저에서 보여지고 있는 DOM과 비교를 한 후, 차이가 있는 곳을 감지해서 실제 DOM에 패치를 시킵니다.  

📍DOM이란?
DOM은 Document Object Model의 줄임말로 번역하면 문서 객체 모델이라는 뜻입니다. 하지만 단어만 들었을 때는 크게 와 닿는게 없습니다. 이 DOM이란 트리 구조로 되어있는 객체 모델로써, Javascript가 getElementbyid()를 같은 함수를 이용하여 HTML문서의 각 요소(li, head같은 태그들)들을 접근하고 사용할 수 있도록 하는 객체 모델입니다.
 
하지만 이 DOM은 트리구조로 되어있어서 이해하기 쉽다는 장점이 있지만, 이러한 구조 덕분에 거대한 DOM 트리에서는 속도 이슈가 발생하였고 지속적인 DOM 업데이트는 잦은 오류와 사용자 인터페이스에 악영향을 끼쳤습니다, 또한 DOM을 제대로 찾지 못한다면 코드를 분석하려고 다시 거대한 HTML을 들여다 봐야 하는 단점이 존재했습니다.
 
이러한 단점을 해결하기 위해 나온것이 바로 가상돔(Virtual DOM)입니다.

                                                    


4. JSX란 무엇인가요?

JSX(JavaScript XML)는 Javascript에 XML을 추가한 확장한 문법입니다.
 - JSX는 리액트로 프로젝트를 개발할 때 사용되므로 공식적인 자바스크립트 문법은 아닙니다.
 - 브라우저에서 실행하기 전에 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환됩니다.
 - JSX는 하나의 파일에 자바스크립트와 HTML을 동시에 작성하여 편리합니다.

참고 : https://goddaehee.tistory.com/296


5. key를 사용하는 이유에 대해 설명하세요.

Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕습니다.key 를 사용하는 이유는 엘리먼트 혹은 컴포넌트의 변화를 감지하기 위함이고,그 이유는 효율적인 DOM 사용을 위해서입니다.

참고 : 

https://www.youtube.com/watch?v=QC3PtSlzp3s

https://ko.reactjs.org/docs/reconciliation.html#recursing-on-children


6. 왜 state를 직접 변경하지 않고 setState를 사용해 값을 변경하나요?


7. prop drilling은 무엇이고 과도한 Prop Drilling을 어떻게 피할 수 있나요?

Prop Drilling 은 props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정입니다.
Prop Drilling 은 규모가 작으면 문제가 되지 않지만, 프로젝트 규모가 커짐에따라 컴포넌트가 수없이 많아 지게 된다면 상위컴포넌트로부터 전달받은 prop을 추적하기 힘들어지게 됩니다. 그렇기 때문에 유지보수도 더욱 어려워 집니다. 

과도한 Prop Drilling 을 피하기 위해서는
1) 전역 상태관리 라이브러리 사용으로 
redux, MobX, recoil 등을 사용하여 해당 값이 필요한 컴포넌트에서 직접 불러서 사용할 수 있습니다.
2) children 을 적극적으로 사용하는 것입니다.이렇게 리팩토링을 진행한다면 하나의 컴포넌트에서 값을 관리하고, 그 값을 하위요소로 전달할 때 전혀 코드의 추적이 어려워지지 않습니다.

import React from "react";
import "./styles.css";

export default function App() {
  const content = "Who needs me?";
 return (
    <div className="App">
      <FirstComponent>
        <SecondComponent>
          <ThirdComponent>
            <ComponentNeedingProps content={content}  />
          </ThirdComponent>
        </SecondComponent>
      </FirstComponent>
    </div>
  );
}

function FirstComponent({ children }) {
  return (
    <div>
      <h3>I am the first component</h3>;
     { children }
    </div>
  );
}

function SecondComponent({ children }) {
  return (
    <div>
      <h3>I am the second component</h3>;
     {children}
    </div>
  );
}

function ThirdComponent({ children }) {
  return (
    <div>
      <h3>I am the third component</h3>
        {children}
    </div>
  );
}

function ComponentNeedingProps({ content }) {
  return <h3>{content}</h3>
}

8. Suspense란 무엇인가요? lazy란 무엇인가요?

1) React.lazy는 해당 lazy 컴포넌트가 있는 컴포넌트가 리퀘스트(방문)될 때 비동기식으로 import 해서 필요할 때 불러오게 됩니다.

2) React.Suspense는 바로 React.lazy가 비동기식으로 불러올 때 잠깐 동안(네트워크 사정에 따라 빈 화면이 보일 수 있습니다) 화면이 비어 보이게 되는데요.

이때 뭔가 로딩되고 있다고 유저에게 알려줄 때 쓰입니다.

참고: 
https://mycodings.fly.dev/blog/2022-08-29-react-lazy-react-suspense-guide


9. useCallback, useMemo, memo의 차이에 대해 설명하세요.

☑️Memo

React는 컴포넌트를 렌더링 한 뒤, 이전 렌더된 결과와 비교하여 Dom 업데이트를 결정한다.
상황에 따라 이 과정의 속도를 높이기 위해 React.memo를 사용 한다.

☑️ useMemo

메모이제이션된 값을 반환합니다. 이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 한다. 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산 합니다. 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산합니다.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

 

☑️ useCallback

메모이제이션 된 콜백을 반환합니다. useMemo와 유사하게 이용되며 '함수'에 적용해줍니다.
의존성이 변경되었을때만 변경됩니다. 때문에 특정 함수를 새로 만들지 않고 재사용가능하게 합니다.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

10. Context API가 있는데 왜 상태관리 라이브러리를 사용하나요?

Context API는 리액트에서 전역상태관리이기 때문에 상태값을 변경하면 provider 로 감싼 모든 자식 컴포넌트들이 리렌더링하게됩니다. 그래서 규모가 커지게 될 경우 상태관리 라이브러리를 사용해 각 자식 컴포넌트들이 리렌더링하지 않도록 작업하기위해 라이브러리를 사용합니다.

Context API는 규모가 작을 때에 유리한 부분이 있습니다. 또한 부모 컴포넌트 사이에 낀 중간 컴포넌트가 존재할 때가 있다. 그 중간 컴포넌트는 부모와 자식의 상태를 매개하기 위해서만 props 를 받는다. 이런 중간 컴포넌트가 많아지면 redux 의 보일러플레이트 만큼 코드량이 많아집니다.

context api 를 쓰면 그런 중간 컴포넌트를 건너뛰고 바로 대상으로 하는 컴포넌트로 전달할 수 있다.

참고:

https://dev.rase.blog/21-10-07-context-and-state-management/


11. 상태관리 라이브러리로는 어떤 걸 사용하고 선택한 이유가 무엇인지. 상태관리 라이브러리들의 장단점을 아는대로 설명하세요.

. Redux

위 그림처럼 Redux는 데이터의 흐름이 단방형으로 흐르는 구조이다.

action, reducer, selector, store를 세팅하는 보일러플레이트 코드는 유지보수라는 장점을 가지고 있지만,

상태의 개수가 적더라도 보일러플레이트 코드가 크다는 단점이 있다.

 

Redux 라이브러리의 경우 store에 모든 상태를 저장하는 중앙집중방식이다.

store는 외부 요소이기 때문에 리액트 내부에 접근할 수 없다.

그리고 비동기 데이터 처리를 하려면 saga와 같은 별도의 라이브러리를 추가적으로 사용해야 한다.

 

Redux는 데이터 관리에 보수적인 접근방식을 가지고 있는데

이는 보일러플레이트 코드가 크다는 단점이 되었지만 확장 및 디버깅에 있어서는 엄청난 강점을 가지고 있다.

  • Redux는 오직 하나의 store만 가지며, 하나의 객체 트리를 가지기 때문에 디버깅이 용이하다.
  • store 내부 상태는 action 객체에 의해서만 변경이 가능하다. 모든 state 변화들이 하나의 store에만 집중되어 있고 단방향으로 일어나기 때문에 예측 가능한 결과가 나타난다.
  • reducer는 순수함수이기 때문에 상태를 변경하는 것이 아닌 새로운 상태를 반환한다.

2. MobX

MobX는 Redux보다 사용률이 떨어진다.

Mobx의 경우 Redux와 달리 불변성에 신경쓰지 않아도 될 정도로 규칙만 잘 지키면 최적화가 잘되는데 왜 사용률이 떨어질까?

  • MobX는 store가 여러개가 될 수 있는데, 이는 분리가 용이해 편리할 수 도 있는 반면 상태 변경 시 다수의 store가 영향을 받을 수 있다.
  • Redux와 다르게 store의 데이터를 action 발행 없이 업데이트할 수 있는데 이는 구현은 쉽고 용이하나 테스트나 유지보수의 측면에서 문제를 일으킬 수 있다.

그래서 유지보수 및 확장성을 고려해야 하는 프로젝트의 경우엔 MobX는 좋지 않은 선택일 수 있다.

하지만 Redux보다 러닝커브가 낮고 보일러플레이트 코드의 양 또한 적기 때문에 프로젝트 규모가 크지 않다면 MobX를 사용하는 것이 좋을 수 있다.


3. Context API

Context API는 리액트가 자체적으로 가지고 있다.

정적인 데이터 위주로 처리하거나 업데이트가 자주 발생하지 않을 때 사용하기 적합하다.

 

복잡한 업데이트를 처리 할 때에는 비효율적인데

Provider로 감싸진 부분의 업데이트가 되지 않은 state에도 리렌더링이 발생하기 때문이다.

이런 불필요한 리렌더링을 보완하기 위해 Recoil이란 라이브러리가 나왔다.


4. Recoil

Recoil은 최근 페이스북에서 나온 라이브러리이다.

 

Recoil은 Atom과 Selector로 이루어져 있다.

Atom은 상태의 단위로, 유니크한 키값으로 구분된다.

해당 Atom을 구독하고 있으면 해당 컴포넌트들만 선택적으로 리렌더링이 된다.

 

Atom의 상태변화는 순수함수를 통해 일어나는데 이를 Selector라고 한다.

Selector는 비동기 처리 뿐만 아니라 데이터 캐싱 기능도 제공하기 때문에 비동기 데이터를 다루기에 용이하다.

이러한 접근을 통해 Recoil은 아래와 같은 특징을 가진다.

  • 보일러플레이트가 없기 때문에 리액트 지역 상태로서 단순한 get/set 인터페이스로 상태를 공유할 수 있다.
  • 동시성 모드와 양립할 수 있는 가능성이 있다.
  • 상태를 분산적으로 둘 수 있기 때문에 코드 스플리팅이 가능하다.

하지만 아직 버전이 낮아 안정성의 측면에서는 좋지 않을 수도 있다.

그래서 큰 규모의 프로젝트에서는 도입하기 어려울 것 같지만 요즘 아래처럼 라이브러리를 같이 사용하는 경우도 있다.

 

1️⃣ Rest API를 사용할 경우

: Tanstack-Query(API로부터 데이터 불러오기, 저장, 자동화) + Recoil(미니 리덕스)

 

2️⃣ GraphQL API를 사용할 경우

: Apollo-client + Recoil

 

💡 코드 스플리팅

코드에서 당장 사용하는 부분만 로딩하고,

현재 필요하지 않은 코드 부분은 따로 분리시켜 나중에 로드함으로서 로딩 시간을 개선하는 것

참고 : https://dori-coding.tistory.com/entry/React-%EC%83%81%ED%83%9C%EA%B4%80%EB%A6%AC-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%96%B4%EB%96%A4%EA%B1%B8-%EC%8D%A8%EC%95%BC%ED%95%A0%EA%B9%8C


12. CSR과 SSR, SSG, ISR이란? 

 

https://guiyomi.tistory.com/125


13. React Hooks은 무엇인가요? 장점과 알고 있는 hook에 대해 설명하세요.

hook을 사용해 함수형 컴포넌트에서도 state와 생명주기를 다룰 수 있기에 클래스형 컴포넌트에서만 가능하던 상태관리를 더 손쉽게 할 수 있어 필요하다.

☑️ useState

상태를 관리합니다. [state이름, setter이름] 순으로 반환 받아서 사용합니다.

const [state, setState] = useState(initialState);

 

☑️ useEffect

화면에 렌더링이 완료된 후에 수행되며componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것

  • ❗️만약 화면을 다 그리기 이전에 동기화 되어야 하는 경우에는,useLayoutEffect를 활용하여 컴포넌트 렌더링 - useLayoutEffect 실행 - 화면 업데이트 순으로 effect를 실행시킬 수 있다.
useEffect(() => {}); // 렌더링 결과가 실제 돔에 반영된 후마다 호출
useEffect(() => {}, []); // 컴포넌트가 처음 나타날때 한 번 호출
useEffect(() => {}, [의존성1, 의존성2, ..]); // 조건부 effect 발생, 의존성 중 하나가 변경된다면 effect는 항상 재생성됩니다.

useEffect안에서의 return은 정리 함수(clean-up)를 사용하기위해 쓰여집니다.

  1. 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행
  2. 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect가 정리됩니다.

 

☑️ useContext

Context API를 통해 만들어진 Context에서 제공하는 Value를 가져올 수 있다

const value = useContext(MyContext);

컴포넌트에서 가장 가까운 <MyContext.Provider>가 갱신되면 이 Hook은 그 MyContext provider에게 전달된 가장 최신의 context value를 사용하여 렌더러를 트리거 합니다.

 

☑️ useReducer

useState의 대체 함수로 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있습니다.
컴포넌트 바깥에 로직을 작성할 수 도 있고, 심지어 다른 파일에 작성한 후 불러와서 사용할 수도 있습니다.
reducer란 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수 입니다.

const [state, dispatch] = useReducer(reducer, initialArg, init);

 

☑️ useRef

특정 DOM 선택할때 주로 쓰이며 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환합니다. 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지됩니다.

const refContainer = useRef(null);

 

☑️ useMemo

메모이제이션된 값을 반환합니다. 이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 한다. 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산 합니다. 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산합니다.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

 

☑️ useCallback

메모이제이션 된 콜백을 반환합니다. useMemo와 유사하게 이용되며 '함수'에 적용해줍니다.
의존성이 변경되었을때만 변경됩니다. 때문에 특정 함수를 새로 만들지 않고 재사용가능하게 합니다.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

참고 : 
https://velog.io/@goyou123/React-Hooks-%EC%B4%9D%EC%A0%95%EB%A6%AC


14. React의 라이프사이클에 대해 설명해주세요.

리액트는 컴포넌트 단위로 개발하게 되는데 이때 각 컴포넌트들은 라이프사이클 즉, 생명주기를 가지고 있다. 생명주기는 생성부터 시작하여 업데이트가 되기도 하며 마지막에는 소멸되는 과정을 거치게 된다. 클래스형 컴포넌트에선 주로 생명주기 메서드를 통해 라이프사이클에 따라 컴포넌트를 조작하는데 이와 달리 함수형 컴포넌트에선 생명주기 메서드가 따로 존재하지 않기 때문에 리액트 훅을 사용하여 생명주기 메서드와 비슷하게 동작하도록 구현한다.

🗨️마운트(생성)

✔️constructor : 컴포넌트가 만들어지면 가장 먼저 실행되는 메서드

✔️getDerivedStateFromProps : props로 받아온 것을 state에 넣을 때 사용하는 메서드이며, 컴포넌트가 처음 렌더링 되기 전에 호출되며 리렌더링 되기 전에도 항상 실행된다.

✔️render : 컴포넌트를 렌더링 하는 메서드

✔️componentDidMount : 컴포넌트의 첫 렌더링을 마친 후 호출되는 메서드이며, 이 메서드가 호출되는 시점에선 이미 컴포넌트가 화면에 출력된 상태이다. 이 단계에선 axios, fetch 등을 사용해 해당 컴포넌트에서 필요하는 데이터를 요청하는 등의 작업을 진행한다.

🗨️업데이트(갱신)

✔️getDerivedStateFromProps : 마운트 단계와 동일하며, 컴포넌트의 props나 state가 변경됐을 때도 호출되는 메서드

✔️shouldComponentUpdate : 컴포넌트의 리렌더링 여부를 결정하는 메서드로, React.memo와 역할이 비슷하다.

✔️render : 컴포넌트를 렌더링 하는 메서드

✔️getSnapshotBeforeUpdate : render에서 만들어진 결과가 브라우저에 실제 반영되기 직전에 호출되는 메서드. 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면 그 다음 발생하게 되는 componentDidUpdate 메서드에서 받아와 사용을 할 수 있다. 하나의 예시로 페이지에 새로운 내용이 추가됐을 때 사용자의 스크롤 위치를 새로운 내용이 아닌 기존 위치로 유지하기 위해 사용할 수 있다. 참고로 함수형 컴포넌트 개발 시 훅을 사용하여 getSnapshotBeforeUpdate 메소드를 대체할 수 없다.  벨로퍼트님 블로그 참고

✔️componentDidUpdate : 리렌더링을 마친 후 브라우저에 모든 변화가 나타난 후 호출되는 메서드. 세 번째 파라미터로 ✔️getSnapshotBeforeUpdate에서 반환한 값을 불러올 수 있다.

 

🗨️언마운트(제거)

✔️componentWillUnmount : 컴포넌트가 브라우저에서 사라지기 직전에 호출되는 메서드. 주로 DOM에 직접 등록했던 이벤트를 제거하는 등의 작업을 한다.

 

🗨️기타 

✔️componentDidCatch : 컴포넌트 렌더링 중 에러가 발생했을 경우 애플리케이션이 중단되지 않고 오류 화면을 보여주는 메서드.


15. 다국어 페이지는 어떤 방식으로 제공하나요?

 

 


16. CSS-in-JS에 대해 설명하세요.

웹을 구성하는데에 html 과 css가 순서대로 나오게 되었는데 웹의 규모가 커짐에따라서 둘만으로는 화면의 모든 스타일을 제어할 수 없는 상황에 직면하였습니다. 이를 해결하기 위해 나온 웹 애플리케이션 스타일 구성방식인 CSS-in-JS와 CSS-in-CSS가 그것입니다.

CSS-in-JS는 단어 그대로 자바스크립트 코드에서 CSS를 작성하는 방식을 말합니다. 

const textStyles = {
  color: white,
  backgroundColor: black
}

<p style={textStyles}>inline style!</p>

위와 같이 코드를 작성한 후 실행시키면 DOM의 상단에 style 태그를 추가하는 식으로 적용됩니다.

<p style="color: white; backgrond-color: black;">inline style!</p>

 1) 장점

  • 컴포넌트로 생각하기— 더이상 스타일시트의 묶음을 유지보수 할 필요가 없습니다. CSS-in-JS는 CSS 모델을 문서 레벨이 아니라 컴포넌트 레벨로 추상화합니다(모듈성).
  • CSS-in-JS는 JavaScript 환경을 최대한 활용하여 CSS를 향상시킵니다.
  • "진정한 분리 법칙"—스코프가 있는 선택자로는 충분하지 않습니다. CSS에는 명시적으로 정의 하지 않은 경우, 부모 요소에서 자동으로 상속되는 속성이 있습니다. jss-isolate 플러그인 덕분에 JSS 규칙은 부모 요소의 속성을 상속하지 않습니다.
  • 스코프가 있는 선택자—CSS는 하나의 전역 네임스페이스만 있습니다. 복잡한 애플리케이션 내에서 선택자 충돌을 피할 수 없습니다. BEM과 같은 네이밍 컨벤션은 한 프로젝트 내에서는 도움이 되지만, 서드파티 코드를 통합할 때는 도움이 되지 않습니다. JSS는 JSON으로 표현된 것을 CSS로 컴파일 할 때, 기본적으로 고유한 이름을 생성합니다.
  • 벤더 프리픽스—생성된 CSS 규칙은 자동적으로 벤더 프리픽스가 붙어있으므로 생각할 필요가 없습니다.
  • 코드 공유—JavaScript와 CSS사이에 상수와 함수를 쉽게 공유할 수 있습니다.
  • 현재 화면에 사용중인 스타일만 DOM에 있습니다(react-jss).
  • 죽은 코드 제거
  • CSS 유닛 테스트!

2) 단점 

  • 학습 곡선(Learning curve)
  • 새로운 의존성
  • 신규 팀원이 코드베이스에 적응하기 어렵게 만듭니다. 프론트엔드를 처음 접하는 사람들은 "더" 많은 것을 배워야합니다.
  • 현상 유지를 위한 도전 (꼭 단점은 아니다.)

 

참고 : 
https://d0gf00t.tistory.com/22

 

https://www.samsungsds.com/kr/insights/web_component.html


17. 함수형과 클래스형의 차이를 말해주세요.

React 컴포넌트를 만들때 클래스형 컴포넌트, 함수형 컴포넌트 2가지 방식이 있다 .
함수형 컴포넌트에서 리액트 훅을 지원해서 함수형 컴포넌트 사용을 권장한다.

클래스형 컴포넌트와 함수형 컴포넌트의 역할은 동일하다. 차이점이 있다면 클래스형 컴포넌트의 경우 state 기능 및 라이프 사이클 기능을 사용할 수 있으며 임의 메서드를 정의할 수 있다는 점이다. 그리고 render 함수가 꼭 있어야 하고, 그 안에서 보여 주어야 할 JSX를 반환해야 한다. 또한 과거의 prototype을 이용해서 구현하던 클래스 문법을 ES6 문법 부터는 class 문법을 사용하여 구현할 수도 있다.
반면 함수형 컴포넌트는 클래스형 컴포넌트보다 선언하기가 좀 더 편하고, 메모리 자원을 덜 사용한다는 장점이 있다. 과거에는 함수형 컴포넌트에서 state와 라이프사이클 API를 사용할 수 없다는 단점이 있었는데, 이러한 단점은 앞서 언급한 것처럼 리액트 훅이 도입되면서 해결되었다. 
함수형 컴포넌트든 클래스형 컴포넌트든 state를 직접 조작하는 것이 아닌, setState나 useState와 같은 세터 함수를 반드시 사용하여 조작해야 한다.

참고 : 

https://born-dev.tistory.com/27


18. 제어 컴포넌트와 비제어 컴포넌트의 차이에 대해 설명하세요.


19. 싱글톤 패턴과 옵저버 패턴 등 디자인 패턴에 대해 설명하세요.


20. Ref에 대해 설명하세요.

1) 정의

일반적으로 HTML에서 DOM요소에 이름을 달때는 id라는 고유값을 사용합니다.이처럼 리액트에서도 DOM요소에 이름표를 붙이는 방법이 있는데 이를 ref라고 부릅니다.
Ref는 일반 객체로 Ref를 console.log로 찍어보면 {current: null} current 프로퍼티 하나를 가진 객체가 나타나고 React는 이 객체를 통해 DOM에 직접적인 접근을 가능하게 해줍니다.

2) Ref를 사용해야 할 때

HTML에서 DOM요소에 이름을 달때 쓰이는 id는 유일해야 하기때문에 컴포넌트 재사용을 한다면 중복될 가능성이 많습니다. 반면에 Ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동한다.

- 포커스, 텍스트 선택영역 혹은 미디어의 재생을 관리할 때
- 애니메이션을 직접적으로 실행시킬 때
-서드 파티 DOM 라이브러리를 React와 같이 사용할 때.

선언적으로 해결될 수 있는 문제에서는 Ref사용을 지양해야 합니다.
예를 들어 Dialog컴포넌트에서 open()과 close() 메서드를 두는 대신 isOpen이라는 prop을 전달이 더 좋은 방법입니다.

참고 :

https://itprogramming119.tistory.com/entry/React-Ref%EB%9E%80

https://velog.io/@wnsaud9322/React%EC%9D%98%EB%AA%A8%EB%93%A0%EA%B2%83-Ref%EB%9E%80


 

21. 폴더 구조는 어떻게 구축하고 관리하나요?

폴더는 컴포넌트형식으로


22. SEO(검색성능)최적화 하는 방법

리액트는 SEO에 어려움이 있습니다. 그리하여 리액트로 만든 웹사이트는 non-SEO friendly site라고 불리기도 합니다. 리액트는 하나의 HTML파일이 있으며, 렌더링 되기 이전에는 빈 상태의 HTML만 있으므로 검색 엔진에 올라가기에 어려움이 있습니다. 이러한 단점을 해결할 수 있는 방법에는 SSR,meta-tag,Pre-rendering 등이 있습니다. 

1)  meta-tag 설정

리액트는 SPA이라, 각 검색로봇(크롤러)들이 리액트로 만들어진 사이트를 읽을 때 단 하나의 index.html 만을 읽게 됩니다. 이는 각각의 페이지에 대한 정보를 읽지 못한다는 단점이 있습니다. 이러한 단점을 극복하기 위해 메타태그를 사용하는 것인데 이것을 사용하여 크롤러가 읽기 쉽도록 어떤 페이지인지 설명해주어 사이트 정보 제공을 하는 것입니다.

참고 : https://velog.io/@miyoni/noSSRyesSEO

2) Pre-rendering 설정

사전 렌더링은 웹 크롤러가 볼 수 있도록 페이지의 모든 요소를 사전로드하는 프로세스를 의미합니다. prerender 서비스는 페이지 요청을 낚아채어 사용자가 크롤러인지 여부를 확인하여 크롤러인 경우 캐시 된 버전의 페이지를 전달하여 줍니다. 반대로 크롤러가 아니라면 일반적인 페이지를 전달해주게 되죠.
즉, 크롤러를 위한 최적화 작업을 하는 것이 prerender의 핵심이라고 할 수 있습니다.

3) SSR

참고 : https://velog.io/@miyoni/noSSRyesSEO


23. 불변성이란 무엇이고, 리액트에서 불변성을 지켜야 하는 이유와, 어떻게 지킬 수 있는지 설명해주세요.

 1)정의

 불변성이란 값이나 상태를 변경할 수 없는 것으로 메모리 영역에서 값이 변하지 않는다 라는 의미입니다.

2) 왜 리액트에서 불변성을 지켜야하나?

리액트에서 불변성을 지켜주는 이유는 리액트가 상태 업데이트를 하는 원리 때문입니다. 리액트는 상태값을 업데이트 할 때 얕은 비교를 수행합니다. 즉 배열이나 객체의 속성 하나하나를 비교하는게 아니라 이전 참조값과 현재 참조값만을 비교하여 상태 변화를 감지합니다. 이런 이유로 배열이나 객체를 업데이트 할때 setState([...state, newState]), setState({...state, [key]: value}) 이런식으로 새로운 참조값을 가진 배열이나 객체를 생성하는 것입니다. 불변성을 지킴으로써 리액트는 상태변화를 감지할 수 있습니다.

불변성을 지켜줌으로써 얻게 되는 또 다른 이점은 바로 사이드 이펙트를 방지하는 것입니다. 즉 외부에 존재하는 원본데이터를 직접 수정하지 않고, 원본데이터의 복사본을 만들어서 값을 사용하기에 예상치 못한 오류를 사전에 방지할 수 있습니다. 다시 반대로 생각해보면 외부의 값을 함부로 변경할 수 있는 것은 위험한 일입니다. 만약 다른 어떤 곳에서 원본데이터를 사용하고 있다고 하면 어플리케이션 어딘가에서 사이드 이펙트가 일어날 가능성이 있기 때문입니다. 결국 리액트는 불변성을 지킴으로 인해 효과적인 상태 업데이트와 사이드 이펙트를 방지하는 이점들을 얻고 있습니다.

📍 효율적인 상태업데이트 (얕은 비교 수행)

얕은 비교란 객체의 프로퍼티를 하나하나 다 비교하지 않고, 객체의 참조 주소값만 변경되었는지 확인합니다. 얕은 비교는 계산 리소스를 줄여주기 때문에 리액트는 효율적으로 상태를 업데이트 할 수 있습니다.

📍 사이드 이펙트 방지 및 프로그래밍 구조의 단순성.

원시타입은 애시당초 불변성 특징을 가지고 있지만 참조타입인 객체나 배열의 경우 값을 변경할 때 원본데이터가 변경될 여지가 있습니다. (불변성이 지켜지지 않을 수 있습니다). 이렇게 원본 데이터가 변경될 경우, 이 원본데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있습니다. 프로그래밍의 복잡도도 올라갑니다. 따라서 불변성을 지켜주면 사이드 이펙트를 방지하고 프로그래밍의 구조를 단순하게 유지할 수 있습니다.

3) 어떻게 불변성을 지키는가?

spread operator, map, filter, slice, reduce 등등 새로운 배열을 반환하는 메소드들을 활용하면 됩니다.
setState를 이용할 때 원시타입 경우에는 값을 바로 넣어주어도 되지만 참조타입인 경우에는 새로운 객체나 배열을 생성한 후 값을 넣어주어야 합니다. 

*정리
- 불변성이란 메모리 영역의 값을 변경할 수 없는 것이다.
- 리액트는 불변성을 지켜줌으로써 효율적인 상태업데이트를 한다.
- 리액트는 불변성을 지켜줌으로써 사이드 이펙트를 사전 방지하고 프로그래밍의 구조를 단순하게 유지한다.
- 불변성을 가진 원시타입과 달리 참조타입의 경우에는 의도적으로 불변성을 지켜주어야한다. 이 때 새로운 주소 값을 가진 객체를 생성하여 상태를 업데이트 해준다. spread operator, map, filter, slice, reduce 메소드들을 활용한다.
* splice는 원본데이터를 변경함

 

참고 : https://hsp0418.tistory.com/171

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함