Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
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
Tags
more
Archives
Today
Total
관리 메뉴

개발블로그

DEVIEW Review(2018.10.13) 본문

DEVIEW Review(2018.10.13)

학교옆메추리 2020. 5. 28. 14:00

1. React Native: 웹 개발자가 한달만에 앱 출시하기

(발표자료: https://www.slideshare.net/deview/121react-native)

React Native

Facebook, Instagram, Discord 등 많은 플랫폼에서 React Native가 사용되고 있다. 네이티브 앱에서 React Native로 전환한 후 많은 덕을 보았다.
빠른 개발속도, 98%에 육박하는 iOS, Android간의 코드 공유 등 탁월한 선택이라고 이야기함.

React Native의 장점은 투입한 개발 리소스에 비해 결과물의 퀄리티가 좋다는 점과 플랫폼간 공유 코드를 생성함으로써 유지 보수비용이 낮아진다는 점이다.

‘단 기간에 프로덕션 레벨의 크로스 플랫폼을 만들어야 할 때 고려할 수 있는 여러 선택지 중 가성비가 가장 좋은 프레임워크!’

Structure

네이티브 영역과, 자바스크립트 스레드, 그 둘을 이어주는 다리역할을 하는 브릿지(Bridge)로 구성되어있음.

— Bridged

  1. Asynchronous
  2. Serializable — 직렬화, 네이티브 영역과 JS스레드간 데이터 공유의 많은 관리 이슈로 인해 데이터를 직렬화, 역직렬화하여 통신한다. but, 간결해진 구조 대신 성능저하가 발생함.
  3. Batched — 네이티브가 호출될때마다 앞서 말한 직렬화, 역직렬화가 일어나면서 부하가 발생함 -> 큐에 담아서 5ms단위로 일괄 처리함으로써 성능 개선

MessageQueue.spy함수로 Bridge를 모니터링할 수 있다.

— Handling Event

함수에서 setState와, API호출을 사용한다고 가정하자.

  1. Event occurred: Native module
    이벤트가 발생하고, setState를 통해 UI 업데이트가 필요해져 네이티브 호출이 일어나고 메시지 큐에 담김.
  2. Serialize event: Bridge
    메시지 큐에 담긴 일들을 받아 JS스레드로 전달.
  3. Process event, Call native method: JS thread
    API호출을 통해 내부적으로 네이티브 함수들이 호출되고, 메시지 큐에 담김.
  4. Serialize command: Bridge
    메시지 큐에 담긴 일들을 네이티브모듈로 전달해줌.
  5. Process command, Update UI: Native module
    전달받은 일들을 수행함.

Tips

  • 작업 시 복잡한 애니메이션이나 인터랙션은 안드로이드로 확인해본다. 
    ( iOS에 비해 성능이 떨어져 잘 안돌아갈 수 있으므로 꼭 확인하길…! )
  • Optional chaining 가용
  • babel-plugin-root-import를 통해 import 경로지옥 탈출! ( 절대경로 사용 )
  • 패키지 버전을 고정하자 ( 버젼 앞 ^를 빼거나 설치 시 exact키워드 사용 )
  • 타입 시스템으로 Flow 사용
    - TypeScript도 좋지만 아직은 Flow를 사용하는것이 더 편하다. 추후 TS지원이 더 많아지면 그땐 TS를 쓰자.
    - 가끔 Flow가 지원하지 않는 문법들이 있는데, ( ex. Optional chaining ) 이는 //$FlowFixedInNextDeploy 주석을 사용하여 회피하자.
  • react-native-fast-image를 사용하면 기존 Image태그의 몇 가지문제점을 해결해줌
  • JavaScriptCore ( JSC )의 동작 오류
    - 디버그 모드는 V8, 빌드된 앱은 JSC로 동작하여 Date객체 등의 동작이 다를 수 있으니 꼭 확인해야함 ( moment.js등의 라이브러리로도 해결 가능)
    - 안드로이드가 오래된 JSC를 사용하여 차이가 있을 수 있음 ( 플랫폼 별 컴포넌트 스타일링을 통해 해결하자! )
  • 안드로이드가 Text에 자동으로 위 아래 padding을 삽입함으로 플랫폼간 차이 발생
    - includeFontPadding스타일 속성 false값으로 두면 해결된다.
    - 공용 <Text />컴포넌트를 만들어 속성을 미리 정의하는것도 좋은 방법.
  • 최소 터치 영역 44px보장하기
    - hitSlop속성을 통해 실제 터치영역을 확장할 수 있다.
  • render()함수가 최초에 한번 실행됨을 까먹지 말자! ( React에도 해당하는 이야기! )
    - state에 isLoading변수를 두어 불필요한 초기 렌더링을 제거하자
  • setInterval등의 함수는 clearInterval함수를 호출하지 않으면 컴포넌트가 언마운트되어도 백그라운드에서 계속 실행되므로 조심하자.
  • 애니메이션 동작에서 60 FPS을 보장하기
    - default인 JSDriver를 사용하면 Bridge를 거쳐야 함으로 성능저하가 발생한다. 애니메이션 내부 useNativeDriver속성의 값을 true로 해주면, Bridge를 거치지 않고 UI업데이트가 일어나 효율적이다.
    - but, NativeDriver가 모든 스타일을 지원하지 않으므로 적정 선에서 타협할것.
  • 반복되는 애니메이션으로 인해 실행시점의 문제나 코드실행의 문제가 발생할 수 있으니 무거운 연산은 다음 프레임으로 실행지연시켜 앱 반응성을 개선하자 ( 무슨 말인지 모르겠다… )
  • FlatList에서 높이가 고정된 구성이라면 getItemLayout속성을 사용하자.
    - 레이아웃의 크기가 매번 계산되지 않아 성능이 개선된다.
  • React.createRef()를 권장. ( 기존 방식이 deprecate되었다. )
  • babel-plugin-transform-remove-console을 통해 console을 제거하자.
  • 이미지를 최적화하자. ( TinyPNG, OptiPNG )
  • <LottieView />로 Adobe After Effects로 작업한 애니메이션을 JSON형식으로 가져와 export할 수 있다.

Q&A

  • Bridge 통신과정 중 직렬화로 인해 성능저하가 발생하므로 큰 영상파일 등은 네이티브 모듈을 사용하는것이 좋을 것 같다.

2. 책에서는 맛 볼 수 없는 HTML5 Canvas 이야기

(발표자료: https://www.slideshare.net/deview/122-html5-canvas)

How browser draw image?

Rendering Engine이 우리가 작성한 태그들을 어떻게 그릴지 알고있다.

  1. Parsing DOM, CSS( 어떤 모양을 그릴지 결정 )
  2. Layouting ( 위치와 사이즈를 결정 )
  3. Layerization ( 그리는 순서를 결정 )
  4. Rendering Engine에 의해 그리는 방법(순서 등) 결정
    - 어떤 모양으로, 어느 위치에 어느정도 크기로, 어떤 순서로 그릴지.

How Canvas draw image?

Canvas도 HTML element이기에 위와 동일하게 그려짐.

But, 캔버스의 내부를 어떻게 그릴지는 개발자의 손(JS 코드)에 달려있다.

  1. 렌더링 엔진이 script태그 내 JS코드를 읽음.
  2. JS Engine이 코드를 해석.
  3. 해석한 결과를 다시 렌더링 엔진에 넘김
  4. 그래픽 라이브러리를 호출함으로써 이미지가 그려짐

Problem of Canvas

캔버스의 목적은 다이나믹하게 변하는 그래픽 즉, 애니메이션 처리에 있다.

— VSync

60fps를 유지하기 위해 우리는 약 16.6ms마다 한번씩 렌더링 할 수 있어야 함.

but…만약 렌더링할게 너무 많아서 연산이 무거워지면, 시간을 초과할 수 있음 ( 렌더링의 모든것이 Main thread에서 일어나기에 너무 바쁘다… )in

— Optimization in browser

브라우저 단에서 최적화가 진행되어 성능이 많이 개선됨.
- 최신 브라우저는 Canvas를 Raster thread(GPU) 에서 처리함 (그리는것을 이야기함. canvas에 대한 JS코드는 여전히 메인 스레드에서 담당함.)

— Optimization with developer

  1. Fullscreen Canvas를 사용하여 DOM 조작을 줄이기
  2. WebGL로 렌더링
  3. Background Canvas 사용하기 (미리 그려놓기)

이러한 노력과 개선에도 불구하고, 아래의 문제점들이 있음.
- JS엔진과 렌더링 엔진간의 binding overhead
- GPU의 도움을 받아도 여전히 발생하는 그래픽 라이브러리 내부 overhead
- DOM렌더링을 하기에도 여전히 Main thread는 바쁨…

Offscreen Canvas!

DOM Rendering과 분리되어 다른 thread인 Web Worker에서 렌더링 할 수 있기 때문에 매우 큰 성능 향상을 보인다. ( canvas 를 그리는 JS코드 해석까지 web worker를 통해 렌더링함. )

case study

발표자료 뒷부분 참고( p90 ~ )

Example

canvas 애니메이션이 동작하는 와중에 무한루프를 돌린다면 어떻게 될까?

  • normal한 canvas로 그리는 애니메이션은 메인 스레드의 과부하로 동작이 멈춘다.
  • but, Offscreen canvas로 그리는 애니메이션은 메인스레드가 아닌 다른 스레드에서 담당하므로 그대로 동작이 유지된다.

3. Javascript 배틀그라운드로부터 살아남기

(발표자료: https://www.slideshare.net/deview/123javascript)

빠르게 많은 양의 정보를 설명해주셨다.
발표자료를 보면 된다.

4. 네이버에서 사용되는 여러가지 Data Platform, 그리고 MongoDB

(발표자료: https://www.slideshare.net/deview/124-data-platform-mongodb)

NAVER’s Data Flatform

초창기에는 web server ← → RDBMS server의 2 tier 구조였으나 서비스가 점점 커짐에 따라 DB쿼리가 복잡하고 무거워졌다.
그에 따라, 빠른 응답을 보장하기 위해 Cache를 추가했다.
빅데이터성 데이터의 저장을 위해 HBase를 사용하였다. ( RDBMS로는 공간, 비용의 문제 발생)

MongoDB

기존의 데이터 플랫폼으로는 커버되지 않는 영역이 필요해지고, 각 개발팀들이 mongoDB를 이용해 자체적으로 운영함에 따라 지원하게 되었다.

— Needs

  1. Schema-less
    - 장점: 사전에 데이터에 대한 구조나 정의를 하지 않아도 된다.
    RDMS로는 공통적인 부분을 플랫폼화 할 때, 각 팀들의 요구사항이 조금씩 다를테니, 서비스 별 별도 table로 관리해야 해서 overhead 발생.
    - 단점: 미리 데이터에 대한 구조(스키마)를 정의하지 않았기 때문에 디비가 무슨 데이터가 들어올지 알 수가 없다. 따라서 들어오는 데이터들을 key, value쌍으로 저장해야 하는데, 이에 따라 RDBMS에 비해 훨씬 많은 저장 용량을 사용하게 된다. ( 또한 테이블마다 id값이 기본적으로 내장되어 있어 추가로 12byte가 사용된다 )
  2. Sharding
    - 데이터 사이즈가 증가함에 따라 Scale up(단일 서버의 스펙을 증가시키는 것)의 한계가 대두되면서 Scale out(여러대의 서버로 데이터 분산)이 필요해짐
    - RDBMS에서도 샤딩으로 scale out 구현 가능하나 확장성이 떨어지고, 개발 및 관리의 overhead가 발생한다.
    - 따라서 Auto Sharding이 가능한 데이터 플랫폼이 필요하게 되었다. (mongoDB는 오토샤딩을 지원한다)
    - 여기서 샤딩이란 대용량의 데이터를 처리하기 위해 데이터를 그룹단위로 분해하여 각각의 샤드가 자신의 그룹에 대한 저장 및 처리를 담당하게 하는 것을 말한다
  3. Secondary Index
    - HBase는 물리적 분리라 불가능하고 MongoDB는 논리적 분리라 가능하다는데 잘 모르겠다.
  4. Transaction ….못알아들었다.
  5. JSON 지원
    웹서버와 디비서버간에 JSON형식으로 데이터를 주고받을 수 있다.
    이 특징 때문에 mongoDB가 NoSQL 데이터베이스라고 불리는 듯 하다.
  6. IDC DR
    - 디비에 중요한 데이터에 들어갈수록 한 곳에만 저장되어있으면 위험성이 커진다. 따라서 DR ( disaster recovery ) 재난 복구 시스템이 필요함!
    - mongoDB는 auto failover(자동 장애조치)가 가능하다.

mongoDB가 이러한 네이버의 니즈에 맞아아 사용을 결심했다고 한다.

Episode about using mongoDB in NAVER

뭔 이야긴지 하나도 모르겠다…

Future of mongoDB

  • NoSQL과 RDBMS의 특징을 고루 가지고 있는 데이터 베이스이다.
  • 성능문제 등 문제점이 많다.
  • 사용처는 확대될 것 같으나 RDBMS에 비해 ACID(하나의 데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하는 성질)와 안정성이 떨어짐으로 인해 메인이 될 것 같지는 않음.

5. 웹 성능 최적화에 필요한 브라우저의 모든 것

(발표자료: https://www.slideshare.net/deview/125-119068291)

summary of how browsers work

  1. HTML 문서를 파싱하여 DOM트리를 만든다.
    - DOM트리는 html문서의 구조화된 표현이다.
    - 우리는 JS를 통해 DOM구조에 접근하여 구조, 스타일, 내용 등을 변경한다.
  2. Recalculate Style
    - CSS문서를 파싱한 결과(CSSOM)를 렌더 트리에 적용한다.
    - html은 단순 문서이다. 각 엘리먼트들의 렌더링의 관한 정보는 css가 가지고 있다.
  3. JavaScript Engine
    - 최신 브라우저들, 강의에서는 구글 크롬의 JS엔진인 V8을 예로 들었다.
    - 소스코드를 파싱하여 JIT 컴파일러로 머신코드를 생성하고, 실행한다.
    - JIT컴파일은 dynamic translation이라고도 하는데, 인터프리트 방식과 정적 컴파일 방식을 혼합한 방식이라고 생각할 수 있다. 런타임에서 인터프리터처럼 한줄한줄 읽어가며 머신코드를 생성하면서 그 코드를 캐싱하여 같은 함수가 여러 번 반복되어 불릴 때 캐싱된 머신코드를 사용하여 매번 머신코드를 생성하는 것을 방지한다.
  4. Render Tree
    - DOM트리 + CSSOM트리
    - DOM트리와 1대1구조를 이루지 않는다.
    예를들어 <a><b><b/></a>에서 a에 display: none속성이 정의되어 있으면 렌더트리에는 b가 없음 ( 실제 화면위에 렌더링할, 보이는 요소들을 중심으로 구성되어 있다. )
  5. Layout
    - 생성된 렌더트리의 노드들에 대한 좌표를 계산하는 과정이다.
    - Global Layout(윈도우 사이즈나 폰트 변경 시. 약간 글로벌한 느낌나는것들을 변경하는 것.)과 Incremental Layout(그 외 모든것)이 있다.
  6. Paint
    렌더트리를 기반으로 화면에 보여준다.

— New version of browser’s main flow

최신 브라우저에서는 두가지의 과정이 추가되었다.

  • Update Layer Tree ( Layout 과정 직후 )
    - 렌더링에 사용될 레이어들을 계산하여 생성한다.
    - css에서 3d Transform, Animation / canvas나 video태그 / position이 relative, absolute인 것들 에 대해서 레이어가 생성된다고 한다. (적어놓은 것 이외에도 레이어 생성 조건이 많다. )
  • Composite Layers ( Paint 과정 직후) 
    - 레이어 트리에 생성된 레이어들을 합성하여 한장의 bitmap으로 만든다.
    - Paint는 각 레이어별로 그리고, Tiled Backing Store기법을 사용한다. 
    ( 잘은 몰라도 레이어 하나씩 그려서 그 타일을 저장해놓는다는 것 같다. )

How the browser makes a frame?

위에서 말했듯 메인 스레드에서 하는 일이 너무 많아 VSync를 지키기 어렵다.
- Compositor thread를 통해 레이어 합성과정, 마우스 스크롤, 줌, 애니메이션 등을 메인 스레드에서 분산하여 처리한다.
- Raster thread에서 Graphics Command를 Bitmap으로 만듦 (픽셀로 구성된 우리의 화면에 출력하기 위해 도형으로 구성된 이미지를 가져와서 도트형식으로 만들어낸다는 말인것 같다.)

chrome://tracing에서 개발자도구보다 더 자세하게 위의 과정들을 볼 수 있다고 한다.

Rendering pipeline stage costs

  • 렌더링 파이프라인에서
    Layout은 width, height, font등을 사용할 때, 
    Painting은 color, background등을 사용할 때,
    Composite은 opacity, transform등을 사용할 때 다시 수행되어야 한다.
  • 렌더링에는 순서가 있으므로 파이프라인 앞쪽인 Layout을 건드리게 되면 그 이후의 작업들이 모두 다시 수행되어야 하므로 비용이 크다.
  • Layout과정은 약 1000개의 DOM 엘리먼트가 효율적이고, 애니메이션은 transform이나 web animation을 사용하여 파이프라인 뒤쪽의 Composite 단계에서 수행하도록 하자.
  • Paint과정은 GPU Rasterization을 사용하면 대략 10배정도 빨라진다.
    <meta name=“viewport” />만 추가해도 이 성능향상을 누릴 수 있다.
  • Composite과정은 Layer가 과다해지면 메모리를 많이 잡아먹고 성능이 떨어진다. 대략 30개 정도의 레이어를 유지하는 것이 가장 효율적이다.

최적화를 통해 VSync안에 모든 일들을 수행하도록 하여 60FPS를 보장하는 멋진 FE가 됩시다!

'' 카테고리의 다른 글

Express middlewares  (0) 2020.07.12
HTTP/1.1 vs HTTP/2  (0) 2020.05.29
JS Promise (2018.10.10)  (0) 2020.05.28
JS this (2018.10.06)  (0) 2020.05.28
JS Class (2018.10.04)  (0) 2020.05.28