Thief of Wealth
article thumbnail

 

CRA

CRA는 create react app의 약자로써, React를 시작할 수 있는 초기 환경을 모두 셋팅해준다.

npx create-react-app my-app 명령어로 실행할 수 있다.

 

* CRA에는 기본적으로 모든 패키지들이 dependencies에 들어가있다. 이유는?

CRA를 사용해서 그 위에 코드를 작성했을 뿐인데, 리뷰로 "이 라이브러리는 왜 dev에 없는가"에 대한 리뷰를 많이 받은것 같다. 그만큼 package.json이 가지는 의미가 중요하다는 거겠지.

 

그런데 우리는 CRA를 썼을뿐, package.json에 있는 코드를 한치의 의심도 없이 사용했다. 그 만큼 신뢰성있는 라이브러리니까!

그리고 이 설계는 Dan Abramov가 의도적으로 설계한 것이다.

 

https://github.com/facebook/create-react-app/issues/6180

 

댄이 말하길, Node앱이면 dependencies, devDependencies를 구별하는게 의미가 있는데, CRA의 경우, 결과물 자체가 static bundle이고, build시에만 모든 package를 이용하기 때문에 굳이 따지마면 모두 devDependencies인데, 일부 배포 스크립트의 오작동을 막기위해서 dependencies에 모두다 넣었다고 한다.

 

dependencies, devDependencies 차이를 모르겠다면?

=> https://zereight.tistory.com/282

 

npx

npm package runner이다.

npx를 사용하면, npm 레지스트리에서 해당 패키지를 찾아서 바로 이용할 수 있다. (최신버전으로 이용가능)

즉, npm 레지스트리에 올라가 있는 패키지를 쉽게 설치하고 관리할 수 있도록 도와주는 도구이다. (모든 종류의 nodejs 기반의 파일들을 간단하게 설치하고 실행할 수 있게 도와줌)

다운 받지 않으므로, 디스크 공간을 낭비하지 않는다.

 

* 왜 npx가 등장했을까

과거 npm으로 패키지 설치시에는 2가지 케이스가 있었다.

1. 전역으로 패키지 설치

2. 특정 프로젝트에만 설치

=> 이렇게 전역/로컬에 설치된채 의존성 라이브러리들이 관리되면, 특정 패키지가 업데이트 될 시, 전역으로 관리되고 있는 패키지랑 로컬로 관리되고 있는 패키지랑 따로 업데이트 해야함.

근데 npx를 사용함으로써, 설치/실행/제거를 할 필요 없이 일회성으로 원하는 패키지를 레지스트리에 접근해서 실행시키고 설치해버릴 수 있다. 레지스트리에서 가장 최신의 버전을 사용하므로 버전문제도 없당.

 

* 언제 npx를 사용해야 할까

- npm run 스크립트를 사용하지 않고 ,로컬에 설치된 패키지를 사용할 경우

- 일회성 명령으로 패키지를 실행할 경우

- gist-based 스크립트를 실행할 경우

- 특정 노드 버전의 스크립트를 실행할 경우

참고: https://webruden.tistory.com/275

 

Emotion

styled-component를 사용하는 도중에 알게된 라이브러리로, styled-component와 같은 기능을 모두 제공하고 있으며, 용량도 가볍고, 성능이 좋다고 알려져있다.

또한, css prop기능을 제공하고, SSR시 서버작업이 필요없다고 한다.

 

CSS-in-JS

말 그대로 js에서 스타일 관련 요소를 사용할 수 있는 방법이다.

JS변수로 선언된 CSS내용을 실제 StyleSheet로 만들고, 랜덤 문자열로 이루어진 클래스명을 만들어 컴포넌트끼리 확실하게 분리될 수 있게 한다.

이게 무조건 좋고, 무조건 사용해야하는 것은 아니다.

그냥 내가 개발하는데 편하고 도움이 되면 사용하면 된다! (너무 맹신하지는 말자)

 

장점

1. CSS보다 더 강력한 추상화이다. (https://oleg008.medium.com/jss-is-css-d7d41400b635)

(CSS세상과 JS세상을 합쳤다~라는 내용)

2. 스타일을 선언적으로 유지보수 가능한 방식으로 설명할 수 있다.

3. 성능이 좋다. (https://cssinjs.org/performance/?v=v10.6.0)

=> 체감은 못했다.

4. 컴포넌트로 생각할 수 있다.

=> 스타일 시트의 묶음을 유지보수할 필요가 없다! 컴포넌트 레벨에서 스타일을 생각할 수 있다.

5. dead code가 제거된다.

=> 안쓰는 코드들 자동으로 제거! (근데 css도 할 수 있는 방법이 있는 것으로 들었당)

6. css를 유닛테스트할 수 있다. (해보진 않았다.)

=> expect(element).to.have.height(30px'); 요로코롬 테스트 가능

7. 스코프

=> 브라우저 렌더링 과정에서 CSS는 js 스크립트와는 상관없이 과정이 진행되기 때문에, 최근의 컴포넌트 형식의 개발 방법에 맞지 않는다. (컴포넌트는 확실하게 스코프가 나누어지는데, StyleSheet는 그에 따르지 않았기 때문에 그에 따른 괴리가 있었음)

 

단점

1. StyleSheet의 스크립트 변환은 그만큼 HTML 파싱에 사용되는 스크립트 코드가 늘어남을 의미한다.

=> 브라우저 렌더링이 StyleSheet와 Script로 나누어 병렬처리되던것에 비해서, 오직 Script로 이루어짐에 따라서 속도가 느려짐이 있다. 

2. CSS가 먼저 제공되어 렌더링 시 형태가 잡혀있는 기존 방식에 비해 컴포넌트가 렌더링되며 형태가 잡히기 때문에, FOUC되어 사용자 경험을 저하시킨다. (아직 경험은 못해봄, next.js에서 해결방법이 있다고 함[https://jthcast.dev/posts/is-css-in-js-the-best/])

=> FOUC(Flash of unstyled content)

스타일 시트가 적용되기 전 마크업 된 그대로의 모습이 잠깐 보이는 현상

https://jthcast.dev/01c24d9136a637e1d7f3ed012c50b58b/css-in-js.mp4

 

 

Context API

Context API는 주로 어플의 전역 데이터관리가 필요할 때 사용된다.

컴포넌트는 기본적으로 계층화되어 있는데, 상위 컴포넌트의 상태와 관련된 하위 컴포넌트에서 사용하려면 prop으로 해당 함수를 전달해주어야만 한다.

그런데 그 하위 컴포넌트까지 prop으로 전달되기 위한 과정에서, 중간 컴포넌트가 해당 prop을 사용하지 않는다면 중간에 있는 컴포넌트들은 자신이 사용하지도 않을 prop을 받아서 넘겨주는 역할을 하게된다.

그렇게되면 유지보수성도 낮아지고, 컴포넌트 본연의 기능이아닌 prop을 패싱하는 역할까지 담당하게 되어 재사용성도 낮아지게 된다.

그래서 쓰고싶은 상태관련 로직을 쓰고 싶은 컴포넌트에서 사용하게 하기 위해 전역 상태관리 기법이 나오게 되었다.

 

그 중의 하나가 Context API이다.

 

redux, mobx같은 전역 상태 관리 라이브러리가 있으나, 간단한 작업에 한해서는 이를 위한 설정 코드를 작성하는 것이 번거로울 수 있다.

(mobx의 경우, inject, observer 코드가 컴포넌트 코드에 붙어서 가독성을 떨어뜨릴 수 있고, redux는 하나의 동작을 위해서 다수의 Action 등의 코드가 필요하다.)

 

그래서 Context API를 사용하면 비교적 간단하게 전역 상태관리를 할 수 있다.

 

하지만 Context API의 단점으로, Consumer와 Provider를 분리할 수 없기에 재사용성이 좀 떨어지고 ,같은 context를 공유하는 컴포넌트들은 어떤 context의 값이 업데이트 될때마다 모두 렌더링이 이루어진다는 단점이 있다. (https://medium.com/react-native-seoul/context-api-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94%EA%B0%80-9ef90247713)

 

A만 바꾸었는데, B까지 바뀌어버리는 리소스낭비가 일어나는 것이다.

 

해결 방법으로는

1. context를 작게 작게 관리하기

2. React.memo 사용

3. useMemo 사용

 

2,3은 최적화를 하기위한 비용 및, 가독성 면에서 좋지 않다.

보통 1번을 많이 사용한다고 한다.

 

 

Class Component, Function Component

https://ui.toast.com/weekly-pick/ko_20200922

https://zereight.tistory.com/956

나는 위 포스팅에 언급된 이유 때문에, 클래스 컴포넌트의 메리트가 크게 느껴지지 않는다고 생각한다. (뇌피셜)

오히려 클래스로 작성함으로써, props의 불변을 위한 추가적인 오버헤드가 들어간다고 생각된다.

 

 

인라인 함수는 지양되어야 하는가

https://github.com/woowacourse/react-lotto/discussions/63

 

인라인 함수는 React가 렌더링 될 때 정의되는 함수를 말한다.

render내에 함수를 바인딩하거나 화살표함수를 사용하는 것을 흔히들 render가 호출될때마다 계속해서 정의가 되기 때문에 성능에 좋지않다라고 알려져 있다.

 

일단 섣부른 성능 최적화는 어디서든 지양되는 말이다. 

https://benediktmeurer.de/2015/12/25/a-new-approach-to-function-prototype-bind/

위 링크를 보면 Function.prototype.bind의 성능문제는 고쳐졌고, 화살표 함수는 babel을 통해 순수함수로 트랜스파일링되어서 느리지 않다고 한다.

 

그냥 "이 코드는 느릴 게 분명해"라고 생각하는 것은 지양해야한다.

자연스럽게 코딩하고, 성능을 측정해서 그 때 성능문제가 있었다면 그 때 고쳐라.

그러니까 인라인 함수가 실제로 성능이 좋지 않다는 확실한 증거가 나올때까지는 괜히 부자연스러운 코딩을 할 필요가 없다. 이말이다~

 

PropTypes를 사용한 이유

 

https://ko.reactjs.org/docs/static-type-checking.html

 

정적타입을 체크하는 방법으로는 다음과 같은 3가지가 있을 수 있다.

 

1. Flow

js를 위한 정적 타입 체커이며, 페이스북에서 만들었으며, react와 함께 사용된다.

 

장점: 타입체크가 가능하다. react와 호환성이 높은것 같다.

단점: 상대적으로 유명하지 않아서 정보를 얻기가 쉽지 않다. 주석을 작성해야 한다.

 

2. Typescript

마이크로소프트가 개발한 프로그래밍 언어이며, js의 슈퍼셋이고 자체 컴파일러를 가지고 있다.

타입언어라서 앱 실행 전, 즉 컴파일 환경에서 빌드 에러를 잡을 수 있다.

 

타입을 지정해주었으므로 안정성이 확보된다. (타입에 대한 예외 처리코드를 추가 안해주어도 됨)

컴파일 과정에서 타입 검사를 통과하여 안정성이 확보되면 타입을 제거하고 최종적으로 JS코드를 생성한다.

 

또한, JS엔진의 최적화를 돕는다.

기본적으로 JS는 hot function(자주 호출되는 함수)에 대한 최적화를 수행하는데,

var add = (a,b) => a+b; 라는 코드가 있다고 가정해보자.

위 함수가 자주 호출되며, a,b가 계속 정수형으로 들어오는 경우 최적화를 수행하는데, 갑자기 정수형이 아닌 string같은 다른 타입이 들어오면 최적화가 해제된다.

근데 TS는 타입이 고정되어 있으므로, 최적화 해제가 발생할 상황이 적다.

 

3. PropTypes

타입체크가 가능하며 타입스크립트와 달리 런타임에서 타입을 체크한다.

이녀석도 JS엔진의 최적화를 도울것같다. (타입을 정해놓으므로!)

 

규모가 큰 프로젝트일 경우, 실행을 하는 비용이 더 크다고 생각하기 때문에, 간단한 프로젝트라면 상관없겠지만 규모가 점점 커질 수록 TS로 작성하는 것이 효율적일것 같다는 판단이 든다.

물론 TS를 잘 사용하기도 어렵고 러닝커브도 좀 있는 편이고, 개발 단계에서 컴퓨터가 힘들어하긴 하지만 ㅎㅎ

 

// ? 그런데 proptype은 api call같이 외부 데이터를 담당하는데 유리하다고 한다. (여러곳에서 강조되는것 같다.) 직접 실행해야만 알 수 있어서 그런가? api 명세만 있다면 타입스크립트도 충분히 가능할텐데 흠..

PropTypes are important when you are testing or debugging components that work with external data, e.g. API calls.(https://dev.to/tschaka1904/react-proptypes-vs-typescript-any-experience--bm9)

 

서비스 레이어, 비즈니스 레이어

고냥 모든 레이어에 대한 정의를 내려보자

 

1. Presentation Layer

=> UI Layer이다.

UI가 변경되면 다 같이 변경되는 layer이다. (View?)

 

2. Service Layer

=> 도메인 모델을 묶어서 현재 어플에서 사용가능한 핵심 작업 집합을 설정하는 계층이다.

- 핵심 로직은 비즈니스 레이어에, 서비스 레이어는 얇게 유지하는게 좋다고  한다.

- 여러 비즈니스 로직들을 의미 있는 수준으로 묶어서 제공하는 것이 서비스 레이어의 역할

 

3. Business Layer

=> data와 그와 관련된 비즈니스 로직(메서드)를 가지고 있는 객체

 

4. Persistence Layer

=> 요청/응답 데이터를 비즈니스 로직에서 필요한 데이터로 가공해서 변환하여 비즈니스 레이어로 넘겨주는 역할

 

* 비즈니스 로직이란?

=> 데이터와 인터페이스가 상호작용하는 로직을 통틀어서 비즈니스 로직이라고 함

 

 

key값에 index를 써도 되는 경우와 쓰지 말아야 하는 경우

 

react에서는 key값을 지정함으로써 형제레벨의 엘리먼트끼리 구별할 수 있게 도와줍니다.

구별하면 react가 어떤 항목을 변경, 추가, 삭제할지 식별할 수 있게 됩니다.

리렌더링될때 같은 키값을 지닌 엘리먼트가 있으면 굳이 그것을 렌더링할 필요가 없기 때문입니다.

 

(https://medium.com/sjk5766/react-%EB%B0%B0%EC%97%B4%EC%9D%98-index%EB%A5%BC-key%EB%A1%9C-%EC%93%B0%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3ce48b3a18fb)

그 과정에서 key값을 유니크하게 사용해야하는데, 보통 index를 사용하는 것을 권하지는 않습니다.

그 이유는 렌더링하려는 엘리먼트 배열의 순서가 바뀌는 경우, index에 맵핑되는 엘리먼트가 달라지므로, 렌더링 결과가 예상한 것과 달라질 수 있기 때문입니다.

 

그럼 index를 절대로 사용하면 안되느냐? 그것도 아닙니다.

1. 배열과 각 요소가 변하지 않고

2. 데이터 내부에 id로 쓸만한 유니크한 값이 없고

3. 데이터가 절대 reordered, filtered 되지 않는 경우

에 사용할 수 있습니다!

 

그러니까 데이터가 절대로 변하지 않는 경우에 어쩔 수 없이 쓰라는 소리!

 

리액트의 재조정이란

 

react는 state나 props가 갱신되면 render를 통해 새로운 React 엘리먼트를 반환합니다.

shouldComponentUpdate를 사용해서 불필요한 rerender를 최소화할 수도 있습니다.

아무튼, 그렇게 만들어진 엘리먼트를 가장 효과적으로 실제 DOM에 동기화하는 단계를 재조정이라고 합니다. (Vdom및 비교 알고리즘 사용)

 

원리는 다음 공식 문서를 참조하자. (key에 대한 언급까지)

https://ko.reactjs.org/docs/reconciliation.html

 

ref를 사용하는 이유

ref는 공식문서(https://ko.reactjs.org/docs/refs-and-the-dom.html)에서 설명된 내용을 언급하자면,

"ref는 render 메서드에서 생성된 DOM노드나 react 엘리먼트에 접근하는 방법을 제공합니다."

라고 언급되어 있다.

 

일반적으로

1. 포커스, 텍스트 선택영역, 미디어의 재생관리

2. 애니메이션 직접 실행

3. 서드 파티 DOM 라이브러리(d3.js같은것)를 React처럼 사용할때 https://clearwater92.tistory.com/31

사용한다고 한다.

 

근데 Dan의 블로그에 따르면 (https://overreacted.io/ko/how-are-function-components-different-from-classes/)

위에서 설명한것은  "DOM refs"이고 리액트의 ref은 좀 더 포괄적인 기능을 제공한다고 한다.

즉, 무언가를 넣을 수 있는 박스라고 생각해도 좋다고 한다.

 

내 생각에는 DOM 요소의 상태든, 값이든 특정 시점을 기억하고 싶을 때 사용하면 될 것 같다.

 

state는 왜 끌어올려야 하나요

리액트에서 상태를 공유하는 것은 상태를 상태가 필요한 컴포넌트들의 가장 가까운 공통 조상으로 이동시킴으로써 공유할 수 있다.

그러면 source of truth(유일한 원천)을 지킬 수 있게되고 일관성있는 값을 보장시킬 수 있다. (싱크가 맞다.)

(react는 top-down data flow이기 때문에 변화하는 데이터(상태)에 대해 한 하나의 원천만 있는 것이 바람직함)

 

조건부 렌더링

대부분 &&나 삼항연산자로 jsx내에서 처리해줬다.

하지만 jsx내에서 이런 조건부 연산이 많이 들어가게 되면 가독성이 많이 떨어지게 된다.

 

배민에서 사용하는 패턴중 하나인 Maybe라는 컴포넌트를 사용해서 가독성을 높일 수도 있다.

https://sujin-park.github.io/study/2020-09-30-React-TypeScript7/

 

&&를 쓸때 유의 사항

React 탄생 배경은 뭘까요?

https://overreacted.io/ko/react-as-a-ui-runtime/

http://wiki.sys4u.co.kr/pages/viewpage.action?pageId=8553032

 

React 개발사인 페이스북은 원래 자사 제품들에 PHP를 사용했었다. (사랑했다.)

PHP를 C++로 컴파일한 후, 빌드하는 프로젝트를 진행하여 PHP 자체의 성능을 개선하기도 했다.

2010년에 발표한 XHP역시 PHP언어의 문법 구조를 바꾸려는 노력중 하나 였다.

XHP는 HTML 출력이 많은 PHP 언어 특성에 맞추어 XML, HTML을 더 빠르고 편하게 출력하는데 목적이 있었다.

이 아이디어를 브라우저로 옮기고자 했고, 이것이 바로 React가 되었다.

JSX라는 js확장 문법을 통해서 XHP와 유사한 기능을 React라는 이름으로 제공하게 된것이다. <= 탄생배경

 

근데 왜 그랬을까?

React가 나오기 전까지는 앵귤러, 백본, 녹아웃, 엠버 등 수많은 프론트엔드 프레임워크가 존재했다.

이들은 MVC, MVVM, MVW등의 패턴들로 이루어져있고 공통적으로 Model이라는 개념을 가지고 있었다.

이러한 모델들은 양방향 바인딩을 통해서 모델에 있는 값이 변하면 뷰에서도 변화를 시켜주었다.

 

근데, 변화하는게 상당히 복잡한 작업이었다. 변화를 일으킬때 어떤 DOM에서 가져와서 어떤 방식으로 View를 업데이트 해줄지에 대한 로직을 다 정해주어야 했다.

 

그래서 페이스북은 생각했다.

"mutation을 하지말자. 대신에 데이터가 바뀌면 View를 날려버리고 새로 만들어버리자."

 

그러면 변화를 만드는 복잡한 작업없이 간단하게 화면이 변경될 것이다.

하지만 계속 그때 그때 새로운 뷰를 만들어내야 하기 때문에, 성능적인 문제가 발생할 것이다.

이를 해결하기 위해 나온것이 바로 Virtual DOM이다.

 

 

React의 장점과 단점을 설명해주세요.

장점 (공감가는 것만 넣었다.)

1. 개발 생태계가 넓다.

: 많은 레퍼런스, 툴, 확장 라이브러리를 가지고 있고, 신뢰성있는 조직인 페이스북에서 지속적인 유지보수를 하고 있다.

 

2. 배우기 쉽다.

: React는 구문이 단순하기 때문에 배우기 쉬운 편이다.

 

3. Virtual DOM으로 인한 빠른 렌더링

 

4. 단방향 데이터 바인딩

: 하위 요소가 상위 부모 데이터에 영향을 미치지 않는다.

 

5. 가볍다.

: 데이터 모델링, 라이팅 등의 기능이 없으므로 상대적으로 가볍다. (체감이 안되는 특성, react밖에 안해봐서 ㅎㅎ)

 

6. 다른 프레임워크나 라이브러리와 혼용이 쉽다.

: 이미 개발이 완료된 서비스에도 적용이 쉽다.

 

7. 반응형 렌더링

: 개발자가 컴포넌트의 모양과 동작을 선언식으로 정의하면, react가 데이터 변경을 감지해서 인터페이스를 다시 렌더링한다.

 

8. 서버사이드 렌더링, 클라이언트 사이드 렌더링을 모두 지원하여 브라우저측의 초기 렌더링 딜레이를 줄이고 SEO 호환도 가능해짐

 

9. 컴포넌트의 가독성이 매우 높고 간단해서 유지보수가 쉽고, UI 수정 및 재사용이 용이하다.

 

 

단점

1. View 이외의 기능은 서드파티 라이브러리를 사용하거나 직접 구현해야 한다.

2. IE8 이하를 지원하지 않는다. (버전을 바꾸면 가능하긴하다.)

 

 

 

공식문서에 언급된 React의 특징은 뭘까요?

React는 사용자 인터페이스를 만들기 위한 Javascript 라이브러리이다.

 

선언형

=> 선언형을 뷰를 사용함으로써 코드를 가독성 있고, 예측가능하고, 디버그하기 쉽게 만들어주었다. 상호작용이 많은 UI를 만들 때 생기는 어려움을 많이 줄여주었다.

 

컴포넌트 기반

=> 스스로 상태를 관리하는 캡슐화된 컴포넌트를 만들어서 그것을 조합하여 복잡한 UI를 만들 수 있다.

 

한 번 배워서 어디서나 사용하기

=> 기술 스택의 나머지 부분에는 관여하지 않으므로, 기존 코드를 다시 작성하지 않고도 React의 새로운 기능을 이용해서 개발할 수 있다.

React Native를 이용하면 React 코드로 모바일 앱을 개발할 수 있다.

 

 

라이브러리 vs 프레임워크

http://wiki.sys4u.co.kr/pages/viewpage.action?pageId=8553032

 

 

Virtual DOM에 대해서 설명해주세요.

 

https://velopert.com/3236

 

일반적인 브라우저 렌더링 과정

1. DOM Tree 생성

: 브라우저가 HTML을 전달받으면 브라우저의 렌더 엔진이 이를 파싱하고 DOM 노드로 이루어진 트리를 만든다.

 

2. Render Tree 생성

: 외부 CSS파일과 각 엘리먼트의 inline 스타일을 파싱한다.

스타일 정보를 사용하여 DOM 트리에 따라 새로운 트리인 렌더트리를 만드는 것이다.

(DOM트리의 모든 노드들은 attach라는 메서드가 있고 스타일 정보를 계산해서 객체형태로 반환된다. 이 과정은 동기적이다.)

 

3. Layout (reflow)

: 렌더 트리가 다 만들어지고 나면, 레이아웃 과정을 거친다.

각 노드들에 스크린의 좌표가 주어지고, 정확히 어디에 나타나야 할 지 위치가 주어진다.

 

4. Painting

: 렌더링 된 요소들에 색을 입히는 과정이다.

트리의 각 노드들을 거쳐가면서 paint 메서드를 호출한다.

 

즉, DOM을 조작하면 위 작업이 반복되어 일어난다.

복잡한 SPA에서는 DOM 조작이 많이 발생하는데 그 만큼 위 연산을 브라우저가 감당해내야 한다는 뜻이다.

 

이게 Virtual DOM이 나온 이유이다. 

view에 변화가 있었다면, 실제 DOM에 적용되기전에 가상의 DOM에 먼저 적용시키고 , 최종적인 결과를 실제 DOM으로 전달해주는 것이다.

Virtual DOM은 렌더링이 되는 것이 아니고 메모리상에 존재하는 것이기 때문에 연산비용이 적고 빠르다!

 

그렇게 최종적인 변화를 딱 한번만 실제 DOM에 던져주게 되니까, 모든 변화를 하나로 묶는게되는거고, 레이아웃 계산과 리렌더링 규모는 커지겠지만, 한 번만하니까 연산 횟수가 줄어드는 것!

 

 

React는 DOM 보다 빠른가??

https://velopert.com/3236

 

Dan이 말하길, React가 DOM보다 빠르다는 것은 잘못된 사실이다.

사실은 유지보수 가능한 어플리케이션을 만드는 것을 도와주고 대부분의 경우에 충분히 빠른것 뿐이다.

리액트를 써도 최적화작업이 제대로 이루어지지 않으면 오히려 성능이 DOM보다 나쁘다.

or

정보 제공만 하는 웹페이지라면 인터렉션이 발생하지 않기 때문에, 일반 DOM의 성능이 더 좋게 나올 수 있다.

 

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

 

 

 

명령형 프로그래밍 vs 선언형 프로그래밍

명령형 프로그래밍은 무엇을 어떻게 할지에 가깝고, (HOW)

선언형 프로그래밍은 무엇을 할것인지에 가깝다. (WHAT)

 

예를 들면, 

명령형: 잠실역 9번 출구로 나와서 우회전 하여 직진하다가, 스타벅스 건물이 보이면 우회전 하여 직진하다가, 교통공원이 나오면 우회전하여 루터회관 건물로 진입하면 됩니다.

선언형: 서울특별시 송파구 신천동 7-20로 가세요.

 

다른 비유로 들자면, 1종 차량(수동 스틱)과 2종 차량(오토 스틱) 느낌이다.

 

위 예제를 보면 알 수 있듯이, 선언형 방식이 제대로 동작하려면 명령형 방식이 추상화된 부분이 필요하다.

좀 더 이해를 돕기위해서 프로그래밍 예제를 들자면

https://boxfoxs.tistory.com/430

위와 같은 코드가 명령형이라고 할 수 있다.

 

1. 코드가 "어떻게"를 위주로 설명하고 있다.

2. 모두 상태의 일부를 변경하고 있다. result, dom

3. 가독성이 좋지 않다. (무슨일이 일어나고 있는지 한 번에 이해하기 어렵다.)

4. 컨텍스트에 의존하는 경우가 많아서 재사용하기 어려운 경우가 많다.

 

그럼 선언형으로 바꿔보자

https://boxfoxs.tistory.com/430

1. "어떻게"가 아닌 "무엇"이 일어나는지 설명하고 있다.

2. 상태를 변경하지 않는다.

3. 한눈에 읽을 수 있어 가독성이 높다.

4. 코드들이 달성하고자 하는 것에 대해 나열되있기만해서 동일한 코드를 재사용하기 쉽다.

 

 

왜 React는 #root에 렌더링하는가? body에 하면 안됨?

https://github.com/facebook/create-react-app/issues/1568

 

 

If you render directly into document.body, you risk collisions with scripts that do something with it (e.g. Google Font Loader or third party browser extensions) which produce very weird and hard to debug errors in production. React warns you if you attempt to do this.

Dan이 말하길,

document.body에 렌더링하게 되면, React에서 구글 폰트 로더나 서드파티 브라우저 확장프로그램같은 script와 충돌할 수 있다고 경고를 낸다고 한다. (경험은 못해봤다 ㅎㅎ)

충돌도 날 수 있고, 디버깅하기도 어려워서 별도의 root라는 공간을 만든 듯 하다.

 

 

CRA로 생성했을때 manifest 파일의 역할은 무엇인가?

https://ljh86029926.gitbook.io/coding-apple-react/1/where-is-html

https://velog.io/@jch9537/React-manifest.json

 

manifest.json은 CRA로 앱을 생성하게 되면 기본적으로 들어있는 JSON파일이다.

앱에 대한 정보를 담고 있다. (앱의 이름은 무엇인지, 아이콘은 어떤것인지 등등)

 

 

react와 react-dom의 차이는 무엇인가?

react: react가 동작하는 핵심 코드가 들어있는 라이브러리

react-dom: react코드를 웹에 붙여주는 역할을 하는 라이브러리

 

 

JSX는 표현식인가요?

https://ko.reactjs.org/docs/introducing-jsx.html

 

yes

컴파일이 끝나면 JSX 표현식이 정규 js함수호출되고 js객체로 인식된다.

 

react는 왜 setState같은 특정한 함수를 사용하여 상태를 변경하는가

https://overreacted.io/ko/how-does-setstate-know-what-to-do/

 

하지만 오늘 보았다시피, 기본 클라스 setState()실행은 오해였습니다. 현재 렌더러를 부르는것 외에는 아무것도 하지 않습니다. 그리고 useState 후크는 이것과 똑같은 일을 합니다.

 

https://ko.reactjs.org/docs/state-and-lifecycle.html

 

state를 직접 수정하게 되면, 리렌더링이 발생하지 않아서 변한 상태값으로 인한 view 변경이 이루어지지 않기 때문이다.

 

setState()는 비동기적으로 동작하나요?

https://ko.reactjs.org/docs/state-and-lifecycle.html

State 업데이트는 비동기적일 수도 있습니다.

React는 성능을 위해서 여러 setState 호출을 단일 업데이트로 한꺼번에 처리할 수 있다

 

 

 

리액트에서의 불변성에 대해 설명해주세요.

https://velopert.com/3640

https://jhonnywest.tistory.com/112

https://meetup.toast.com/posts/110

https://estaid.dev/reasons-to-maintain-immutability-with-react/

https://ljs0705.medium.com/react-state%EA%B0%80-%EB%B6%88%EB%B3%80%EC%9D%B4%EC%96%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-ec2bf09c1021

react는 리렌더링을 한다. 실제 DOM에 반영되기 전에 Virtual DOM에 리렌더링을 하고 실제 DOM에는 최종적으로 달라진 영역만 반영이 된다.

이때 Virtual DOM의 리렌더링도 아낄 수 있다면 아끼는게 좋겠다는 생각이 들것이다!

 

shouldComponentUpdate 같은 lifecycle api를 사용하여 컴포넌트를 업데이트할 것인지 정해줌으로써 최적화를 할 수 있다.

이때의 로직은 현재의 prop의 상태값과 nextProp의 상태값을 비교함으로써 업데이트할지 말지를 정할 수 있는데 

 

불변성이 지켜지지 않는경우, 상태값이 복잡하고 depth가 크다면, 0번 인덱스부터 모든 deptch를 순회하여 값이 달라진 부분이 있는지 검증해야할 것이지만,

불변성이 지켜지는 변수로 관리한다면 변수의 레퍼런스만 비교하면된다! (참조타입인 경우겠죠!)

 

또한 불변성을 지키면 의도치 않는 수정에 의한 side effect을 막을 수도 있다.

 

그렇기에 react에서는 상태의 불변성을 강조한다. (redux의 reducer도 마찬가지이다.)

 

* 그러면 불변성을 유지하는게 항상 성능에 유리한가요?

=> 불변성을 유지한다는 것은 새로운 변수를 만드는 것이다. 이것도 결국엔 비용이기 때문에 게임처럼 실시간으로 캐릭터의 좌표가 변경되는 경우에는 오히려 비효율적일 수도 있다. 참고만 하자.

함수 컴포넌트도 어쨌든 함수이다. 그럼 함수를 직접 호출하면되는데 굳이 JSX문법을 써서 React가 컴포넌트를 호출하게 하는 이유는 무엇인가?

https://overreacted.io/ko/react-as-a-ui-runtime/

제어의 역전때문이다. https://overreacted.io/ko/react-as-a-ui-runtime/

React가 컴포넌트 호출 제어권을 가지게 되면 다음과 같은 이점이 있다.

 

1. 컴포넌트는 함수 이상의 역할을 해준다.

React는 컴포넌트와 연결된 로컬 상태와 관련된 기능을 함께 제공한다. (몇가지 기능을 추상화해준다는 뜻)

React가 상호작용에 대한 응답으로 UI 트리를 렌더링하는데,

컴포넌트를 직접호출한다면 React가 하던 일들을 직접 구축해야한다.

 

2. 컴포넌트 타입으로 재조정을 한다.

React가 컴포넌트를 호출할 수 있게 되면, 트리의 구조를 더 많이 알려줄 수 있다.

컴포넌트 타입이라하면 tag name이다. tag name이 바뀌면 모든 상태를 증발시키고 새로운 뷰를 생성하는 것이 react의 기본 동작이다.

React가 컴포넌트를 호출하게 하면 이 부분도 대신해준다.

 

3. React가 재조정을 지연시킬 수 있다.

브라우저가 컴포넌트를 호출할때 그 사이에 몇가지 부수적인 작업을 할 수 있게 되어서, 

규모가 큰 컴포넌트 트리를 다시 렌더링 하더라도 메인  스레드를 멈추지 않게 할 수 있다. (경험해보진 못함)

 

4. 평가가 지연된다.

자바스크립트에서 함수를 호출하면 인자들은 호출전에 평가된다.

 

아래와 같은 경우를 살펴보자

함수가 어떤 조건에 의해 일찍 종료되었다.

 

그럼 사용자가 직접호출한 컴포넌트는 항상 실행될 것이고, (위)

React가 호출하도록 놔둔 컴포넌트는 실행되지 않을 것이다. (아래)

즉, 지연평가를 통해 React가 호출 시점을 정할 수 있게 해준다!

 

 

=> 핵심 요약.

React에게 컴포넌트의 호출을 맡김으로써,

1. React가 수행하는 자잘한 동작 (UI관련 트리 생성 등)을 대신 수행해주고,

2. 호출 시점을 React가 정할 수 있게하여 원하는 시점에 호출할 수 있다.

 

 

ref를 남용하면 안되는 이유는 무엇일까요?

 

https://ko.reactjs.org/docs/refs-and-the-dom.html

 

ref를 남용하다보면 어플리케이션에 "어떤 일이 일어나게"할 때 사용될 수 있습니다.

이 때에는 상태값을 끌어올리는 것이 적절한 경우가 많기 때문에 남용을 지양하도록 하자.

 

상태값을 끌어올려야하는 이유는 옆 키워드를 검색 => state는 왜 끌어올려야 하나요

 

 

profile on loading

Loading...