20년 넘은 레거시 사이트에 Vue 기반 GNB / Footer 적용
목차
전 회사 메인 서비스는 20년 이상 운영된 레거시 환경 아래 구성되어 있었다. 그동안 수많은 기능이 추가되었지만, 적절한 시점에 리팩토링이 이루어지지 않은 채 확장만 반복되면서 코드 구조는 점점 복잡해졌고, 이른바 ‘스파게티 코드’ 상태가 되어 기존 코드를 분석하고 새로운 기능을 적용하는 과정 자체가 쉽지 않은 상태였다.
이러한 상황에서 PC 메인 서비스의 GNB(Global Navigation Bar)와 Footer를 전면 개편해야 했고, 기존 구조를 유지한 채 부분 수정으로 대응하기에는 한계가 분명했다.
단순한 UI 개선이 아니라, 일부 페이지는 Vue 기반으로 일부 페이지가 이미 동작하고 있었고, 향후 확장과 유지보수를 고려한 구조 개선이 필요하다고 판단해 GNB와 Footer를 Vue 기반으로 새롭게 만들기로 결정했다. 이 글에서는 이러한 환경에서 GNB를 어떻게 설계하고 적용했는지, 그리고 어떤 방식으로 문제를 해결했는지 정리해보려고 한다.
기존 구조 #
기존 GNB / Footer는 PHP 기반으로 구현되어 있었으며, 메뉴 변경이 필요할 때마다 업무 협조 요청을 통해 개발자가 직접 수정하는 방식이었다.
- 메뉴 변경이 드물다면 큰 문제가 되지 않았겠지만, 실제로는 변경 요청이 빈번했음
- 업무 담당자는 즉각적인 수정이 불가능해 답답함을 느꼈고, 개발자는 과거 구현 방식을 다시 파악한 후 작업을 진행해야 하는 부담이 생김
- 실제 변경 작업 중 오류가 종종 발생했으며, 이러한 경험이 반복되면서 이 업무를 업무 담당자 / 개발자 모두 부담스럽게 느끼게 되어버림
심지어 관리자 페이지에서 메뉴를 직접 수정할 수 있는 기능과 미리보기 기능이 존재하긴 했지만, 해당 기능에 대한 인수인계가 제대로 이루어지지 않았고, 사용 중 오류도 발생하면서 실질적으로 활용되지 못해 대부분의 메뉴 변경은 하드코딩 방식으로 처리하고 있었다.
또한 메뉴이용 사용자 통계 기능도 제공되지 않아, 업무 담당자가 사용자 흐름을 파악하는 데에도 어려움이 있었다.
이러한 구조는 단순한 불편함을 넘어, 지속적인 운영과 확장에 있어 명확한 한계로 작용하고 있었다.
리뉴얼 #
이러한 상황에서 담당 부서로부터 PC 페이지 GNB와 Footer에 대한 전면적인 개선 요청이 들어왔고, 기존 단점을 보완할 수 있도록 다음과 같은 기능들이 요구되었다.
- 담당자가 직접 메뉴 이름 변경, 메뉴 추가 / 삭제를 할 수 있어야 함
- 적용 전 미리 확인할 수 있는 Preview 기능 필요
- 메뉴 클릭에 대한 통계 기능 필요
- 광고 배너 교체 및 클릭 통계 기능 필요
- 리비전: 최근 n개의 GNB 정보를 저장해 필요 시 rollback 할 수 있는 기능 필요
이는 단순한 UI 변경이 아니라, 개발자 의존 구조를 운영 중심 구조로의 전환이었다.
구현 #
결론부터 말하면, 이번 GNB / Footer 리뉴얼은 Vite(Vue) 기반으로 구현한 후 라이브러리 형태로 빌드하여 기존 레거시 시스템에 적용하는 방식으로 구현했다.
과거 일부 컴포넌트를 빌드하여 웹 페이지에 적용한 경험이 있었고, 레거시 서비스 내 일부 페이지에서도 Vite(Vue) 기반 MPA 방식이 이미 운영 중이였기 때문에, 이를 바탕으로 레거시 환경에서도 Vue 기반 구조를 적용하는 것이 가능하다고 판단했다.
그리고 이번 GNB / Footer 개편을 계기로, 기존 레거시 페이지들도 이번 리뉴얼하는 GNB / Footer를 포함해 Vue 기반으로 전환하여 점진적으로 대체하는 방향을 고려해 단계별로 현대화 하는 기반을 마련하고자 했다 (해당 내용은 업무 담당자들과도 공유함).
또한 기존의 PHP 중심 레거시 방식을 유지하는 것은 장기적인 유지보수성과 확장성 측면에서 한계가 있다고 판단했다. 이에 따라, 향후 구조 개선과 개발 생산성을 고려하여 Vue 기반 구조를 도입하는 것이 더 적절하다고 판단했다.
개발에는 다음과 같은 기술을 사용했다.
- Vite (Vue), 라이브러리 빌드
- Tailwindcss, DaisyUI
- Typescript
- Prettier, ESLint, Commitlint 적용
- Node / Docker 기반 개발환경 구성
사용자 페이지 #
전 회사에서는 디자인팀에서 Vue 기반으로 퍼블리싱 해주어 디자인 측면에서는 큰 수정 없이 적용이 가능했고, 필요한 경우에는 협의를 통해 일부 수정만 진행했다.
다만 테스트 및 적용 과정에서 몇 가지 현실적인 이슈가 있었다.
테스트 환경의 부재 #
레거시 서비스에는 운영 환경과 동일한 조건의 개발 서버가 사실상 존재하지 않았다. (개발 서버와 운영 서버의 버전 차이로 인해 테스트 결과의 신뢰도가 낮았음)
이로 인해 운영 서버에 직접 적용하되, 특정 로그인 사용자에게만 새로운 GNB / Footer가 노출되도록 분기 처리하여 테스트를 진행했다.
페이지별 CSS 충돌 #
레거시 서비스는 페이지마다 서로 다른 스타일이 적용되어 있었기 때문에, GNB / Footer의 스타일이 페이지별로 다르게 깨지는 문제가 발생했다.
이를 해결하기 위해
- 전체 페이지를 담당 부서와 함께 점검하며 스타일을 일괄 수정
- 신규 GNB / Footer 기준으로 기존 스타일을 정리하고, 필요한 경우 컴포넌트 스타일도 함께 수정
- 사용되지 않는 레거시 페이지는 이 과정에서 함께 정리
하는 작업을 병행했다.
Vue 컴포넌트에 scoped 스타일을 적용했지만, 기존 레거시의 전역 스타일과 태그 기반 CSS가 우선 적용되면서 의도한 스타일이 유지되지 않는 문제가 있었다.
결과적으로 일부 영역에서는 스타일 충돌을 제어하기 위해 !important를 사용할 수밖에 없었으며, 이는 레거시 환경에서 안정적으로 동작시키기 위한 현실적인 선택이었다.
메뉴 데이터 #
GNB 메뉴 데이터는 페이지 로드 시마다 DB에서 조회하는 것은 비효율적이라고 판단하여, 메뉴 정보를 JSON 형태로 CDN에 저장한 후 이를 가져와 사용하는 구조로 변경했다.
일반적으로는 Redis와 같은 캐시를 사용하는 것이 적절하지만, 레거시 서비스의 배포 구조로 인해 이를 적용하기 어려운 상황이었다.
레거시 서비스는 FTP 기반으로 배포되고 있었으며,
- PR 이후 담당자가 직접 FTP 접속하여 배포
- 캐시 파일이 저장된 디렉토리가 그대로 노출됨
- 배포 과정에서 캐시가 변경되거나 삭제될 경우 서비스 전체에 영향 발생
과 같은 구조적 문제가 존재했다.
이러한 환경에서 기존 방식으로 캐시를 운영하는 것은 위험하다고 판단하여, 메뉴 데이터를 특정 담당자만 접근 가능한 CDN에 JSON 형태로 저장해 이를 사용하는 방식으로 변경해 DB 의존을 제거하고, 공통 데이터를 보다 안정적으로 제공할 수 있도록 했다.
관리자 페이지 #
관리자 페이지는 별도의 팀원이 담당하여 개발을 진행했으며, 나는 전체 구조 방향 설정과 주요 기능 설계, 그리고 사용자 페이지 적용에 집중했다.
관리자 페이지에서는 다음과 같은 기능을 중심으로 구현되었다.
- 메뉴 변경 이력 저장 (사용자 정보 포함)
- 메뉴 구조 미리보기 기능
- CDN 기반 JSON 캐시 생성 및 배포
로그 #
담당자가 메뉴 정보 편집 후 저장 버튼을 누를 때 전체 메뉴 정보를 JSON 형태로 사용자 정보와 날짜와 함께 DB에 저장하였고 이를 관리자 페이지에서 볼 수 있도록 구현했다.
미리보기 #
이번 구현의 요구사항 중 하나인 미리보기 기능은 사용자 페이지에서 사용하는 Vue 컴포넌트를 그대로 재사용하여 구현했다.
DB에 저장된 메뉴 데이터를 불러온 후, 컴포넌트에 props 형태로 전달하여 실제 적용 모습과 동일하게 렌더링되도록 구성했다.
캐시 #
레거시 서비스는 콘텐츠, 쇼핑몰 등 여러 서비스가 동일한 DB를 사용하고 있었기 때문에
DB 부하가 빈번하게 발생하는 구조였다.
이러한 환경에서 GNB 메뉴까지 매번 DB에서 조회하는 것은 비효율적이라고 판단했다.
따라서 메뉴 데이터를 CDN에 JSON 형태로 저장하고, 사용자 페이지에서는 이를 직접 조회하도록 구성했다.
다만 CDN은 캐싱된 콘텐츠를 제공하는 특성상, 동일한 파일을 업로드해도 즉시 반영되지 않는 문제가 있었다.
이를 해결하기 위해 CDN의 무효화(Invalidation) 기능을 활용하여 메뉴 변경 시 캐시를 즉시 무효화하고 최신 데이터가 반영되도록 처리했다.
해당 기능은 관리자 페이지 구현을 담당한 팀원이 개발을 진행했으며, 나는 CDN Invalidation 방식과 적용 방향을 정의하고 관련 자료를 공유하여 구현이 가능하도록 지원했다.
적용 #
구현 완료한 후 업무 담당자들과 최종 테스트 및 레거시 전 페이지 대상으로 이상 없는지 확인 후 적용했다.
전체 업무 기간은 약 3개월 가량 소요되었고 적용 이후 별다른 이슈 없이 안정적으로 운영되었으며, 메뉴 변경 및 관리 측면에서도 소모시간과 커뮤니케이 비용 또한 감소되었다.
결론 #
이번 GNB / Footer 리뉴얼은 단순한 UI 개편이 아니라, 레거시 시스템을 점진적으로 현대화하기 위한 구조적 개선 작업이었다.
기존에는 메뉴 관리가 개발자에게 의존하고 있었지만, 이번 개편을 통해 담당자가 직접 관리할 수 있는 구조로 전환되었다. 또한 Vue 기반 구조를 도입함으로써, 기존 레거시 페이지를 유지한 채 점진적으로 개편해 나갈 수 있는 기반을 마련할 수 있었다.
이 과정에서 이상적인 구조를 적용하기보다는, 현재 시스템 환경에 맞게 현실적인 타협을 하며 안정적으로 적용했다.
적용 이후에는 담당 부서에서도 레거시 시스템이 점진적으로 개선되는 과정을 체감할 수 있었고, 다른 서비스(쇼핑몰)에도 동일한 방식으로 적용하고 싶다는 의견이 나오기도 했다.
결과적으로, 이 업무는 개발과 운영 모두에서 만족할 수 있는 결과를 만들어낸 사례였다고 생각한다.
회고 #
시간이 흐른 뒤 이 글을 정리하면서, 이번 업무를 진행하며 몇 가지를 다시 돌아보게 되었다.
팀원에게 기회를 #
이번 업무에서는 CSS 레이아웃 수정과 같은 단순 대응보다는, 개발 비중이 높은 관리자 페이지 기능을 팀원에게 맡기기로 했다 (당시 나의 일정도 영향을 주었지만, 의도적인 선택이기도 했다).
이 팀원은 3년차 개발자로, 레거시 유지보수 외에도 신규 프로젝트를 몇 차례 경험한 상태였다. 이번 기회를 통해 단순 구현을 넘어,
- 사용자 관점에서의 입력(Form Validation) 처리
- CDN 기반 캐싱 구조 이해 및 Invalidation 적용
- 관리자 UI 구현
과 같은, 이전과는 다른 개발 경험을 할 수 있도록 하고자 했다.
개발은 단순히 기능을 구현하는 것보다,
새로운 문제를 해결하고 그 과정에서 성장하는 경험이 중요하다고 생각한다.
이번 업무를 통해 이 팀원이 새로운 영역을 경험하고, 개발에 대한 흥미와 함께 한 단계 성장했다는 느낌을 받을 수 있기를 바랐다.
기술 부채 #
앞서 언급한 것처럼, 20년 이상의 기술 부채를 가지고 있던 레거시 서비스에 Vue 컴포넌트 기반의 GNB / Footer를 적용했고, 향후 레거시 페이지를 점진적으로 교체할 수 있는 기반을 마련했다.
다만 시간이 지나고 돌아보니, 이 구조가 조직 전체를 고려했을 때도 적절한 선택이었는지에 대해 생각을 하게 되었다.
다른 팀원들 또한 Vue를 다룰 수 있었기 때문에 기술적으로는 충분히 이어서 개발이 가능한 상태였지만, 테스트 및 배포 프로세스가 충분히 정립되어 있지 않은 상황이었다.
결과적으로, 레거시 환경에서의 기술 도입이 또 다른 형태의 기술 부채로 이어질 가능성도 있었던 것은 아닌지 고민하게 되었다.
개인적으로는 20년 넘는 레거시는 반드시 개선이 필요했기 때문에 이와 같이 진행은 했겠지만, 부족했던 테스트 및 배포, 기타 환경 구성의 필요한 시스템도 같이 진행 했을 것 같다.
문화 부채 #
오랜 기간 누적된 문제는 코드에만 남는 것이 아니라, 업무 방식과 의사결정 구조에도 함께 쌓이게 된다.
그동안 충분히 정리되지 않은 코드 위에 기능이 계속 추가되었고, 문제가 발생하면 이를 수정하는 방식이 반복되었다. 이러한 구조 속에서 후임 개발자들은 기존 코드를 이해하고 수정하는 데 많은 시간을 소모해야 했다.
개발 인력은 부족했고, 근본적인 개선을 진행할 수 있는 시간도 충분히 주어지지 않았다. 결과적으로 단기적인 대응이 우선되는 구조가 반복되었고, 업무 부서의 개발 요청은 점점 증가하게 되었다.
이 과정에서 개발팀에 대한 기대보다는 “요청하면 늦어지고 문제가 발생할 수 있다”는 인식이 점차 형성되었던 것 같다.
이후 팀장이 된 뒤, 실장님과 함께 구조적인 개선을 시도하기 시작했다. 신규 서비스들 또한 안정적으로 개발 및 론칭을 진행했고, 이 과정에서 개발팀은 “우리는 할 수 있다” 라는 인식이 형성되었고, 이번 GNB 개편 역시 문제 없이 적용되는 모습을 보고 운영 부서에서도 점차 신뢰를 갖고 맡길 수 있게 되었다.
물론 제한된 인력과 시간으로 인해 모든 요구사항을 즉시 반영할 수는 없었지만, 이전과 달리 개발팀이 신뢰를 바탕으로 협업할 수 있는 상태로 변화했다는 점에서 의미가 있었다고 생각한다.