본문 바로가기

Web + APP/Angular

Angular Hydration

반응형
SMALL

Angular는 예전부터 SSR과 Hydration에 대해 지속적인 관심을 가져왔다.

 

공식 문서에서도 크롬 오로라 팀이랑 협업해서 어떻게든 성능 올리려고 노력했다고 한다.

 

우리도 노력 중입니다.

그렇다면 Hydration이 무엇일까 ?

 

Hydration이란 서버단에서 정적으로 DOM 구조를 넘겨주면, 그걸 받아서 동적인 event를 붙여넣는거라고 하더라.


Why is hydration important ?

hydration은 DOM 구조를 재생성하지 않는다는 점에서 app 성능을 향상시킬 수 있다.

 

hydration 없이도 SSR이 가능하긴 하지만, app의 DOM을 re-render해야한다. 그렇게 되면, 우리가 app 만들 때, "깜빡" 하는 이슈가 발생하게 되는 것이다. (UI flicker라고 한다)

 

hydration은 이러한 이슈를 막을 수 있다는 점에서 사용자 경험을 향상시키고 성능도 향상시킬 수 있다.

 


How do you enable hydration in Angular

hydration을 적용하기 전에 SSR app을 가지고 있어야한다.

 

https://angular.io/guide/universal

 

Angular

 

angular.io

 

위 URL을 통해서 SSR을 맛 볼 수 있다. (위 글을 먼저 정리할 걸, 서순이 잘 못 됐다)

 

아 서순 ;

일단 SSR이 app에서 동작을 하면, main app component 혹은 module을 방문했을 시 hydration을 사용할 수 있다.

 

import {
	bootstrapApplication,
    provideClientHydration,
} from '@angular/platform-browser';

bootstrapApplication(RootCmp, {
	providers: [provideClientHydration()]
});

 

NgMouldes를 쓰는 중이라면, provideClientHydration을 root app module provider 리스트에 넣어도 된다.

 

import {provideClientHydration} from '@angular/platform-browser';
import {NgModule} from '@angular/core';

@NgModule({
	declarations: [RootCmp],
    exports: [RootCmp],
    bootstrap: [RootCmp],
    providers: [provideClientHydration()],
})
export class AppModule {}
provideClientHydration() 의 경우 서버에 있는 application에서도 사용되고 있는지 확인이 되어야한다.
기본 프로젝트 구조(ng new로 생성한)에서는 root인 AppModule에서 호출하는것만으로 충분한데, 그 이유는 해당 모듈이 서버 모듈에 의해 import되기 때문이다.
만약 custom setup을 사용하고 있다면, provideClientHydration()을 서버 config의 provider 리스트에 추가하도록하자.

해당 절차를 밟고 서버를 시작하고, 브라우저에서 app을 로드하자

 

개발 모드에서 app이 실행되는 동안 dev tools를 통해서 hydration이 제대로 동작하는지 확인할 수 있다.

 

hydrated된 node들 혹은 컴포넌트와 같은 관련 메시지를 확인해야한다.

 

Angular는 페이지에 렌더된 컴포넌트의 stat을 계산하고, 이 중에 third party library로부터 포함된 것들도 포함된다.

 


Constraints

Hydration은 app에다가 몇가지 조건을 주게된다.

 

app은 반드시 서버와 클라이언트, 서로 같은 DOM 구조를 가져야한다.

 

hydration의 과정은 각자 같은 구조의 DOM tree를 가짐을 원한다.

 

이는 서버에 렌더링되는 동안 Angular가 만드는 공백, 주석 노드도 포함하며, 이러한 공백 및 주석 노드들은 SSR이 렌더링 과정에 의해 HTML에 생성되게 된다.

 

SSR에 의해 생성된 HTML은 서버와 클라이언트 사이간에 변경되지 않아야한다.

 

만약, 서버와 클라이언트 사이간 DOM tree 구조가 다르다면, hydration 과정 중 문제가 발생하게 되는데, 이는 DOM API를 사용하여 직접 DOM을 조작할 때 원인이 된다.


Direct DOM Manipulation

native DOM APIs를 사용하여 DOM을 조작하는 컴포넌트가 있을 때, hydration은 에러를 마주하게 된다.

 

appendChild를 통해 node들을 추가하거나, document에 직접 접근 하는 상황이 해당 예이다.

 

DOM node를 분리하여 이동시키는 것도 에러의 원인이 된다.

 

Angular는 이런 DOM 변화를 인식할 수 없고, hydration 과정 중 해결할 수 없다.

 

Angular는 기대했던 구조와 다른 구조를 마주하게 되고, hydrate에 문제가 생기는 것이다.

 

이러한 미스매치는 hydration의 실패와 DOM mismatch error를 마주하게 할 것이다.

 

진짜, 몇 번을 강조했는데, Angular 팀에서도 굉장히 우려를 많이 하는 부분인가보다 ;;

 

하긴 유저들은 이런 설명서 잘 안 보고 그냥 사용하잖아. 그죠 ?

 

냉장고 샀다고 냉장고 설명서 다 보고 그러진 않지.

 

근데, 우리는 잘 읽고 사용해야함..

 

안 그럼 혼남

 

이미 적용한 부분들이 있다면, ngSkipHydration attribute를 사용하고, 추후에 리팩토링할 수 있을 때, 하도록하자.


Valid HTML structure

valid HTML이 아닌 컴포넌트 템플릿 케이스가 몇 가지 있는데, 아래의 경우와 같다.

  • tbody 태그가 없는 table 태그
  • p 태그 안에 div 태그
  • h1 태그 안에 a 태그
  • a 태그 안에 a 태그

syntax validator(https://validator.w3.org/)를 통해서 HTML이 유효한지 안한지를 체크할 수 있다고 한다.

 

음.. 워닝 두 개 밖에 안 뜨네..?


Preserve Whitespaces Configuration

hydration 기능을 쓸 때, preserveWhitespaces를 false로 두고 쓰는걸 추천한다. 

 

tsconfig에 없다면, fasel가 디폴트로 들어간다.

 

만약, true로 있다면, 이슈가 발생할 수 있다.

 

angular 쪽에서도 해당 부분에 있어서 계속 수리 중이라고한다.

 

뚱땅뚱땅

서버의 경우엔 tsconfig.server.json에서 확인하고, 브라우저의 경우 tsconfig.app.json을 확인하자.

 

둘 다 값이 일치해야한다.

 

그 뒤 내용은 귀찮아서 안 써야겠다.

 

안녕 ~

반응형
LIST

'Web + APP > Angular' 카테고리의 다른 글

Angualr v16 - signal  (6) 2023.06.04
providers와 viewProviders의 차이 / content child와 view child  (0) 2022.05.21
HostListener & HostBinding  (0) 2022.04.30
NGRX Store - An Architecture Guide (1)  (0) 2022.04.11
attr vs attr.name  (0) 2022.03.30