logo
문의하기
서비스리소스블로그아카데미
logo
문의하기
logo

데이터와 IT 흐름을 읽는 시선,
뉴스레터 EXEM View 구독하기

Subscribe

주식회사 엑셈

서울시 강서구 마곡중앙8로5길 40

Tel 02-6203-6300 ㅣ Fax 02-6203-6301

ⓒ EXEM Co., Ltd. All Rights Reserved.
개인정보 처리방침서비스 이용약관
  • 서비스

    • Database
    • Application
    • AIOps
    • LLMOps
    • Big Data
    • All-in-One
    • Consulting
  • 신청

    • 세미나
    • 사옥 투어
  • 회사

    • 기업 소개
    • 채용 안내
    • IR
    • 오시는 길
  • 자료

    • 제품 브로슈어
    • 제품 살펴보기
    • 도서 실습자료
  • awsaws
  • microsoftmicrosoft
  • oracleoracle
  • naver-cloudnaver-cloud
exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다
exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다
exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다
exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다

exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다

태그
테크
**수정 금지** (제목 연동)
exemONE 화면 연계 맵 개발기: 코드베이스를 노드와 엣지로 표현하다
날짜
2026.09.10
작성자

최연진

엑셈원 화면 연계 맵 개발기

안녕하세요. 엑셈원 프론트엔드를 개발하고 있는 FE2팀 최연진입니다.
“이 공용 코드를 수정하면 어느 화면까지 확인해야 할까?”
규모가 커진 프론트엔드 프로젝트에서 자주 마주치는 질문입니다. 코드 검색으로 함수의 사용처는 찾을 수 있지만, 그 사용처가 사용자가 보는 어떤 화면과 연결되는지, 해당 화면에서는 다시 어디로 이동할 수 있는지까지 한눈에 파악하기는 어렵습니다. 엑셈원에는 URL을 가진 일반 화면뿐 아니라 화면 위에서 열리는 상세 슬라이드와 브라우저 팝업도 다수 존재합니다. 여기에 여러 화면이 함께 사용하는 컴포넌트와 composable까지 더해지면 하나의 사용자 흐름이 여러 폴더와 도메인에 흩어집니다.
이 문제를 해결하기 위해 코드베이스를 정적 분석해 화면 관계를 노드와 엣지로 보여주는 DEV 전용 화면 연계 맵을 만들었습니다. 현재 Git 변경 사항이 어떤 화면과 관련될 수 있는지도 함께 표시합니다.
 
이 글에서는 코드를 그래프 데이터로 바꾼 방법, Vue Flow와 Dagre를 선택한 이유, 그리고 정적 분석이 확실하게 증명하지 못하는 관계를 과장하지 않기 위해 세운 기준을 소개합니다.
💡
화면 연계 맵의 목표는 관계를 최대한 많이 그리는 것이 아니라, 개발자가 표시된 관계를 믿고 다음 확인을 시작할 수 있게 하는 것입니다.
 
 

1. 수작업 문서 대신 코드에서 관계를 읽다

통합 모니터링 제품에는 서로 성격이 다른 여러 영역이 있고, 하나의 사용자 흐름이 그 경계를 자주 넘습니다. 목록에서 상세 슬라이드를 열고, 상세 화면에서 다른 대상의 화면으로 이동하거나, 알림에서 관련 화면으로 바로 진입하기도 합니다.
전체 연계를 문서로 정리하는 방법도 생각할 수 있습니다. 하지만 많은 관계를 처음부터 손으로 옮기는 데 비용이 들고, 구현이 바뀔 때 문서를 함께 수정하지 않으면 실제 동작과 멀어지기 쉽습니다. 문서를 없애려는 것은 아닙니다. 다만 자주 바뀌는 화면 관계만큼은 사람이 별도로 관리하기보다 코드에서 다시 생성하는 편이 낫다고 판단했습니다.
 
화면을 등록하고 여는 단서는 이미 코드에 남아 있습니다.
  • 라우터에는 URL을 가진 화면이 등록되어 있습니다.
  • 슬라이드와 팝업은 각각의 레지스트리에 컴포넌트가 등록되어 있습니다.
  • 라우팅, 상세 열기, 새 창 열기와 같은 호출에는 화면 전환의 단서가 남아 있습니다.
 
화면 연계 맵은 이 단서들을 모아 다음 두 가지 질문에 답하도록 설계했습니다.
  • 이 화면은 어디에서 열리고, 여기에서는 어디로 이동할 수 있는가?
  • 지금 변경한 코드가 사용자가 보는 어떤 화면과 관련될 수 있는가?
 
코드를 지도 데이터의 원본으로 삼으면 담당자에게 묻거나 여러 검색 결과를 조합하는 시간을 줄일 수 있고, 현재 작업 트리의 구조를 필요할 때마다 다시 확인할 수 있습니다.
 
 

2. 스캐너가 코드를 노드와 엣지로 바꾸는 방법

전체 구조는 다음과 같이 나눌 수 있습니다.
정적 스캐너는 코드에서 지도 데이터를 만들고, DEV 서버는 Git 변경 정보를 별도로 분석합니다. 뷰어는 두 결과를 받아 화면 관계와 변경 근거를 함께 보여줍니다.
정적 스캐너는 코드에서 지도 데이터를 만들고, DEV 서버는 Git 변경 정보를 별도로 분석합니다. 뷰어는 두 결과를 받아 화면 관계와 변경 근거를 함께 보여줍니다.
 

2-1. 화면 등록 정보를 노드로 변환하기

처음 동작하는 것은 Node.js로 작성한 정적 스캐너입니다. 스캐너는 애플리케이션이 화면을 등록해 둔 명부부터 읽습니다.
코드에서 읽는 정보
변환 결과
의미
라우터 설정
화면 노드
URL을 통해 진입하는 일반 화면
상세 UI 레지스트리
슬라이드 노드
현재 화면 위에서 열리는 상세 화면
팝업 컴포넌트 맵
팝업 노드
별도 브라우저 창으로 열리는 화면
 
각 노드에는 화면 이름과 종류, 소속 영역, 선언 위치처럼 검색과 탐색에 필요한 정보도 함께 저장합니다.
기존에 매핑된 라우터 파일과 중앙 레지스트리에서 지원하는 방식으로 화면을 추가하면 다음 스캔에 반영됩니다. 다만 모든 구조 변경을 자동으로 이해하는 것은 아닙니다.
새 라우터 파일이나 도메인을 추가하거나, 수동 계약이 참조하는 파일과 등록 이름을 바꾸는 경우에는 스캐너의 매핑과 계약도 함께 확인해야 합니다. 자동으로 읽는 등록 정보와 사람이 관리하는 해석 규칙을 구분해 두었습니다.
 

2-2. 호출 코드를 연계 증거로 변환하기

노드를 수집한 다음에는 라우터 이동, 상세 열기, 팝업 열기처럼 화면 전환을 만드는 호출을 찾습니다.
스캐너는 import와 재노출 관계를 역방향으로 따라가 공용 코드가 연결되는 가장 가까운 화면을 찾습니다. 공유 컴포넌트라도 사용 화면마다 동작이 다를 수 있으므로, 필요한 경우 Vue 템플릿의 이벤트와 prop, 화면별 허용 조건을 함께 확인합니다.
여기서 중요한 것은 호출을 발견하는 것과 그 의미를 확인하는 일을 구분하는 것입니다. 지원하는 규칙 안에서 발신 화면과 목적지를 확인하고, 실행 조건이 있으면 그 근거를 남깁니다. 다만 임의의 함수가 실제 UI에서 실행되는지, 모든 런타임 분기가 도달 가능한지까지 완전히 증명하는 분석기는 아닙니다.
💡
스캐너의 핵심은 단순히 호출을 발견하는 데 그치지 않고, 지원하는 분석 규칙 안에서 발신 화면과 목적지, 실행 조건의 근거를 확인하는 것이 핵심입니다.
 

2-3. 필요한 문맥만 골라서 해석하기

코드의 성격에 따라 해석 방법을 나누었습니다. 형태가 일정한 화면 등록 정보는 미니 파서로 읽고, 호출 후보가 실제 코드인지 확인하거나 변수의 바인딩을 구분할 때는 TypeScript AST와 심볼 분석을 사용합니다. Vue 이벤트와 prop처럼 템플릿 문맥이 필요한 부분에는 Vue 파서를 사용합니다.
예를 들어 문자열 안에 적힌 이동 코드와 실제 호출은 구분해야 합니다. 변수 이름이 같더라도 호출 위치에서 다른 지역 변수를 가리킨다면 같은 router나 목적지로 취급할 수 없습니다. 이런 차이는 단순한 문자열 검색만으로 판단하기 어렵습니다.
문법을 읽는 것만으로 알 수 없는 프로젝트의 의미도 있습니다. 같은 상세 컴포넌트를 여러 화면이 공유하더라도 화면 종류와 실행 조건에 따라 허용되는 동작이 다를 수 있습니다. 이런 경우에는 명시적인 의미 계약으로 자동 분석 결과를 보정하고 검증합니다.
최종 결과는 노드, 엣지, 동적 행동, 진단 등으로 나누어 DEV 전용 생성물로 출력합니다. 같은 입력과 분석 환경에서 결과를 비교하기 쉽도록 노드와 관계, 호출 위치의 순서도 고정합니다.
 
 

3. Vue Flow로 그리고, Dagre로 배치한다

화면 연계 맵이 그려낸 실제 지도 중 일부
화면 연계 맵이 그려낸 실제 지도 중 일부
 
그래프 UI에는 Vue Flow 라이브러리를 사용했습니다. 확대와 축소, 캔버스 이동, 노드·엣지 선택 같은 상호작용과 커스텀 노드 렌더링을 직접 구현하지 않아도 되고, 기존 Vue 컴포넌트와 상태를 자연스럽게 연결할 수 있기 때문입니다. 검색 결과를 선택하면 해당 노드로 이동하고, 노드나 엣지를 클릭하면 들어오는 연계와 나가는 연계, 호출 위치를 상세 패널에 표시하는 기능도 Vue Flow 위에 구현했습니다.
다만 Vue Flow가 노드의 위치까지 자동으로 결정해 주는 것은 아닙니다. 수많은 노드의 좌표를 사람이 직접 관리할 수 없기 때문에 배치에는 Dagre 라이브러리를 함께 사용했습니다. Dagre는 방향이 있는 그래프를 계층적으로 배치하는 라이브러리입니다. 스캐너가 만든 노드와 엣지, 각 노드의 크기를 Dagre에 전달하면 좌표가 계산되고, Vue Flow는 그 좌표를 이용해 그래프를 렌더링합니다.
모든 화면을 한 번에 펼치면 정확한 데이터도 읽기 어려운 그래프가 됩니다. 이를 피하기 위해 첫 화면에서는 영역 간 관계를 집계해서 보여주고, 영역을 선택하면 내부 화면과 한 단계 이웃을 펼치는 구조를 선택했습니다.
💡
Vue Flow는 그래프를 탐색하는 경험을 담당하고, Dagre는 그래프를 읽기 좋게 배치하는 역할을 담당합니다.
 
 

4. 많이 그리는 것보다 정확하게 구분하기

구현하면서 가장 어려웠던 부분은 엣지를 찾는 일이 아니라, 발견한 호출을 정말 엣지라고 불러도 되는지 판단하는 일이었습니다.
 
notion image
 
여러 화면이 같은 목록 컴포넌트를 사용하고, 목록에서 선택한 대상의 종류에 따라 서로 다른 상세 화면이 열린다고 가정해 보겠습니다. 정적 분석으로는 클릭 시점에 사용자가 어떤 대상을 선택할지 알 수 없습니다.
가능한 상세 화면을 모든 사용 화면에 엣지로 연결하면 실제보다 많은 관계가 만들어집니다. 반대로 모두 제외하면 해당 화면에서 실행할 수 있는 행동을 놓치게 됩니다.
 
이 문제를 해결하기 위해 분석 결과를 다음과 같이 구분했습니다.
  1. 발신 화면과 도착 화면이 모두 증명되면 확정 연계로 기록합니다.
  1. 도착 화면은 정해졌지만 특정 탭, 권한, 데이터 상태에서만 실행되면 조건부 연계로 기록합니다.
  1. 도착 화면이 사용자 선택이나 응답 데이터에 따라 결정되면 타깃이 없는 동적 연계로 기록합니다.
 
확정 연계, 조건부 연계, 동적 연계를 모두 보여주는 실제 예시
확정 연계, 조건부 연계, 동적 연계를 모두 보여주는 실제 예시
예시의 상세 패널은 목적지가 정해진 관계와 선택값에 따라 달라지는 행동을 함께 보여줍니다. HomeView 캡처에서 나가는 항목은 7개지만, 그래프의 선 7개를 뜻하지는 않습니다. 고정 목적지가 있는 관계 6개와 동적 행동 1개를 합친 수입니다. 대상이 정해지지 않은 행동의 후보 화면은 그래프의 엣지나 BFS 도달 범위에 넣지 않습니다.
연계 점검 목록도 별도로 제공합니다. 등록된 상세 화면의 열림 근거를 찾지 못했거나, 호출한 팝업 이름에 대응하는 등록 화면을 확인하지 못한 경우처럼 추가 검토가 필요한 지점을 보여줍니다.
 
 

5. 사이드 이펙트를 줄이기 위해 영향 범위를 그리다

엑셈원을 개발하면서 반복해서 마주친 문제 중 하나는 사이드 이펙트였습니다. 프로젝트의 규모가 크다 보니 특정 화면을 수정하기 위해 공용 컴포넌트나 유틸을 변경했는데, 같은 코드를 사용하는 예상 밖의 화면까지 동작이 달라지는 경우입니다. 수정한 코드는 몇 줄뿐이어도 실제로 확인해야 할 범위는 훨씬 넓어지곤 했습니다.
그래서 화면 연계 맵에 현재 작업 트리의 Git 변경 사항을 겹쳐 표시했습니다. 스테이징 여부와 관계없이 아직 커밋하지 않은 변경 파일을 수집해 IDE의 변경 목록과 같은 범위를 분석합니다. 기본은 미커밋 범위이고, 브랜치 전체(MR 관점) 범위도 선택할 수 있습니다.
 
공통 유틸 파일에서 함수 하나를 수정했을 때의 실제 예시입니다. 해당 함수를 사용하는 화면 목록을 보여줍니다.
공통 유틸 파일에서 함수 하나를 수정했을 때의 실제 예시입니다. 해당 함수를 사용하는 화면 목록을 보여줍니다.
 
각 변경 파일에서는 import 관계를 역방향으로 따라가며 해당 코드를 사용하는 화면을 찾습니다. 추적은 가장 가까운 화면 컴포넌트에서 멈춥니다. 공용 모듈을 변경했다는 이유만으로 애플리케이션 전체가 영향을 받는 것처럼 표시하지 않고, 실제로 그 코드를 사용하는 화면에 변경을 귀속하기 위해서입니다.
하지만 파일 단위 추적만으로도 범위가 지나치게 넓어질 수 있습니다. 하나의 공용 유틸 파일 안에는 서로 관계없는 여러 함수가 함께 있기 때문입니다. 그래서 TypeScript 파일은 가능한 경우 Git diff에서 변경된 export 심볼을 식별하고, 그 심볼을 실제로 참조하는 import 경로만 추적합니다.
이 기능이 사이드 이펙트의 발생 여부를 자동으로 판정해 주는 것은 아닙니다. 정적 분석만으로는 실행 시점의 모든 데이터와 동적 호출을 알 수 없으며, 분석 근거가 부족하면 실제보다 넓은 범위를 보여줄 수도 있습니다.
대신 무엇부터 확인할지를 바꿔 줍니다. 이전에는 “어떤 파일을 수정했는가”에서 시작했다면, 이제는 “이 변경과 연결된 화면 중 어디까지 확인해야 하는가”를 기준으로 테스트 범위를 정할 수 있습니다.
💡
변경 영향 표시는 테스트를 대체하는 결과가 아니라, 놓치기 쉬운 확인 대상을 작업이 끝나기 전에 드러내는 체크리스트입니다.
 
 

6. 정확성을 지키면서 개발 속도를 떨어뜨리지 않기

영향 범위를 보여주는 도구는 빠르기만 하거나 정확하기만 해서는 실제 개발 과정에 정착하기 어렵습니다. 잘못된 관계를 보여주면 확인 범위를 오히려 왜곡할 수 있고, 실행할 때마다 오래 기다려야 한다면 개발자가 자연스럽게 도구를 우회하게 됩니다.
 
정확성과 사용성을 둘 다 갖춰야 개발 도구로 자리 잡을 수 있습니다.
정확성과 사용성을 둘 다 갖춰야 개발 도구로 자리 잡을 수 있습니다.
 
먼저 같은 코드에서는 항상 같은 결과가 만들어지도록 노드와 엣지, 호출 위치의 정렬 순서를 고정했습니다. 중복된 관계, 존재하지 않는 화면을 가리키는 엣지, 새롭게 발생한 미해결 패턴뿐 아니라 동적으로 결정되는 연계가 실제 Vue 이벤트와 연결되어 있는지도 확인합니다.
정확성을 유지하는 것만큼 사용성도 중요했습니다. 한 번의 스캔에서는 파일 원문과 주석을 제거한 결과를 캐시해 여러 분석 단계에서 재사용합니다. Vue의 클릭 가능 여부처럼 템플릿 정보만 필요한 단계에서는 파일 전체를 다시 해석하지 않고 <template> 영역만 분석하도록 범위를 줄였습니다.
반복 실행에서는 입력 파일의 경로와 내용, 스캐너와 파서 환경으로 fingerprint를 만듭니다. 이 값과 기존 생성물의 hash가 모두 일치하고, 이전에 검증까지 통과한 결과인 경우에만 생성물을 재사용합니다. 파일 수정 시간만 비교하는 방식보다 계산은 조금 더 필요하지만, 오래된 결과를 잘못 재사용할 가능성을 줄일 수 있습니다.
그 결과, 약 10초 걸리던 전체 스캔은 약 3초로 줄었습니다. 개발 서버를 다시 시작할 때는 fingerprint가 일치하면 스캔 자체를 건너뛰므로, 반복 실행에서는 대기 시간이 사실상 사라집니다.
 
 

7. 마치며

화면 연계 맵은 여러 파일에 나뉘어 있는 화면 등록 정보와 호출 근거를 모아, 다음에 무엇을 확인할지 찾도록 돕는 도구입니다. 코드가 표현하는 모든 동작을 자동으로 이해하지는 못하지만, 지원하는 규칙으로 확인한 관계와 조건, 아직 판단할 수 없는 부분을 구분해 보여주려 했습니다.
이렇게 만든 기능은 앞서 말한 사용 예시 외에도 온보딩 자료로 사용되거나 AI를 활용한 코드 리뷰 시 스캐너 추출물을 참고하는 등 다양하게 활용할 수 있습니다.
 
마지막으로 만들면서 배운 것을 3가지로 남깁니다.
  1. 개발 도구의 가치는 기능의 수가 아니라 표시된 정보를 믿을 수 있는지에서 결정됩니다. 오탐을 한 번 경험한 사용자는 도구 전체를 의심하게 됩니다.
  1. 도구도 제품처럼 관리해야 합니다. 제품 코드는 매일 바뀌기 때문에, 결과를 스스로 검증하고 언제든 다시 생성할 수 있는 구조가 없으면 도구는 조용히 낡아 갑니다.
  1. 자주 바뀌는 구조 문서는 관리하는 것이 아니라 생성하는 것이라고 생각하게 됐습니다. 신뢰할 수 있는 원본이 이미 코드에 있다면, 사람의 일은 옮겨 적기가 아니라 해석 규칙을 만드는 일입니다.
 
 

 
 

 
 
함께 보면 좋은 아티클
exemONE 차트는 어떻게 성능을 확보하고 있을까 | 엑셈
버벅이던 차트 성능 문제를 해결한 개선 과정을 공유합니다.
exemONE 차트는 어떻게 성능을 확보하고 있을까 | 엑셈
https://ex-em.com/ko/blog/how-exemone-optimizes-chart-performance
exemONE 차트는 어떻게 성능을 확보하고 있을까 | 엑셈
QA도, 시간도 없던 팀이 AI Agent로 테스트 자동화를 정착시킨 방법 | 엑셈
AI로 테스트 코드 작성을 자동화한 경험과 배운 점
QA도, 시간도 없던 팀이 AI Agent로 테스트 자동화를 정착시킨 방법 | 엑셈
https://ex-em.com/ko/blog/ai-test-code-automation-experience-lessons-learned
QA도, 시간도 없던 팀이 AI Agent로 테스트 자동화를 정착시킨 방법 | 엑셈
Table of Contents
엑셈원 화면 연계 맵 개발기1. 수작업 문서 대신 코드에서 관계를 읽다2. 스캐너가 코드를 노드와 엣지로 바꾸는 방법2-1. 화면 등록 정보를 노드로 변환하기2-2. 호출 코드를 연계 증거로 변환하기2-3. 필요한 문맥만 골라서 해석하기3. Vue Flow로 그리고, Dagre로 배치한다4. 많이 그리는 것보다 정확하게 구분하기5. 사이드 이펙트를 줄이기 위해 영향 범위를 그리다6. 정확성을 지키면서 개발 속도를 떨어뜨리지 않기7. 마치며