회사 프로젝트 성능 최적화記

Dzeko·2023년 9월 6일
0

개발일지

목록 보기
100/112
post-thumbnail

회사에서 맡은 프로젝트는 Workbench 이다.
Workbench는 SMS 마케팅을 그래프로 유저가 쉽게 커스텀/자동화하여 사용할 수 있도록 제공하는 서비스이다.
선임이었던 전 사수께서 mxGraph 라는 라이브러리를 이용해 우리 회사의 핏에 맞게 커스텀하여 구축하였고, 나는 이를 고도화 하는 작업에 투입되어 하는 중이다.

그 동안 신나게 기능 추가에만 열을 올렸으나 워크벤치 사용자들이 많아짐에 따라 사용자들이 타일을 수백 개씩 사용을 하면서,
성능 이슈가 제기된 후에야 성능에 신경을 쓰기 시작했다.

기존 Workbench 성능 문제점

1. 일정 타일 갯수(약 200개)가 넘어가면 워크플로우 진입 시 로딩이 굉장히 느려진다.

2. 이에 따라 워크플로우 안에서의 동작도 느려진다. (마우스 동작 및 패널 동작에 의한 워크플로우 편집)


그동안은 mxGraph 라이브러리가 상당히 복잡해 이해도가 낮기도 했고,
커스텀한다 하지만 기능을 추가할 뿐 mxGraph의 코드 자체는 되도록 건드리지 않았기에,

그저 mxGraph가 무거운 라이브러리이니 그럴만 하겠다 라고만 믿고있었다.

이에 한 워크플로우 당 타일 갯수를 제한하는 쪽으로 정책을 수정하면서 마무리되는 듯 했다.

하지만 오랜 시간 mxGraph를 다루다 보니, 슬슬 전체적인 코드의 흐름이 분석이 되고 매커니즘이 눈에 익으면서, 개선할 사항들이 보이기 시작했다.


결론부터 말하자면, mxGraph는 그렇게 무거운 라이브러리가 아니다.(그렇다고 가볍다는 말은 아니다)

우리가 더 무겁게 쓰고 있던 것이다.

mxCell이라는 객체는 mxGraph에서 만들어내고 사용하는 그래프 요소다.(줄여서 cell)
cell이 많을수록 워크플로우가 무거워지는 것은 당연하다.

우리가 사용하는 타일은 하나의 cell이지만, 이 cell 또한 여러개의 cell로 이루어져 있다.
tileIcon, warningIcon, Ports, tileNumber 모두 하나의 cell이다.
(여담으로 타일넘버는 처음에 cell이 아닌 html element로 타일에 박았다. 하지만 망할 사파리 이슈 때문에 어쩔 수 없이 cell로 만들어 넣게 되었다.

그러므로 한 타일을 구성하는 cell의 갯수는 최소 5~6개다. Branch타일 같은 경우 최대 18개까지 cell을 가질 수 있다.

한 사용자의 워크플로우를 예를 들면, 한 워크플로우에 355개의 타일을 사용하고 있다.
이 워크플로우의 cell의 갯수는 무려 1063개다.
당연히 느려질 수 밖에 없다.

개선 사항을 나열해보면 크게 세 가지다.


1. 워크플로우 로드 시 동작되는 메소드 정리

  • 워크플로우에 진입을 하면, api로부터 CDATA로 인코딩된 그래프 정보를 가져온 후, decode를 진행하고 view에 파싱한다.

    이 때 실행되는 메소드들이 importGraphModel 메소드 안에 있다.

    그 각각의 메소드들이 view를 너무 많이 다시 그려주고 있었다.
    이미 전체 뷰를 그려줬는데, 어떤 조그만 변경 사항이 생겨도 전체 뷰를 다시 그리는 동작이 많았다.
    해당 cell만 그려주거나 걷어내는 작업을 했다.

  • v1.3에서 타일명이 변경되고 타일의 display text가 변경된 일이 있었는데, 이 작업 또한 매 번 실행되며 셀을 다시 그려주고 있었다. - v1.3 릴리즈 일자를 기점으로 워크플로우가 업데이트된 날짜를 비교해 분기를 해주었다.

  • 미니맵을 그릴 때, 본 워크플로우에 있는 모든 셀들을 그대로 그려주다 보니 같은 셀을 두 번씩 그리는 작업이 확인됐다. 워크플로우의 셀을
    먼저 그려준 후, 로딩 후에 미니맵의 셀들을 그려주었다.

워크플로우 로딩 시 성능 개선 결과

  • 타일 240개 (cell 719개) Workflow
    • 1 try: 15608ms -> 2818ms
    • 2 try: 15749ms -> 2603ms
    • 3 try: 15237ms -> 3018ms



  • 타일 355개 (cell 1063개) Workflow
    • 1 try: 32330ms -> 5009ms
    • 2 try: 31599ms -> 5123ms
    • 3 try: 33214ms -> 4866ms


평균 약 600% 개선



2. 마우스 이벤트에 걸리는 메소드 정리

  • mxGraph의 마우스 관련 메소드는 수 없이 많다. 이런 마우스 동작 하나에도 여러 이벤트 리스너가 등록되어 있다.

    ex) graph.mouseDown/Move/Up, panning.mouseDown/Move/Up, rubberband.mouseDown/Move/Up 등)

    mouseDown, mouseMove, mouseUp 할 때마다 필요없는 메소드가 호출되는 것을 막았다.

  • cell이 선택될 때 호출되는 setSelectionCell 메소드가 mouseDown 이벤트와 click 이벤트에서 동시에 호출되었다.

    setSelectionCell 메소드는 꽤 무거운 메소드이기에 click 이벤트에서는 제거하는 것 만으로 성능 200% 개선의 효과를 얻을 수 있었다.


3. view 의 변화를 그리는 방식

아마 제일 큰 변화이고 앞으로의 개발 방향에 있어서도 큰 영향을 미칠 것 같다.
1번에서 얘기된 바와 같이, 고작 cell 하나의 스타일 변화에 전체 view를 다시 그리는 동작들이 많았다.
아래 동작들에서 해당되는 셀만 동작되도록 변경했다.

  • 타일 및 라인 생성
  • 타일 save
  • undo/redo
  • filter alert
  • 패널 동작에 의한 style 반영/revert


4. Etc.

  • Zoom in/out 시 view scale을 적용할 때 전체 cell을 revalidate 하는 메소드가 두 번 동작되었다.

    viewStateChanged() 라는 메소드에서 revalidate를 해주고, 같은 범위에서 작동되는 sizeDidChange에서도 revalidate를 해주고 있었기 때문에
    revalidate라는 무거운 함수를 한 번만 작동되게 함으로써 200% 성능 개선을 얻었다.


각각의 동작들에 대한 개선 결과


테스트 Cycle: 타일 선택 및 해제 -> 라인 생성 및 Mouse move -> 타일 save -> undo -> redo
  • cell 생성/삭제: 4494ms -> 19ms (23653%)

  • 타일 선택/해제: 142ms -> 29ms (490%)

  • 라인 생성: 1183ms -> 7ms (16900%)

  • 라인 move: 20ms -> 3ms (660%)

  • 타일 save: 16000ms -> 1100ms (1450%)

  • undo/redo: 4372ms -> 16ms (27325%)

최소 490%, 최대 27325% 까지 개선되었다.

profile
Hound on the Code

0개의 댓글