Spa
SINGLE PAGE APPLICATION
한 페이지에 여러가지 인터랙티브한 UI를 포함한 어플리케이션이다.
장점
- 사용자는 전체 화면의 새로고침(서버를 통한 전체 페이지 갱신)없이 빠르게 부분 UI의 갱신한다.
- 향상된 UX를 뽐낸다.
- 서버의 View 작업의 부담이 감소된다.
구현의 어려움
- 클라이언트 렌더링 최적화 기술의 필요하다.
- 모듈 관리가 복잡하다.
- View - Model 역할과 의존성
- Data binding처리
- 상태 관리가 어렵다.
- 전역변수
- 서버와의 데이터 동기화
- 라우팅 처리의 부담이 있다.
- 초기 로딩에서 불필요한 자원의 로딩을 해야한다.
향상된 디자인
1. 디렉토리 구조 정의
계층을 나누고 각 계층은 동등한 수준으로 만든다.
- /utils
- /libs
- /components
- /modal
- /calendar
- /stores
- /todos
- /others
- /views
- /headers
- /list
2. rendering 최적화
DOM 업데이트 영역의 최소화
변경을 탐지하고 그 부분의 업데이트만 실행한다.
동일한 결과에 대해서는 재사용
캐시를 사용하는 방법이다.
3. 더 빠른 초기 로딩
-
bundling 최적화
- 공백제거, 변수/함수 이름 난독화. 중복 모듈 최소화
-
Server Side Rendering
- 서버에서 정적인 UI를 완성. 클라이언트에서 이벤트 추가 (hydration)
- fetch data (server) → render to HTML (server) → load code (client) → hydrate (client)
- 클라/서버 모두 templating 해야 하는 부담.
-
SSR 을 넘어서 보자.(*)
- Streaming HTML
- selective hydrating
-
Code splitting
async function getComponent() { const element = document.createElement('div'); const { default: _ } = await import('lodash'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } getComponent().then((component) => { document.body.appendChild(component); });
- 웹팩에서의 실행 example. (Lazy loading 을 사용하고 있음.)
- https://medium.com/@anuhosad/code-splitting-in-webpack-with-dynamic-imports-4385b3760ef8
SPAs 애플리케이션 디자인
역할을 명확하게 해야 한다.
Model
비즈니스 로직이 없는 데이터 의 생성/변경/삭제
- Testable model 인가?
View
데이터 조작이 없는 순수한 View 렌더링
- 다른 데이터 구조에도 적용이 가능한가?
Model -> View의 단방향의 흐름제어 (unidirectional data flow)
- View 간의 의존성이 없다.
- 데이터 변경에 의해서 View가 변화한다.
Model 과 View의 관계
- Data-binding
- defineProperty
const fooView = {
render(data) {
console.log("rendering data", data)
}
}
const store = {
_property1 : ''
};
const getter = () => `result is ${object1._property1}`;
const setter = (data) => {
store._property1 = data;
//아마도 어떤 view 렌더링
fooView.render(data);
}
Object.defineProperty(store, 'property1', {
get: getter,
set: setter
});
store.property1 = 77;
- Proxy API
- 구독형 방식 (Observer pattern) « 중요