개발자 윤찬

웹 개발자 윤찬의 프로필 사진개발자 윤찬
2024. 10. 24.

데이터 시각화 및 클라이언트 사이드 ai 활용

VienceVisualization
"초반 적응기"

서비스 회사

서비스 회사지만, 초반에는 솔루션도 있었다. 언젠가는 저 솔루션을 서비스에 접목 시키는 것을 목표로 하고 지금은 다른 회사에서 데이터 시각화클라이언트 사이드에서 ai를 활용하는 프로젝트가 있으면 받아서, 제공해주는 일을 가끔 하게 되었다. 특히 데이터 시각화나, 클라이언트 사이드 ai활용 같은 경우는 논코딩 툴에서 특정 노드가 해당 역할을 할 것이기 때문에 미리 해볼 수 있는 좋은 기회라고 생각한다.


솔루션1 - 데이터 시각화 D3

처음 D3를 접했을 때는 살짝 신세계였다. 예전부터 CodePen에서 외국 개발자들이 만든 universe 시뮬레이션이나 다양한 인터랙티브 요소들을 보면서 어떻게 구현하지라는 생각이 있었다. 사실 당시에는 어떤 특별한 라이브러리가 이러한 기능들을 제공해주고 있다고 생각했지만, 이번기회에 D3를 알게 되었고, 그동안 궁금했던것들이 하나씩 풀리기 시작했다. 특히 데이터를 기반으로 돔 요소를 자유롭게 다루고, 애니메이션과 상호작용을 더해 생동감 있는 결과물을 만들어낼 수 있다는 점이 무척 인상 깊었다.

D3를 활용한 첫 업무는, 여러 정제된 데이터를 기반으로 각각의 꺾은선 그래프를 개별적으로 생성하는 것이다. 이후, 서버에서 제공받은 코드를 통해 특정 블록이나 변수를 선택하면, 해당 꺾은선 그래프의 영역이나 모양이 인터랙티브하게 조정되도록 구현한다. 또한 사용자는 그래프를 드래그하여 조작할 수 있으며, 이렇게 변경된 내용은 서버에 다시 전달되어 업데이트된 코드로 반영되도록하는 것이다.

사실, D3만 없다면, 간단한 api 통신이지만, d3가 들어가 난이도가 올라간것 같다.

일단, 요소를 잘 다루기 위해서 주말에 위와 같이 연습을 진행했고, 바로 실전에 적용을 해봤다.

데이터 시각화 D3의 작업

왼쪽 하단의 데이터 리스트가 있고, 이 데이터들로, 기본적인 선 그래프들이 D3로 구현이 되어있다. 여기서 미션이 있었는데

  • 각 MIN, MAX에 따라서 영역 그래프로 변경
  • 오른쪽 하단의 python코드의 조건문 수치와, 상단 그래프의 범위 동기화
  • 브라우저 확대/축소시 렌더링 무한루프 오류 해결

이렇게 작업이 요구되었다.


먼저, MIN, MAX 영역 그래프 설정은 주말에 공부했던것에서 구현을 한번 해본적이 있어서 간단하게 할 수 있었다. 특히 기존의 선 그래프에서 영역 그래프로 변경할 때, d3.area라는 영역으로 바꾸는 함수를 지원해주기 때문에

위처럼, rangeBox 객체의 각 그룹마다 minValues와 maxValues를 꺼내고, 각 변수에 대해 xScale을 사용해 x좌표를 계산하며, yScales를 기준으로 최대값과 최소값에 대응하는 y좌표 배열을 만든다. 그런 다음, 이 좌표들을 d3.area 함수에 넣어 두 경계가 다른 영역을 생성한다.

x좌표는 xScale을 기준으로 하는 이유는, 높이 , 넓이 등의 변수가 x축에 위치하기 때문에 각 변수에 해당하는 위치를 정해주려 하였고

y좌표는 각 변수별 값의 크기를 나타내므로, 변수마다 독립적인 yScales를 사용해 최대값과 최소값을 대응하는 y좌표를 계산한다.

이후부터는 hover 이벤트 적용만 하게 되면 첫번째 요구사항을 구현할 수 있었다.


이번에는 영역 렌더링 및 드래그가 있는 인터렉션을 구현해야하는데, 변수별로, 최소값 최대값 위치에 빨간원을 표시하고, d3 드래그 핸들러를 설정해서, 실시간으로 수정할 수 있게 구현하였다.

클래스명이 .min-point-{variable}인 최소점에 대해서, MinDragHandler() 함수를 호출해, 해당 변수의 최소값 점에 드래그 이벤트 핸들러를 붙여, 모든 변수별로 최대값과 최소값 위치에 있는 점들에 드래그 인터랙션이 활성화 되고, 이 값을 백엔드에 전송해서, 코드와 동기화 시킬 수 있게 되었다.


마지막으로는 확대, 축소시 다음의 오류가 발생하는 문제였는데, 이는 간단하게 다음의 문제였는데,

Styled-CSS에서 width와 height가 브라우저 크기나 확대/축소가 변할 때마다 계속 변경되어서, React가 무한히 반복 렌더링되는 문제

이를 방지하려고 레이아웃 구조를 고정 즉, width, height를 px로 설정하여, 컴포넌트 크기 변화에도, 설정한 값으로 고정되기 때문에 다음의 렌더링 문제를 막을 수 있었다.


솔루션2 - 클라이언트 사이드 딥러닝 적용

기존 c계열로 되어있던 코드를 web에서 동작할 수 있도록 마이그레이션 하였고, opencv-ts와 onnxruntime-web을 활용하여. 클라이언트 사이드에서 딥러닝을 적용시켜 객체를 탐지할 수 있도록 구현하는 작업

AI는 백 서버단에서 다 돌리는 줄 알았지만, 클라이언트의 자원을 사용해서 실행시키는 것도 요즘 뜨는 기술이라고 들었다. 특히 서버 부하 감소라는게 가장 큰 이점이되는데, 서버가 모든 사용자 요청마다 무거운 연산을 수행할 필요가 없어서, 서버 대신 클라이언트가 처리해 서버의 연산 부하와 비용을 크게 줄일 수 있다.

사실 이번 솔루션은 원래 C 계열 언어로 이미 구현되어 있었지만, 웹 환경에서 동작하도록 다시 구현하는 과정에서 기존 코드를 해석하고 변환하여, 웹에서 사용할 수 있는 opencv-ts와 onnxruntime-web 라이브러리를 활용해 재구현하는 미션이었다.

  • opencv-ts 같은 경우는, 웹 브라우저에서 적용가능하도록, TypeScript로 구현 가능하도록 해주는 것이다.
  • onnxruntime-web은 ONNX 형식으로 저장된 딥러닝 모델을 웹 브라우저 내에서 실행할 수 있게 해주는 라이브러리라, 입력으로 받는 ONNX 파일을 해석해준다.

이 프로젝트는 코드 해석이 가장 큰 문제였지만 중간중간에 재밌는 구현이 있었는데

ONNX 모델이 예측한 결과를 받아 화면에 바운딩 박스 div를 생성/수정하여 시각화 하는 과정이었다.

위와 같이 ONNX 모델의 출력 결과가 index 7개씩 1개의 객체를 반환하기 때문에 7개씩 끊었다. 그리고 좌표에 비율(ratio)을 곱해 원본 이미지 크기에 맞게 보정하고, 그에 맞춰 동적으로 div 태그를 생성했다. 사각형을 표시하는 작업은 구현 자체는 간단했지만, 모델의 출력 결과가 화면에 정확한 크기와 위치로 딱 맞게 그려질 때 느껴지는 쾌감은 정말 특별했었다.

나중에는 메인 서비스인 Vience Canvas에서 datahub에 업로드한 onnx 모델을 불러와서, 하나의 노드에서 클라이언트 사이드로 딥러닝을 실행시키는것을 목표로 하고 처음이자 마지막? 솔루션을 해보며 점점 회사에 적응 할 수 있는 계기가 되었던것 같다.

Profile Picture

CHAN

과정은 복잡하되, 결과는 단순하게

Thank You for Visiting My Blog, Have a Good Day 😆
ⓒYoonchan Cho