제공 :
한빛 네트워크저자 : Jason Strimpel
역자 : 반광수, 프리랜서 프로그래머
원문 :
Isomorphic JavaScript with LazoJS내가 @WalmartLabs에서 시작했을 때, 나는 많은 대중을 상대로 하는 웹사이트에서 강력한 힘을 발휘할 수 있는 것을 목표로 한 새로운 웹 프레임워크를 제작하는 일을 하는 팀에 배치됐다.
나는 최근에 OSCON(Open Source Convention)에서 이 경험에 대해 말할 기회가 있었다. 대화의 제목을 "만족스러운 비즈니스와 공학의 요구사항: 클라이언트-서버 자바스크립트, SEO(Search Engine Optimization), 그리고 최적화된 페이지 로드" 였는데, 상당히 어려운 주제다.
제목에 담고자 시도하고, 대화를 주고 받고자 했던 것은 어떻게 하면 우리는 SEO와 최적화된 페이지 로드 문제를 대중을 상대로 하는 웹사이트에서 나를 포함한 UI 엔지니어들의 행복과 생산성을 유지하면서 해결할 것인가였다. 우리가 어떻게 LazoJS라는 새로운 동일한 구조의 자바스크립트인 웹 프레임워크를 만듦으로 이 문제를 해결했는지 살펴보도록 하자.
요구사항
프레임워크가 지원해야 할 세가지 주요 요구사항이 있었다:
-
SEO - 사이트들은 모든 검색엔진 색인 작성기가 방문 가능해야 한다.
-
최적화된 페이지 로드 - 페이지들은 재빨리 로딩되어야 한다; 기본적인/인덱스화된 내용을 위한 미끼는 금지다.
- 최적화된 페이지 이동 - 사용자들은 재빨리 페이지간 이동이 가능해야 한다.
이러한 지켜야 할 가이드라인들을 가지고 이해관계자들과 확인하고 협업하기 위해 우리는 출발했다.
이해 관계자들최소한의 요구사항을 만난 것과 더불어, 우리 팀이 각각의 이해 관계자들의 요구사항을 설명하는 것이 필요했다. 발견 과정에서 우리는 이해 관계자들의 세가지 분류, 그리고 각각의 그룹을 위한 몇 가지 일반적인 요구사항과 목표를 확인했다.
-
제품 매니저들 - 주요 관심사는 혁신적인 제품을 만듦으로써 비즈니스 요구사항들을 충족시키는 것
-
엔지니어들 - 주요 관심사는 깨끗하고 효율적인 코드, 그리고 생산성 있게 일하기, 좋은 환경
-
엔지니어 관리자들 - 엔지니어와 제품 매니저들과의 요구사항에 균형을 유지하면서 가장 낮은 비용으로 최대한 빨리 양질의 코드를 전달하기.
우리는 주요 이해관계자들을 파악하였고 그들의 요구사항을 더 잘 이해하였으므로, 우리는 산업 동향을 살펴보기로 결정하였다.
앞으로 생각할 것일단 당신이 소프트웨어를 제작하면 그것은 언젠가 사라진다는 것은 비밀이 아니다. 그것은 결국 더 좋은 솔루션
[1]으로 대체될 것이다. 이것을 알면, 우리가 개발 비용에 대한 최대한의 보상을 보장 가능한 프레임워크를 만드는 것이 중요하다. 그래서 우리는 산업에서 최신 동향을 살펴보기로 결정했다. 우리는 어떤 쇼킹한 것을 발견하지는 않았다. - 하나의 플랫폼으로서 자바스크립트와 웹은 대단한 것이다 - 그것은 지난 몇 년간 산업에 관심을 기울였던 사람에게는 뉴스거리는 아니다.
Node.js 채택과
모듈들이 걱정스러울 정도의 속도로 증가했고 웹은 컴퓨터와 전화 운영 시스템과 다양한 디바이스에서 사용되는 다른 애플리케이션에 동력을 주는 데에 사용되었다. 우리는 프레임워크의 오랜 수명을 보장하기 위해 요구사항과 이해 관계자들의 요구들과 더불어 이러한 동향을 감안하길 원했다.
평가 솔루션들우리는 모든 요구사항들을 가졌으므로 우리의 다음 단계는 평가 과정을 시작하는 것이다. 우리는 3가지 주요 솔루션들을 조사했다 - 고전적인 웹 애플리케이션, 단일 페이지 애플리케이션, 그리고 융합형 웹 애플리케이션 모델들.
고전적인 웹 애플리케이션이 모델에서 내용은 서버에서 만들어진다. HTML 덩이가 브라우저로 보내진다. 브라우저는 HTML을 분석한다. 그리고 마지막으로 클라이언트의 수명 주기는 초기화된다. 이것은 주요 요구사항들을 충족시킬 것이다. 그러나 우리가 발견한 문제는 시간이 흐르면 클라이언트와 서버 간에 결국 중복된 로직에 처한다는 것이다, 이것은 비효율적이다.
예를 들면, 만약 한 제품 페이지가 부가적인 내용으로 제품 리뷰를 가지고 있다면 리뷰를 찾아가기 위해 페이지화는 필요하다. 전체 페이지를 새롭게 호출하는 것은 지극히 비효율적이다. 그래서 전형적인 해결책은 페이지를 만들 때 AJAX를 이용하여 리뷰 페이지 세트를 가져오는 것이다. 그 다음 최적화는 페이지 세트를 뿌려주기 위해 필요한 데이터만 가져오는 것일 것이다. 이것은 중복된 템플릿과 모델과 자산, 그리고 클라이언트에 뿌려주는 것이 필요하다. 당신은 또한 더 많은 단위 테스트를 하고 싶을 것이다. 이것은 매우 간단한 예이다. 그러나 만약 당신이 큰 애플리케이션에 대해 개념을 가지고 추론해본다면, 그것은 애플리케이션을 뒤따라가고 유지하기가 어렵게 만든다 - 사람들은 주어진 상황에서 어떻게 애플리케이션이 끝나는지 쉽게 추론할 수가 없다. 게다가 중복은 자원 낭비이며 애플리케이션에 특성이 추가되거나 수정될 때 두 개의 UI 코드베이스를 걸쳐서 버그가 생길 가능성을 열어 놓는다.
단일 페이지 애플리케이션우리가 평가한 다음의 솔루션은
단일 페이지 애플리케이션(single page application) (SPA) 모델이다. 이 솔루션은 화면에 뿌려주는 것은 전적으로 클라이언트에 책임을 이전함으로써 고전적인 웹 애플리케이션을 괴롭히던 문제를 제거하였다. 우리는 정말 이 모델을 좋아하였다. 왜냐하면 이것은 애플리케이션 로직을 데이터 검색에서 분리하였고, UI 코드를 단일 언어로 통합하고 실행할 때, 서버에 주는 충격을 상당히 줄여주었다. 그러나 이것은 요구사항들을 지원하지 않았다.
예를 들어, SPA가 SEO를 충분히 지원하기 위해서는 검색 엔진 인덱싱
[2]을 위해 서버에 DOM을 실행하는 것이 필요하다. SPA의 전송 경로는
브라우저 히스토리 API(browser history API)를 지원하지 않는 브라우저에서 위치 해쉬에 의존한다. 그것은 SEO에 적합하지 않다. SPA는 또한 내용을 뿌려주기 전에 데이터와 자원을 가져올 필요가 있다. 그래서 이 솔루션은 최적화된 페이지 요구사항을 충족하지 않았다. 첫 페이지 로드를 제공하는 서버에서 DOM이 실행되지 않는 한 말이다. 그런데 이것은 느리고 추가적으로 제공되는 자원이 필요하다. 우리는 단지 최소한의 요구사항들을 충족시키기 위해 추가적인 노력
[3]이 필요한 프레임워크를 만들기를 원치 않았다. 그래서 우리는 SPA에 대한 접근은 건너 뛰었다.
융합형 웹 애플리케이션우리가 평가한 마지막 모델은 융합형 웹 애플리케이션 모델
[4]이다. 그것은 UI 코드를 단일 코드 기반으로 통합한다는 의미에서 SPA와 유사하다. 그러나 그 코드는 클라이언트와 서버에서 동작할 수 있다. 한가지 좋은 예는 Airbnb의
Rendr이다. 이 모델은 SEO에 대한 충분한 지원을 하고 최적화된 페이지 로드를 하는 서버에서 첫 페이지 응답을 표현하는데 애플리케이션에 유연성을 제공한다. 이것은 어떠한 추가 노력 없이도 우리의 최소 요구사항들을 충족시키는 것에 도움을 줄 수 있다.
선택우리는 융합형 웹 애플리케이션으로 가기로 결정했다. 그것이 요구사항들을 충족하기 때문이다. 아직도 앞으로 생각할 것들을 고려해 볼 때 모든 이해 관계자들에게 가장 좋게 제공한다. 아래는 우리가 프로세스를 만드는 결정을 하는 사이에 떠오른 몇 가지 생각이다.
-
우리는 UI는 UI 엔지니어들에 속해야 한다(UI should belong to the UI engineers)고 생각했다. 그것이 클라이언트에 있던지 서버에 있던지. 그리고 백엔드와 프론트엔드 사이에 명확한 분리 선을 좋아한다. 이러한 분리는 두 엔지니어링 팀들을 더 행복하게 해주고 개발을 더 깔끔하게 해준다.
-
우리는 히스토리 API를 제공하는 이어지는 클라이언트의 페이지 요청들을 위해 SPA 모델의 분산 구현을 좋아했다; 이 접근은 서버의 부담을 줄여주었다.
-
우리는 격이 다를 정도로 완전 양질의 URL과 히스토리 API를 지원하지 않았던 클라이언트를 위해 서버 구현에 대한 적절한 대비책을 지원할 수 있다는 생각을 좋아했다; 이것은 애를 쓰지 않고도 SEO 지원을 해주었다.
-
우리는 수명 주기의 일반적인 구현과 함께 UI는 단일 코드 기반으로 하기를 좋아했다. 이것은 어떤 중복된 노력이 없다는 것을 의미하고, 그래서 UI 개발 비용을 줄일 수 있었다는 것을 의미한다.
-
단일 UI 코드 기반을 가지는 것은 유지보수하기가 쉬울 것이다. 그것은 우리가 특징들을 더 빨리 파악한다는 것을 의미한다.
최종 결과
시장에 현재 존재하는 것을 평가한 후에, 우리는 결국
LazoJS라는 새로운 하이브리드 웹 프레임워크를 제작하였다. LazoJS의 중요한 부분과 수명 주기에 대해 고차원의 시각으로 살펴보기로 하자. LazoJS
wiki에서 더 많은 정보를 확인 할 수 있다.
왜 새로운 것이라야 하는가?우리는 뭔가 새로운 것을 만들었다. 왜냐하면 우리의 요구사항을 충족할 것은 아무 것도 없었기 때문이다. 우리는 분명히 다른 라이브러리들로부터 배웠고 그것들을 확장했었다. 그러나 결국 우리는 프런트 엔드 엔지니어들에게 잘 맞는 인터페이스와, 많은 대중을 상대로 하는 웹사이트들에서 힘을 발휘할 수 있도록 디자인되고 준비되고 완전히 개발된 동형 자바스크립트 프레임워크 제품이 필요했다.
요청 수명 주기Routes는 구성요소의 액션과 관련 있다. 이러한 액션들은 페이지 응답을 반환하는 책임이 있다.
특정 클라이언트가 하는 시작 페이지 요청은 SEO 지원과 최적화된 페이지 로드를 제공하기 위해 서버에 전달된다.
[클라이언트에게 첫번째 페이지 응답은 SEO지원과 최적화된 페이지 로드를 위해 서버에 전달된다.]
그것이 히스토리 API를 지원한다면, 특정 클라이언트가 다음에 하는 페이지 요청들은 클라이언트에서 실행된다. 이것은 서버에 부담을 줄여주고 클라이언트의 응답속도를 개선해준다.
[클라이언트가 하는 그 다음 요청은 해석을 분산하고 성능을 향상시키기 위해 클라이언트에서 해석된다]
핵심 부분들LazoJS 는 현존하는 오픈 소스 기술의 증명된 기술들 기반 위에 세워졌다:
애플리케이션 구조
우리는 LazoJS 애플리케이션이 한번만 보고도 이해될 정도로 아주 쉽기를 원했다. 그래서 우리는 간단한 구조를 결정했다.
환경 지정 코드는 "서버"와 "클라이언트" 디렉토리에 위치한다. 일반적인 RequireJS
로더는 서버 모듈을 클라이언트에, 클라이언트 모듈을 서버에 자동으로 건네준다.
이 구조는 새로운 개발자들이 참가 하고, 새로운 특징을 추가하고, 문제를 해결하는 것을 쉽게 해준다. 왜냐하면 개발자가 코드를 어디에 배치해 놓아야 하는지 알기 때문이다.
컴포넌트컴포넌트(Components)는 이러한 의미에서 재사용, 캡슐화, 구성이 LazoJS에서 구현한다. 이것들은 페이지 요청이 다중으로, 파라미터화된 MVC 초소 애플리케이션으로 분리되는 것을 허용한다. LazoJS components는 단일 페이지 요청과 다중 페이지 요청들을 걸쳐서 재사용되고 구성될 수 있다.
[Components 는 MVC pattern을 그들 자신의 수명 주기와 함께 재사용 가능한 초소형 애플리케이션으로 캡슐화한다]
Components는 액션 기능들을 수행한다. Component의 액션 최종 결과는 클라이언트에게 마크업과 DOM 바인딩이다.
모델LazoJS 는 Backbone Model과 Collection을 확장하는데 이것들은 클라이언트와 서버에서 기동하는 것이 가능하다. 이러한 동형 기능에 더불어, LajoJS는 또한 서버 데이터 수집기, 모델과 콜렉션 CRUD 작업을 백업하는
동기화기(synchers)를 가지고 있다. 이것들은 다른 것들 보다 개발할 때 서비스를 정지시키거나 UI 요구사항을 충족시키기 위한 서비스 종료시점
[5]을 깨뜨리는데 유용하다.
[LazoJS 모델, 수명 주기 모음]
로드맵LazoJS는 아직 유아기에 있다. 그러나 안정된
API를 가지고 있고 생산에 힘을 주는 애플리케이션이다. 우리는 개발 중에 마스터한 상태에서 최첨단으로 가동하였다. 그리고 충분히 검증된 새로운 버전을 한번 출시하였고 지금 생산에 가동되고 있다.
Github에 기능 개선된 목록이 있고 내부적으로 현재 우선순위가 매겨져 있다. 게다가 나는
애플리케이션 생성기(application generator)를 만들고 있는 중인데 더 쉽게 애플리케이션 개발 속도를 높이도록 해준다. 나는 LajoJS API에 단순한 개선 외에 어떤 엄청난 변화를 보지 못했다. 그래서 그것은 사용되어질 준비가 되어 있다.
*****
[1] 소프트웨어의 죽음은 진행 중이다. 그리고 그것은 좋은 일이다. 그러나 또한 중요한 것은 당신이 제작한 것이 일찍 교체되어야 할 때 그것에 의존하는 애플리케이션에서 일시적인 것이 아니라, 애플리케이션에서 불필요한 불안정을 만드는지 확인하는 것이 중요하다.
[2] Google은 최근에 자바스크립트 애플리케이션들을 위해 인덱싱 지원(indexing support)을 발표했다. 그러나 Google은 말하길 "때로는 사물이 표현될 때 완벽하게 되지 않고 있다", 그리고 또 애플리케이션이 처리과정에서 실패하고 다른 검색엔진을 지원하고자 한다면 "당신의 사이트를 적당한 수준으로 낮추는 것이 언제나 좋은 생각이다"라고 말했다.
[3] 만약 당신이 이미 현재 사용되는SPA 솔루션에 거대한 투자를 하고 있다면 서버에서 DOM을 가동하거나 DOM을 모방하는 것은 가능한 선택이 될 수도 있다는 것은 이해할만하다.
[4] 이 모델은 때때로 동형 자바스크립트 또는 "성배"로서 참조된다.
[5] 이것은 클라이언트로부터 온 네트워크 요청을 한가지로 번역한다. 왜냐하면 그것은 보조 동기화기를 대리하는 모델을 위해 한번 호출을 하기 때문이다.
편집자 주: 당신이 프런트 엔드 자바스크립트에 대해 더 깊이 파는 것을 찾는다면, 재로드 오버슨과 제이슨 스트림펠이 쓴
Web Components를 점검하기를 원할 것이다.