본문 바로가기

개념정리/기술면접대비

[기술면접 대비] 6. 모던 프레임워크 - node, vue, react

[모던 프레임워크]

1. 라이브러리와 프레임워크

라이브러리는 내가 제어권을 가지고 호출해 사용하는 도구라면 프레임워크는 어떠한 환경. 제어의 역전이 일어나 프레임워크가 내 코드를 호출 할 제어권을 가짐.

여기서 의문. 리액트, 뷰, 앵귤러는 프레임워크인가 라이브러리인가? 리액트는 자신을 '사용자 인터페이스를 만들기 위한 JavaScript 라이브러리' 라고 소개한다. 뷰는 '사용자 인터페이스를 만들기 위한 프로그레시브 프레임워크' 라고 소개한다. 어째서? 유의미한 차이가 있는지 궁금함.

 

1. js의 모듈화 사용방법

7. require와 import 차이

require는 commonJS에서 명명한 규칙으로 node.js에서 사용하는 카워드, (내보내기도 node는 module.exports 씀)

import는 es6에서 새롭게 도입된 키원드.

 

8. export용법 아는대로

선언된 변수를 내보낼 수 있음 export {var1, var2, ... }

선언과 동시에 내보낼 수 있음 export var(let,const) var1 = "hello";

리네이밍해서 내보낼 수 있음 export {var1 as myValue}

기본값으로 내보낼 수 있음 export default var1 (파일 당 하나만 가능. 유명값이 아니라 아무 이름으로나 import 가능)

 

19. 컴파일러와 트랜스파일러

9. Virtual DOM

기존의 DOM은 엘리먼트를 수정, 추가, 삭제시 마다 redner tree를 다시 구축하고 배치하고 그렸다.

SPA이 등장하면서 하나의 거대한 html이 나타났는데, 여기서 문제 발생. 죄다 다시 그려??

이러한 문제를 해결하기 위해 등장~! DOM의 JS 경량 표현.

로컬에 virtual DOM을 생성하고 브라우저에 render 요청 전 virtual DOM에서 변경점을 찾아내서 실제 DOM에 대한 제어를 최소화한다. 어떻게?

먼저 virtual DOM에서 리렌더링 작업 수행

이전의 v-DOM과 현재 내용 비교 

바뀐 부분만 실제 DOM에 전달해 적용 (이 때 실제로 화면이 변경됨)

 

10. SPA

단일 페이지로 구성된 어플리케이션.

어플리케이션의 모든 정적 리소스를 최초 요청시 다 받아옴. 페이지 전환시에도 서버에 요청하는게 아니라 클라잉언트 쪽에서 라우팅을 통해 처리. 이 과정에서 전체 페이지를 처음부터 다시 그리는 게 아니라 변경된 부분만 갱신하므로 네이티브 앱과 유사한 사용자 경험 제공 가능.

 

11. CSR과 SSR

클라이언트 사이드 렌더링과 서버 사이드 렌더링

CSR의 문제 ! 최초 요청시 많은 자원을 요청함. SEO문제 (빈 페이지로 인식함)

 

12. AMD와 CommonJS

 

13. node

CommonJs의 개념적 명세와 v8엔진의 기술력이 바탕이 되어 탄생

1) 패키지 관리

2) 모듈화가 핵심

3) 범용 어플리케이션으로의 확장성

node.js +a

Express : 미니멀한 node기반 프레임웤, SPA제공

 

14. npm

노드 패키지 매니저

 

15. package.json

프로젝트 명세서

 

16. 웹팩

번들링 함.

파일을 하나의 모듈로 보고 엔트리 포인트부터 시작해 연결된 모든 모듈을 번들링 해서 하나의 아웃풋을 만듦.

이 때 파일이 모듈화 될 때 타는 게 로더.

아웃풋이 나오면 후처리 담당(암호화,공백제거 등) 하는 게 플러그인.

 

17. 바벨

크로스 브라우징을 지원하기 위함.

ES6, typescript, JSX식 같은 것들은 브라우저 환경에 따라 다름.

모든 브라우저가 이해 할 수 있는 언어로 변환 작업이 필요한데 이를 담당함. 사실 바벨은 파싱>변환>출력 과정 중 파싱과 출력만 담당함. 변환 과정을 담당 하는 바벨 플러그인을 사용해야 제대로 변환이 이루어 짐.

플러그인을 모아 놓은 게 프리셋

preset-env, preset-react, preset-typescript 등등이 있다.

문법적으로 변환이 가능한 것들은 플러그인을 타는데, 아예 새롭게 추가되거나 변경 된 기능은 어떻게 할 까? 한마디로 대체재가 없는 상황이라면? 누락된 것을 끼워넣어주는 역할을 하는 폴리필!

새로운 기능을 정의해서 제공하는 역할.

새로운 문법으로 대체된 경우는 트랜스파일러만 있어도 구 표준으로 변환이 가능하지만 아예 기능이 새롭게 추가되거나 변경된 함수는 명세를 읽고 직접 함수를 구현해줘야 함. 이를 위해 기존 함수의 동작 방식을 덮어쓰거나 새롭게 구현하는 스크립트

 

18. 린트

코드 오류, 일관성, 스타일 등을 점검. 

일관된 코드 스타일을 유지하고, 가독성을 향상하는 포맷팅. 무분별한 변수 선언, 글로벌 스코프 오염 등을 방지하는 코드 품질 체크.

 

22. 크롬 브라우저 제외 ES6 지원방법

바벨로 타깃 브라우저를 잡고 preset-env 적용

 

23. 타입스크립트

js + 타입

 

24. 정적, 동적 웹

정적 : js, css, html 등이 항상 같은 파일이 돌아옴

동적 : 게시판 등은 새로운 내용이 필요함.

 

25. MVC

Model : 데이터

View : 화면

Controller : 동작 제어, model과 view 연결

 

 

 

 

Node.js

Node.js에 대해 찾아보면 항상 자바스크립트 런타임 이라는 말로 귀결된다. 

대체 런타임이란 무엇인가. JS가 실행되는 환경을 의미한다. 

JS가 실행되는 환경이란 무엇인가? JS는 웹 상에서 동적인 조작을 가하기 위해 탄생한 언어다. 그러니 당연히 오랜세월 동안 JS가 실행되는 환경이라 하면 브라우저였다.

하지만 Node.js는 JS가 브라우저 밖에서도 동작할 수 있는 새로운 환경을 열어줬다. 말 그대로 Node.js 자체가 JS의 새로운 런타임이 되었다.

 

NPM

npm은 노드 기반의 패키지 관리 툴이다. 

의존성 

 

Webpack 웹팩

https://webpack.js.org/

- 최신 프론트엔드 프레임워크 환경에서 가장 많이 사용하는 모듈 번들러

- 웹팩은 빌드 과정에서 내부적으로 의존성 그래프를 만들며 각 모듈의 관계를 매핑함.

- JS코드를 파일 단위유효범위를 지정해주고, 웹 개발 작업에 유용한 자동화 도구(파일 압축및 난독화, css전처리기 변환 등)를 제공하며, 웹 어플리케이션의 성능 향상을 위한 여러 이점(Dynamic & Lazy Loading)을 제공한다.

 

공식문서가 제공하는 웹팩의 장점

더보기

1. 기존의 JS를 먼저 살펴봅시다

There are two ways to run JavaScript in a browser. First, include a script for each functionality; this solution is hard to scale because loading too many scripts can cause a network bottleneck. The second option is to use a big .js file containing all your project code, but this leads to problems in scope, size, readability and maintainability

JS가 브라우저에서 동작하기 위해 두가지 방법을 생각해 볼 수 있습니다. 하나는 기능별로 나뉜 작은 스크립트 파일을 여러개를 사용하는 것이고, 다른 하나는 모든 코드를 하나의 큰 스크립트 파일에 작성해서 사용하는 것 입니다. 전자의 방식은 많은 파일을 요청하으로 네트워크의 병목현상을 유발 할 것입니다. 후자는 당연히 너무 큰 파일의 크기가 문제가 될 것이고 스크립트의 가독성, 유지보수성이 파괴될 것이며 JS의 느슨한 스코핑 규정이 여러가지 골치아픈 문제를 야기할 것입니다.

 

2. IIFE는 유용했습니다. 하지만...

IIFEs solve scoping issues for large projects; when script files are wrapped by an IIFE, you can safely concatenate or safely combine files without worrying about scope collision.
However, changing one file means you have to rebuild the whole thing. Concatenating makes it easier to reuse scripts across files but makes build optimizations more difficult. How can you find out if code is actually being used or not?
Even if you only use a single function from lodash, you have to add the entire library and then squish it together. How do you treeshake the dependencies on your code? Lazy loading chunks of code can be hard to do at scale and requires a lot of manual work from the developer

 

 

*웹 환경에서 모듈이란?

웹 어플리케이션을 구성하는 HTML, CSS, JS, Image 등의 모든 자원을 의미있는 단위로 나눈 것

*번들링이란?

웹 어플리케이션을 구성하는 여러 모듈들을 빌드(번들링)하여 하나의 파일로 병합 및 압축하는 것.

 

웹팩의 핵심 컨셉 (공식문서 제공)

1. Entry

2. Output

3. Loaders

4. Plugins

5. Mode

6. Browser Compatibility

 

Babel 바벨

 

Lint 린트

 

 

 

 

 

 

 

Vue와 React의 등장배경

서버 사이드에서 처리하던 수많은 JS 코드가 클라이언트의 브라우저 단으로 이동함(CSR)

그러나 JS 코드들이 CSS/HTML와 복잡하게 맞물린 구조가 통일된 형태로 정리되지 않아 전체적인 상태관리와 DOM 제어가 점점 복잡해짐. JS는 컨트롤러와 돔 API를 사용한 프리젠터 역할을 모두 담당해야 했음.

이를 해결하기 위해 우선 컴포넌트 단위로 프로젝트를 쪼개고, 각 컴포넌트는 해당 컴포넌트의 view를 담당하는 템플릿에 model을 담당하는 데이터와 이벤트를 바인딩한 형태로 구성함.

JS코드로 모델을 변경하면 DOM에 대한 동기화는 vue나 react가 변화를 감지하고 재렌더링을 통해 자동으로 업데이트를 수행함. 

 

virtual DOM

js로 DOM의 사본을 만들어 메모리에 올려놓음. React, Vue 등의 모던 JS 프레임워크 환경에서 사용한다.

실제 DOM 요소를 직접 조작하지 않고 virtual DOM을 수정하면 실제 DOM과 비교해 변경된 부분의 돔만 업데이트 하므로 빠르고 가볍다.

virtaul DOM이 업데이트 된 후 실제 DOM이 업데이트되어 사용자의 브라우저에 표시됨.

Vue는 MVVM 모델을 사용함. view - 실제 DOM, View model - Vue js, model - js코드. 

js로 데이터만 변경하면 뷰 모델인 vue가 템플릿에 바인딩된 데이터 변경을 감지하고 실제 view를 담당하는 DOM을 자동으로 업데이트 해준다.

vue의 모델과 상태변화를 감지하는 로직에 대한 overview

 

vue 라이프사이클

 

1. create

 - beforeCreated : 뷰 인스턴스가 생성되기 전. 따라서 데이터에 접근하거나 수정할 수 없다 (computed나 watcher도 사용 불가)

 - created : 인스턴스는 생성되었으나 템플릿이 DOM에 렌더링 되기 전. computed 속성이나 데이터에 접근 가능하다. 템플릿이 렌더링 되기 전 필요한 데이터를 가져오는 ajax 호출을 넣기 적합한 훅. 

2. mounted

 - beforeMounted 

 - mounted : 인스턴스가 mount된 직후 호출됨. vue가 생성한 virtual DOM 엘리먼트인 $el에 접근 가능하다. 기본적으로 자식 컴포넌트의 mount 훅부터 시작해 부모 컴포넌트의 mount 훅까지 올라오지만 비동기 action 등을 사용할 경우는 항상 자식 컴포넌트의 mount훅이 완료되었음을 보장하지 않음. 이를 보장하려면 mounted 훅 내에서 this.$nextTick을 사용해야 한다.

3. updated

 - beforeUpdated : 데이터는 변경되었지만 DOM은 아직 update되지 않음. DOM이 변경되기 전에 직접 event listener등을 해제 할 일이 있다면 여기서 해야 함.

 - updated : 변경된 데이터로 virtual DOM이 재렌더링 된 직후에 호출됨. DOM과 관련된 operation을 수행하기 적합함. update 훅 내에서 state를 변경하게 되면 재렌더링이 무한 반복되므로 state변경은 computed나 watcher에서 수행할 것. 이 또한 자식 컴포넌트가 모두 재렌더링 된 상태를 보장하지 않으므로 이를 보장하려면 mounted 훅 내에서 this.$nextTick을 사용해야 한다. 

4. destroyed

 - beforeDestroyed : 모든 컴포넌트가 아직 살아있음. 이벤트 리스너를 해제하기 좋음.

 - destroyed : 모든 컴포넌트를 비롯한 vue instance가 소멸됨. $el을 사용할 수 없다. vue와 관련된 액션보다는 3rd party 라이브러리등을 해제하는 데에 사용하지만 실제적으로 잘 사용되지 않음. 

 

 

react 라이프 사이클

상위 컴포넌트로부터 내려받은 props를 해당 컴포넌트의 state에 복사하지 말고 직접 사용할 것. 

(https://ko.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html)

 

*class형 컴포넌트에서 사용됨. 함수형 컴포넌트는 다른 hook을 사용한다.

0. constructor : 인스턴스에 이벤트 메서드를 바인딩하거나 state값을 초기화하는 작업이 필요할 떄 사용함. 컴포넌트가 mount되어 렌더링 되기 전에 호출됨. 

더보기
constructor(props) {
  super(props);
  // 여기서 this.setState()를 호출하면 안 됩니다!
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}

1. componentDidMount : 컴포넌트가 마운트된 직후 호출됨. 데이터를 가져오기 위한 네트워크 요청을 보내거나 DOM노드를 사용한 초기화 작업을 수행할 수 있음. 데이터 구독을 등록하기 좋음.

2. componentDidUpdate : 최초 렌더링을 제외한 모든 재 렌더링 이후 호출됨. props 변경을 감지하고(조건문을 사용해 직접 비교) 네트워크 요청을 다시 보내거나, 컴포넌트 갱신 후 DOM을 조작하기 좋은 훅. 

3. componentWillUnmount : 컴포넌트의 마운트가 해제되어 제거되기 직전에 호출. 타이머를 사용했거나 mount훅에서 데이터 구독을 등록했다면 이 훅에서 직접 제거해줘야 함. 마운트가 해제된 뒤에는 재렌더링이 일어나지 않으므로 state를 변경하지 말 것.

 

 

vue와 react 차이 

https://kr.vuejs.org/v2/guide/comparison.html

 

다른 프레임워크와의 비교 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org