AngularJS에서 Vue로 전환하면서 배운 것


프롤로그

나는 NHN에서 협업도구인 Dooray!를 개발하고 있다. 프로젝트, 메일, 메신저, 캘린더, 드라이브, 위키, 주소록, 칸반 등 방대한 기능을 담은 서비스이며 약 5년 전부터 개발되기 시작하여 현재까지 잘 유지되고 있는 서비스다. Dooray는 프로젝트 초기에 가장 핫한 프레임워크인 AngularJS를 선택했고 현재까지도 AngularJS로 대부분의 프론트엔드 개발을 하고 있다. AngularJS는 1.7x버전 대에서 이제 생을 마감하여 유지보수 정도만 진행되고 있기 때문에 프로젝트를 계속 AngularJS로 개발해도 되는지에 대한 논의와 불안함에 있었는데, Dooray!팀에서 VueJS를 다음 프론트엔드 프레임워크로 결정하게 되었다. 어떤 프레임워크가 좋으냐는 뜨거운 감자로 항상 논쟁이 많다. 왜 Vue를 선택했냐는 끝나지 않을 이야기는 접어 두고, 어쨌든 프레임워크를 전환하면서 배운 것을 이 글에서 공유하고자 한다. AngularJS가 여전히 높은 점유율을 가지고 있으므로 우리와 같은 고민을 하는 회사와 개발자가 많을 것이라고 짐작한다. 이 글에서 다룰 내용은 뻔할 수도 있지만 프레임워크를 전환할 때 꼭 챙기기를 권장한다.

프레임워크 전환 전에 챙겨야할 사항

프레임워크 전환은 신규 기능을 추가하고 버그를 수정하는 것이 아니므로 전환 후에도 전환 전의 서비스와 동일한 기능을 유지해야 한다. 이 때 필요한 것이 보통 회귀 테스트인데, 기존 기능들이 여전히 잘 동작하는지 테스트할 수 있는 방법을 미리 마련해두고 시작하는 것이 좋다.

서비스 기획서 확보

그러기 위해서 내가 먼저 찾았던 것은 기획서다. 서비스를 개발한 기획자와 개발자가 여전히 같이 일을 하거나 같은 회사에 있는 경우는 그나마 운이 좋은 경우라고 할 수 있다. 서비스의 기능과 히스토리를 인수인계 받을 수 있고 문제가 생길 경우 문의를 할 수 있기 때문이다. 그리고 기획서도 남아 있을 확률이 높다!

기획서는 서비스의 거의 모든 기능 명세를 나타내고 있으므로 이 명세를 파악해야 한다. 어떤 개발을 어떻게 해야 하고 구현하는데 얼마나 걸릴지 가늠을 할 수 있기 때문이다. 그리고 화면과 기능 흐름에 따라 구현 순서에 의존성이 생기므로 기능 명세 파악은 더욱 중요하다고 강조하고 싶다. 만일 기능 파악이 덜 되어 나중에 부랴부랴 구현해야 하는 경우를 상상해 보면 등에서 식은 땀이 날 것이다(이미 내 등은 땀에 다 젖었었다).

이와 관련한 내 경험은 검색 기능 관련이었는데, 검색 UI가 화면 상 AngularJS에 있어서 Vue로 개발할 부분인줄 몰랐던 것이다. AngularJS로 구현된 검색영역에서 검색어를 입력하면 Vue 영역에서 검색 결과가 보여져야 하는 기능 명세를 한참 개발하다가 알게 되었다. 부족한 기간에 이 기능을 구현하기 위해서 엄청난 코드 타이핑으로 개발을 했다. 아마 이걸 개발하다가 내 맥북 키보드의 키캡이 떨어진게 아닌가 싶다.

1 두레이 주소록 캡쳐화면과 중간의 Vue영역 표시, 녹색 영역이 AngularJS로 구현된 검색UI이다.

만약 서비스 기획서가 없다면 서비스를 사랑하는 마음으로 모든 기능을 빠짐없이 철저히 완벽하게 사용해보고 기능 파악을 해야 한다! 나처럼! 오예~

QA 테스트 케이스 시트 확보

QA의 테스트 케이스 확보 또한 성공적인 프레임워크 전환을 위해 중요한 자료이다. 물론 여러분의 서비스 기획서가 아주 상세하고 훌륭하겠지만, QA팀의 테스트 케이스 시트는 사용자 입장에서 기능과 화면의 흐름을 보다 꼼꼼하게 검증할 수 있기 때문에(적어도 Dooray!팀의 QA시트는 그렇다) 기획서에서 나타나지 않지만 중요한 기능을 검증할 수 있다.

나의 경우는 기획서가 없어서 오히려 이 문서가 더 소중했다. 왜냐하면 QA 테스트 케이스를 보면서 몰랐던 기능을 파악한 적도 많았기 때문이다. Dooray! 주소록 서비스의 QA 테스트 케이스는 약 300개 정도인데, 화면별, 기능별, 영역별로 잘 짜여져 있어서 기능 파악을 하는데 크게 도움이 되었다. 그리고 꼭 당부하고 싶은 것은 QA 시트를 속독하지 말고 여러 번 정독하라는 것이다. 정독하면서 실제 서비스에서 한번씩 기능을 확인해서 눈과 뇌에 새겨라. 그래야 또 식은 땀나는 상황을 만들지 않을 것이다.

코드를 통한 기능 파악

두 문서를 통한 사전 기능 파악이 잘 되었다고 하더라도 코드 기반의 기능 파악도 꼭 필요하다. 나 같은 경우는 AngularJS에서 Vue로 전환하는 것이므로 프레임워크에 종속적인 코드를 제외하고는 거의 새로 구현해야 할 것이다(혹은 함수 단위별로 코드를 잘 이전하던가). 코드를 통한 기능 파악에서 강조하고 싶은 부분은 UI라이브러리가 바뀌는 경우이다. AngularJS 기반의 라이브러리의 경우 동일한 Vue 라이브러리가 있는지 조사해 보아야 한다. 기 구현된 어떤 컴포넌트는 상속이나 포크 등의 방법으로 커스텀 구현한 것일 수도 있다.

Dooray! 주소록은 부트스트랩을 사용하고 있었고 Vue로 넘어가면서는 element-ui를 사용하기로 했다. UI라이브러리가 달라지기 때문에 컴포넌트의 기능과 디자인, 세부적인 동작(트랜지션 등)도 달라진다. 이로 인해 개발해야 했던 사항들은 element-ui에 서비스 공통 디자인을 적용(css 오버라이드 포함), AngularJS에서 포크나 커스텀 구현한 컴포넌트나 코드의 재구현, element-ui에 딱 맞는 컴포넌트가 없어서 새로 개발한 컴포넌트 등이 있었다. AngularJS에서 Vue로 전환하고 난 후 가장 아쉬웠던 점이 사전 기능 파악이다. 그러므로 중요한 기획서 확보, QA 테스트 케이스 확보, 코드를 통한 개발 기능 파악이 매우 중요하다고 생각한다. 그 후 개발 계획을 잘 세워야 하는 것이다.

개발 계획 세우기(WBS 작성)

개발 방법론이나 관리 방법, 개인의 성향 등에 따라 사용하는 방법은 천차만별이므로 어떻게 계획을 세우라는 이야기는 하지 않겠다. 다만, 계획 세우기에 대해서 말하고 싶은 것은 다시 한 번 기존 기능을 최대한 파악하라는 것이다.

  • 서비스를 직접 사용하면서 기능 파악하기
  • 기획서를 확보하고 기능 파악하기
  • QA 시트를 보고 기능 파악하기
  • 코드를 보고 기능 파악하기

개발 계획을 세울 때 예측과 결과의 격차를 최대한 좁히는데 도움이 될 것이다.

프레임워크 전환 후 회귀 테스트

스프린트가 끝나갈 무렵 QA 전에 나를 포함한 개발자가 회귀 테스트를 진행하였다. 물론 QA팀에 Full QA 요청을 한 상태라 테스트 커버리지가 올라갈 것이지만, 개발자의 경우 본인이 구현한 코드를 알고 테스트를 할 때 엣지 케이스를 좀 더 테스트를 더할 수 있지 않을까 생각했다. 최초 목표는 성공율 95%였는데, 실제로 회귀 테스트를 해보니 성공율이 85%였다. 2222

그리고 Full QA를 4일 동안 진행하였고 검출된 이슈는 약 70개가 넘었다. 이슈의 원인으로 종류를 구분해 보니 사전 기능 파악이 부족해서 발생한 이슈가 약 30%였다. 어떻게 보면 발생하지 않아도 될 이슈가 발생해서 다소 아쉬웠다. 스프린트 회고 회의에서도 공통적으로 나온 의견이었다. 33333 이슈 원인 챠트

지금 생각해보면 사전 기능 파악이 잘 되었다면 QA기간 동안 폭풍과 같은 이슈처리를 약간 쎈 바람 정도로 낮출 수 있지 않을까 하는 생각을 한다. 우여곡절이 많았지만 결국은 팀원의 각고의 노력으로 Dooray! 주소록의 Vue 프레임워크 전환은 무사히 끝났다. 기쁘다.

프레임워크 전환 후 성능 테스트

프레임워크를 전환을 계획할 때 큰 고민은 성능이 어떻게 될까였다. Dooray!는 SPA로 개발되어 있었고 각 서비스는 상단에 다음 그림과 같이 탭 형태로 되어 있다. 모든 서비스를 한꺼번에 Vue로 전환하기는 난이도, 일정, 유지보수 측면에서 매우 어려운 과제이므로 이 탭 중 하나의 서비스만 Vue로 전환하기로 했다. 44

웹 페이지 구조 결정

크게 세 가지 형태로 검토가 되었고 각각의 장단점이 있었다. 이는 성능과도 밀접하게 연관된다. 우리와 같은 고민을 하고 있는 개발자라면 도움이 되는 내용일 것이다.

첫 번째 방법은 SPA를 포기하고 별도의 페이지로 분리하는 것이다. Vue를 사용하여 별도의 페이지로 개발하면 되므로 개발하는데 크게 어려움은 없어 보였다. 기존 구현과 새로운 구현의 CSS가 잘 분리될 것이고, 웹팩을 사용하여 필요한 파일만 번들되도록 처리할 수가 있을 것이기 때문에 첫 번째 대안이었다. 단점이 하나 있다면 페이지 전환 시 깜빡임이 일어나서 하나의 애플리케이션으로 보이는 SPA의 장점이 사라진다는 것이었다. 리소스를 새로 로딩해야하기 때문에 성능도 느려져 보일 것이다. 쉽게 수용하기는 어려운 단점이라고 생각한다.

두 번째 방법은 SPA를 유지하면서 Vue 개발 영역을 iframe으로 처리하는 것이다. 첫 번째 방법의 장점은 모두 수용하는 방법인데, 프로토타이핑 결과 메인 프레임과 자식 프레임 간의 메시지를 주고 받는 방식으로 데이터 전달도 크게 문제가 없었다. 가장 큰 장점은 Shadow DOM처럼 CSS를 분리할 수 있다는 장점이라고 생각한다. 방대한 소스에서 예측하기 힘든 CSS 충돌을 방지할 수 있는 것이다. 가장 큰 단점은 감정적인 것이었다. 지금이 어느 때인데 iframe이라니? iframe이라니? 다음 세 번째 방법을 프로토타이핑한 후에는 깔끔하게 포기했다. 참 잘했다.

세 번째 방법도 SPA를 유지하면서 AngularJS 내부에 Vue컴포넌트를 직접 삽입하는 형태이다. 찾아보니 ng-vue 라이브러리도 있었는데 사용방법이 다소 어렵고 원리를 생각하면 직접 구현하는 것이 어렵지 않다고 판단했다. AngularJS는 특정 DOM 하위는 AngularJS컴파일을 하지 않고 순수한 DOM 형태로 둘 수 있는 ng-non-bindable이 있다. 다음 예제처럼 이 디렉티브를 사용하면 쉽게 Vue를 삽입할 수 있다.

AngularJS 템플릿의 ng-non-bindable

<div class="contact-vue-component" ng-non-bindable>
  <div class="vue-wrapper-element"></div>
</div>

AngularJS 컴포넌트 컨트롤러에서 직접 Vue를 생성한다

this.$onInit = () => {
  this.component = new Vue({
    el: $element.find(".vue-wrapper-element")[0],
    store,
    router,
    components: {
      ServiceMain
    },
    data() {
      return {
        state: "nice state"
      };
    },
    template: `
<service-main component-name="ContactBodyContainer" :state="state"></service-main>`
  });
};

우리는 이 세번째 방법을 선택하기로 했다. 그리고 점차 Vue 컴포넌트가 차지하는 화면 영역이 넓어지면서 서서히 AngularJS가 페이드아웃 되고 완전히 Vue로 전환이 될 것이다.

그래서 성능은?

프레임워크 전환 후 성능이 어떻게 되었는지를 이야기 하기 위해서 웹 페이지의 구조를 어떻게 결정했는지 설명했다. 1, 2번째 방법처럼 별도의 페이지로 분리하지 않는 것이기 때문에 기존 AngularJS에서 사용하는 모든 리소스에다가 새로 개발될 Vue에서 사용하는 모든 리소스가 추가되어야 한다. 그러므로 성능도 더 느려지지 않을까 추측했다. 결과를 먼저 말하면 이번 프레임워크 전환은 다행히 더 느려지지 않았다.

크롬 개발자 도구의 네트워크와 퍼포먼스, Audits를 사용하여 프레임워크 전환 전후를 측정하였다.

로딩 성능

다음은 몇 가지 로딩 성능 측정 자료이다.

이벤트 AngularJS AngularJS + Vue
DCL(DOMContentLoaded) 1900 ms 1922 ms
Loaded(L) 3856 ms 3666 ms
FMP(First Meaningful Paint) 5896 ms 3722 ms

DCL은 HTML 파일의 용량과 포함된 자바스크립트, CSS파일의 갯수에 영향을 받는 수치다. 서버 사이드 렌더링이 없는 SPA이므로 HTML파일은 크기 변화가 없었고, 자바스크립트와 CSS리소스 구성의 변화도 성능을 떨어뜨리지 않았음을 알 수 있다. Loaded 이벤트 또한 리소스 구성에 있었음에도 불구하고 성능이 저하되지 않았다. 그러나 로딩 속도에서 중요하게 사용하는 지표인 FMP는 약 2초 정도 빨라진 것을 볼 수 있다. 퍼포먼스 탭에서 측정 자료를 분석해 보니 AngularJS의 부트스트랩 함수 호출 시간이 2초 정도 줄어든 것으로 확인되었다. AngularJS의 부트스트랩 시간이 줄어들고 Vue의 초기화 시간은 그에 비해 무척 빠른 것으로 판단된다.

전체적인 로딩 속도 측면에서 보면 리소스의 로딩과 처리에서는 성능이 저하되지 않았고 AngularJS의 부트스트랩 시간을 줄이므로써 FMP가 약 2초 정도 빨라졌기 때문에 로딩 성능은 더 좋아졌다고 볼 수가 있겠다.

AngularJS의 퍼포먼스 측정 화면 55 AngularJS + Vue의 퍼포먼스 측정 화면 66

리소스 요청 비교

프레임워크를 바꾸었기 때문에 리소스의 갯수와 용량은 당연히 변하였다. 주요 리소스의 요청 갯수와 용량에 대한 자료이다.

AngularJS AngularJS + Vue 비고
JS 크기 11.7 MB 10.9 MB
JS 리소스 갯수 29 개 32 개
CSS 크기 2.2 MB 3.0 MB
CSS 리소스 갯수 10 개 12 개
XHR 응답 크기 6.9 MB 5.6 MB API호출 1개 증가로 1.2KB 증가함
(개발자 도구에서 서비스 워커의 JS, CSS다운로드도
XHR로 기록되므로 API 기준으로 증가한 수치가 1.2KB이다)
XHR 요청 갯수 38 개 37 개 API 호출은 기존 대비 1개 증가됨

자바스크립트 용량이 줄어든 것은 언뜻 이해가 되지 않고 이번 배포에 프레임워크 전환 작업만 포함된 것이 아니라서 의미 있는 자료로 보기는 어려웠다. CSS도 마찬가지겠지만 예상한대로 element-ui를 사용하였기 때문에 용량이 다소 증가했다. 작업하면서 신경 썼던 XHR 요청갯수와 용량의 경우는 의도한 대로 딱 1개만 증가했다. 이전 대비 불필요한 XHR이 없도록 구현되어 이 점은 만족스러웠다.

프레임워크를 전환하며

서비스의 프레임워크를 바꾸기 위해서는 많은 노력이 든다. 이 글에서는 구현도 중요하지만 그 사전 준비가 매우 중요함을 강조하였다. 기능 파악을 잘 하고 빠지거나 부족한 기능이 없이 구현해야 한다. 만약 원래 되던 기능이 안되면 사용자 입장에서는 매우 불편할 수 밖에 없다. 심지어 신규 기능이 들어간 것이 아니므로 사용자는 프레임워크가 바뀐 줄도 모를 것이다! 그리고 웹 페이지 구조를 AngularJS 내부에 Vue를 포함하는 것으로 결정했기 때문에 성능을 잘 고려하면서 구현해야 하는 것도 중요하다. 프레임워크를 전환하기 위하여 필요한 전체적인 흐름을 정리하며 이 글을 마친다.

  • 사전 기능 파악

    • 서비스 기획서 확보와 정독
    • QA 테스트 케이스 시트 확보와 정독 + 직접 테스트해보기
    • 코드를 통한 기능 파악
  • 개발 계획 잘 세우기
  • 프레임워크 전환 전후 성능 측정 하기

이 글이 도움이 되었길 바란다.

P.S. AngularJS와 Vue가 동시에 돌아가는 서비스를 경험해 보고 싶다면 지금 바로 Dooray!의 주소록과 프로젝트 칸반보드를 사용해보라. 무료체험 링크이다.


유동식, FE Development Lab2019.04.19Back to list