서비스 운영 및 관리
헐레벌떡 서비스를 런칭하고 운영 상황에 돌입하고 돌아보니, 뭔가 매우 많이 억울했다. 정신없던 시간이 지나가고 다시 생각해 보았을 때, 차라리 디자인 가이드라인만 외주한테 공급받고 밑바닥부터 내가 개발했었다면 상황이 더 나았을 거라는 생각이 들었다. 동작하지도 않고 재사용 할수도 없는 외주업체의 코드를 매일 마이그레이션 하고 conflict를 수정하는 상황에서 구현되지 않은 기능을 모두 내가 구현했으니 외주가 싸 놓은 똥을 내가 치우는 것으로 모자라 그들의 작업 비용까지 내가 보전해 주는 셈이 되었다.
외주가 얼마나 허접했는지를 설명하자면 끝도 없지만 요약하면 다음과 같다.
- 디자인 가이드라인은 실제 시스템에서 사용하는 데이터의 형태를 고려하지 않고 제작되었다.
(예를들면, 표 A열의 값 데이터 형태는 UUID v4 형식이지만, 이를 무시하고 매우 짧은 텍스트를 기준으로 UI 가이드라인을 작성함) - 퍼블리싱 및 기능구현을 담당했던 외주 개발자는 1명이었으며, vue 개발을 해 본 경험이 있는지 의문이 들 정도의 실력이었다.
- 그가 사용한 스타일 시트는 어떤 툴에서 생성해 낸 값을 단순히 복붙한 형태로만 구현된 것으로 보였으며, 분명 동일한 UI 인데도 스타일시트가 재사용되지 않고 똑같은 코드로 복붙되어 있었음
- 구현할 페이지는 대략 10 페이지 정도 되었으나, 이 중 정상적으로 노출되는 페이지는 하나도 없었고, 모두 내가 새로 구현했다.
- 외주에서 개발을 진행하는 동안 지속적으로 내가 요청사항을 업데이트 해 주었으나, 정상적으로 구현되지 못하였다.
- 일례로 SPA로 구현 중이던 페이지 중 한 페이지만 일부를 Nuxt 프로젝트로 릴리즈 해 줄 것을 (문서로 명확히) 요청하였으나, 작업하던 SPA 프로젝트의 구현을 중단하고 Nuxt 프로젝트로 1 페이지부터 새로 구현하고 있었음...
- 그리고 이 시점은 이미 일정이 초과된 시점이었기에 그냥 포기하고 자체개발로 전환한지 오래였음
- 참고로 우리 프로젝트는 SPA 기반 구현이었다.
- 기본 요청사항도 구현하지 못하는 상황이었는데 어쩌면 당연한 결과였을지도 모른다.
서비스를 런칭하기까지 내가 구현한 코드가 60%를 훨씬 넘긴 상황에서, 어쨌든 재사용 하기도 애매해진 외주의 코드를 떠안은 채 나는 서비스를 운영하면서 신규 기능 구현 요청을 구현하게 되었는데, 이렇게 쌓여있던 코드 쓰레기들로 인해 개발 진도가 잘 나가지 못하게 되었다. 스타일시트는 쓸데없이 외주코드 > SD템플릿의 styled component 코드 > UI라이브러리(Antdv) 스타일 순으로 중복되어있었으며, 이를 피해 스타일을 적절히 적용하기도 쉽지 않았고 SD 템플릿이 중복 구현했던 UI 컴포넌트는 완전하지 않은 상태로 노출되고 있어 UI개발이 쉽지 않았다.
다른 UI라이브러리를 사용하는 것도 고려했었는데, 당시는 Vue3 초반인 상황이어서 Vuetify와 같은 대형 라이브러리도 정식 릴리즈가 되지 못한 상황이었다.
외주의 코드를 버리자
결국 나는 외주와 관련된 코드를 모두 제거하기로 마음먹었다. 기억으로는 이게 2022년도 중반이었던 것 같다.
사용하지 않던 SD 템플릿 제거
외주 코드를 버리기 위해 어떤 작업부터 해야할지 감이 오지 않았는데, 가장 먼저 UI 구현에 가장 방해가 되는 styled component를 사용하던 SD 템플릿을 제거하는 것이 가장 좋아보였다. 우리 프로젝트에서는 해당 템플릿의 컴포넌트를 다양하게 사용하지 않았기 때문에, 사용하지 않는 컴포넌트와 관련된 파일부터 삭제하는 것으로 작업이 시작되었다.
SD템플릿의 코드는 꽤나 고약했는데, Ant Design Vue 컴포넌트를 읽어 styled component를 이용하여 새로운 디자인의 컴포넌트로 컨버팅하는 형태로 구현되어 있었다. 템플릿에서 구현해 놓은 컴포넌트를 그대로 사용했다면 아무런 문제가 없었을 테지만, 우리 프로젝트만의 고유 디자인 가이드라인이 있었고, 이를 구현하기 위해 이중으로 스타일이 입혀진 컴포넌트를 사용하는 것은 꽤나 번거로운 일이었다.
SD템플릿 코드를 Ant Design Vue 컴포넌트 기반으로 변경
솔직히 Pilot 프로젝트때 내가 구현했던 vue2 + vuetify 조합의 UI가 UI의 미려함과 성능면에서 모두 뛰어났던 터라 SD템플릿 컴포넌트와 Ant Design Vue(이하 Antdv)컴포넌트 또한 마음에 들지 않았다. Antdv 컴포넌트는 react 기반으로 만든 jsx 코드를 vue 컴포넌트로 wrapping 한 느낌의 컴포넌트였는데, 이상하게도 동작이 많이 느렸다.
그래도 어쩌겠는가, frontend 구현에 무한한 복잡성을 제공하던 템플릿의 컴포넌트를 당장 대체하기 위해서는 Antdv 컴포넌트가 필요했고, 일단은 Antdv컴포넌트 기반으로 모든 UI를 변경하였다.(물론 자체 디자인가이드라인에 맞는 스타일 커스터마이징과 함께)
이 일은 꽤나 고통스러운 일이었는데, 다행히도 UI대체가 완료되고 SD템플릿 코드를 모두 제거할 수 있었다. 기간은 얼마나 걸렸는지는 잘 모르겠으나 2~3개월(풀타임은 아님) 정도 소요되었던 것 같다.
자체 컴포넌트를 구현하여 Antdv 제거
SD템플릿을 제거한지 얼마 지나지 않아 나는 Antdv 컴포넌트도 제거할 계획을 세웠다.
이 계획을 세우게 된 데에는 몇 가지 이유가 있었는데 가장 먼저 UI 커스터마이징이 여전히 불편했기 때문이었다. 우리 프로젝트는 자체 디자인 가이드라인이 있기 때문에 Antdv컴포넌트를 사용하려면 디자인 커스터마이징이 필수로 따라왔는데, 커스터마이징 할 요소가 너무 많아 작업 능률이 오르지 못했다.
다음 이유로는 성능이 너무 느렸다. 우리 프로젝트는 Data Table 컴포넌트의 복잡한 사용이 많은데, 기능 추가가 많아질 수록 Antdv 컴포넌트(a-table)의 반응속도가 매우 느려졌다. 그리고 해당 컴포넌트의 구조 특성상 UI커스터마이징도 쉽지 않았다.
마지막 이유로는 Vite 마이그레이션이 매끄럽지 못했기 때문이다. 사실 위 작업들을 진행하기 위한 선행연구로 webpack 기반 프로젝트였던 이 프로젝트에 Vite를 적용하는 것을 내부적으로 검토한 적이 있었는데, 이때 Antdv 라이브러리가 매끄럽게 동작하지 않았기 때문이었다. (예를들면, 로컬빌드 후 브라우저로 화면에 접근한 뒤 다른 페이지로 이동하면 Antdv라이브러리가 다시 로딩되면서 페이지가 새로고침 되는 현상 등이 있었다)
크게 위 세 가지 이유로 Antdv 컴포넌트를 제거할 계획을 하게 되었다.
자체 컴포넌트 개발
외주의 코드를 모두 버리고 초고속 빌드시스템인 Vite를 적용하기 위해서는 다음 작업이 선행되어야 했다.
- SD템플릿 제거
- Antdv 컴포넌트 및 라이브러리 제거
- Antdv 컴포넌트를 대체할 자체 UI컴포넌트 구현 및 적용
나는 우리 프로젝트 코드에 사용된 Antdv 컴포넌트 목록을 확인하기 시작했다. 간단하게는 a-spin부터 복잡하게는 a-table까지 정말 다양한 컴포넌트를 사용하고 있었다. 그리고 나는 하나씩 각개로 부수기로 마음먹었다.
Antdv 컴포넌트를 하나씩 자체 컴포넌트를 구현하면서 대체해 나갔다. 대체목적으로 구현하는 자체 컴포넌트는 Composition API를 적극 활용하는 SFC(Single File Component)로 구현하였다. 배워가면서 구현하다 보니 처음에는 속도가 잘 나오지 않았지만, script setup의 편리함 때문인지는 모르겠으나 익숙해질 수록 컴포넌트 구현이 수월해져 가는 것을 느꼈다.
Antdv 컴포넌트를 모두 자체 구현한 UI컴포넌트로 대체하는 과정도 꽤나 험난했다. 곳곳에 사용된 a-spin, grid 표현에 사용된 a-row/a-col 등, 자잘하게 많이 사용된 컴포넌트부터, this.$nexttick() 까지 호출해 가면서 마개조급 커스터마이징을 했던 a-table 컴포넌트까지 아주 다양했다. 그리고 각 컴포넌트에서 제공하는 다양한 props 및 기능들을 하나하나 구현해 가면서 UI를 대체해 갔다.
신규프로젝트의 시작
안타깝게도 위 작업을 진행하면서 새로운 소식이 들려왔다. 내 프로젝트 코드를 base로 하는(=동일 저장소를 사용하는) 신규 프로젝트의 개발이 시작되었다. 해당 프로젝트의 front 코드는 내가 구현했던 코드예제를 모두 모방하여 만들어졌다. 비록 내 프로젝트는 아니었으나, Antdv를 자체컴포넌트로 마이그레이션 하고 있던 나로서는 해당 프로젝트의 코드를 신경쓰지 않을 수 없었다.
게다가 해당 프로젝트를 개발하시는 분은 frontend와 backend까지 개발해야 하는 풀스택 개발 담당자이셨고 상대적으로 frontend 공통영역 작업에 기여할 만한 여유는 없어보였다.
모든 코드의 컨버팅
어쩔수 없이 나는 신규 UI컴포넌트를 구현하면서 신규 프로젝트의 코드까지 컨버팅 하는 작업을 진행하였다. 일이 더 늘어서 힘들었으나 그래도 컴포넌트가 하나하나 도장깨기 되는 모습을 볼때마다 뿌듯함도 느껴졌다. 그리고 생각보다 내가 만든 UI컴포넌트의 퍼포먼스도 나쁘지 않아 만족스러웠다.
그렇게 3개월 정도 흘렀을까... (정확하지 않다.) 모든 UI컴포넌트의 대체구현이 마무리 되었고 Antdv 라이브러리도 성공적으로 삭제할 수 있었다. 가장 만족스러운 부분이라면 가장 구현복잡도가 높았던 a-table 컴포넌트를 자체 컴포넌트로 대체구현한 결과, 사용법이 훨씬 간소화 되었고 UI동작 성능도 상당히 빨라졌음이 느껴졌다.(물론 수치적으로 비교테스트를 해본 것은 아니나, 눈으로 보기에도 한박자 빨라진게 느껴질 정도였다.)
(다음편에 계속)