Skip to content

Latest commit

 

History

History
32 lines (17 loc) · 3.89 KB

universal.md

File metadata and controls

32 lines (17 loc) · 3.89 KB

유니버설 코드 작성하기

자세히 살펴보기 전에 잠시 "유니버설" 코드, 즉 서버와 클라이언트 모두에서 실행가능한 코드를 작성하는 경우의 제약사항에 관하여 살펴봅니다. 유즈케이스 및 플랫폼 API의 차이에 따라 서로 다른 환경에서 실행할 때 코드의 동작이 정확히 동일할 수는 없습니다. 여기서는 꼭 알아야할 중요한 것들을 다룹니다.

서버에서의 데이터 반응성

클라이언트만 존재하는 앱에서는 모든 사용자가 브라우저에서 앱의 새로운 인스턴스를 사용하게됩니다. 서버 측 렌더링의 경우에도 동일한 요청이 필요합니다. 각 요청에는 교차 요청 상태(Cross Request State) 오염이 없도록 격리 된 새 앱 인스턴스가 있어야합니다.

실제 렌더링 프로세스는 결정적이어야하므로 서버에서 데이터를 "미리 가져(pre-fetching)"옵니다. 렌더링을 시작할 때 애플리케이션 상태는 이미 완료되어 있어야 합니다. 즉, 서버에서 데이터 반응성이 필요하지 않으므로 기본적으로 비활성화 되어 있습니다. 데이터 반응성을 비활성화하면 데이터를 반응형 객체로 변환하는 성능 비용을 피할 수 있습니다.

컴포넌트 라이프사이클 훅

동적인 갱신이 없으므로 모든 라이프사이클 훅 중 beforeCreatecreated만 SSR 중에 호출됩니다. 즉, beforeMount 또는 mounted와 같은 다른 라이프사이클 훅 안의 모든 코드는 클라이언트에서만 실행됩니다.

또 다른 주의 사항은 beforeCreatecreated에서 전역적인 사이드이펙트를 만드는 코드 (예: setInterval로 타이머 설정) 클라이언트 측 코드에서만 타이머를 설정한 다음 beforeDestroy 또는 destroyed에서 제거할 수 있습니다. 그러나 SSR 중 destroy 훅이 호출되지 않기 때문에 타이머가 영원히 계속 살아있습니다. 이를 피하려면 사이드이펙트를 발생하는 코드를 beforeMount 뚀는mounted로 옮겨야 합니다.

플랫폼에 의존하는 API에 접근하기

유니버설 코드는 특정 플랫폼의 API 접근을 가정할 수 없으므로 코드가 window 또는 document와 같은 브라우저 전용 전역 변수를 직접 사용하면 Node.js에서 실행할 때 오류가 발생합니다. 이 반대의 경우도 마찬가지 입니다.

서버와 클라이언트간 공유되지만 다른 플랫폼 API를 사용하는 경우 플랫폼 별 구현을 범용적인 API로 래핑하거나 이를 위해 라이브러리를 사용하는 것이 좋습니다. 예를 들어 axios는 서버와 클라이언트 모두에서 동일한 API를 제공하는 HTTP 클라이언트 입니다.

브라우저 전용 API의 경우 일반적인 방법은 클라이언트 전용 라이프사이클 훅에 게으른 접근(Lazyily Access)을 하는 것 입니다.

써드파티 라이브러리가 범용적인 사용을 고려하지 않고 작성된 경우 서버에서 렌더링 된 애플리케이션과 통합하는 것이 까다로울 수 있습니다. 일부 전역 변수를 가짜로 만들어(mocking) 작동시킬 수 있으나 이는 편법이며 다른 라이브러리의 환경설정 감지 코드를 건드릴 수 있습니다.

사용자 정의 디렉티브

대부분의 사용자 정의 디렉티브는 DOM을 직접 조작하므로 SSR중 오류가 발생합니다. 이 문제를 해결하는 방법은 두가지 입니다.

  1. 추상화 메커니즘으로 컴포넌트를 사용하고 가상 DOM 수준에서 작업해야합니다. (예 : 렌더링 기능 사용)
  2. 컴포넌트로 쉽게 바꿀 수 없는 사용자 정의 디렉티브가 있는 경우 서버 렌더러를 만들 때 directives옵션을 사용해 "서버용 버전"을 제공할 수 있습니다.