본문 바로가기
Random

코드 리팩터링하기

by SeanK 2022. 10. 13.

안녕하세요, 개발자 Sean입니다.

 

소프트웨어 엔지니어링은 다른 공학과는 다르게 무형의 어떤 것을 만들어낸다는 특징이 있습니다. 

 

그렇기 때문에 어플을 만들어 나가는 과정에서 무수히 많은 예상치 못한 결과를 만나기도 합니다. 

 

또한 잘 계획되지 못한 기능 구현은 끔찍한 코드 실타래를 만들어 내고 이는 필연적으로 원인을 알 수 없는 버그와 에러로 이어지죠. 

 

그리고 이번 주에 제가 그런 실수를 범했습니다. 

애널리틱스라는 분석 페이지를 제작 중이었는데요, 

 

음... 복잡한 기능인 데다가 개념 이해가 어렵다 보니 

 

일단은 만들고 보자

 

 

라는 생각으로 무작정 키보드부터 두드리고 본 결과

 

약 1천줄의 ... '의미를 알 수 없는 변수명'과 '왜 이렇게 짜인 건지 이해할 수 없는 컴포넌트 구조'로 점철된 코드가 만들어졌습니다. 

 

한 스프린트 만에 1천줄이라니 내심 대단하긴 한데 더 대단한 건 기적적으로 코드가 작동하고 있었습니다. 하핳

하지만 직감적으로 느낌이 왔습니다. 

 

만약 기능을 추가한다면 무조건 이 코드는 무너진다..!

 

왜냐하면 제가 만든 코드인데도 제가 이해를 못하고 있었거든요 ㅎ...

 

그래서 시간을 충분히 잡고 처음부터 개념정리와 함께 어떻게 코드 구성을 해야 하는지 등을 생각하며 리팩터링을 하는 시간을 가져보았습니다. 

 

리팩터링 이전의 코드 구성

우선은 전체적인 그림을 살펴보는게 중요하다고 생각했습니다. 큰 물줄기를 정리해야 데이터의 흐름과 상태 제어를 논리적으로 구현할 수 있다고 생각했기 때문입니다. 

 

그래서 현재 코드를 개념적으로 정리한 결과 위와같은 구성이 나왔습니다. 

 

보기만 해도 복잡한 코드임이 느껴졌습니다. 

 

위의 청사진을 바탕으로 문제점을 분석해보니 세가지의 문제가 있었습니다. 

  • Analytics.js가 모든 자식 컴포넌트를 핸들링 하고 있기 때문에 파일의 크기가 비대해졌습니다. 
  • GeneratorDrawer.js는 DataAnalysis.js / EventAnalysis.js / IndexAnalysis.js로 부터 데이터를 전달받아야 하는 구조였습니다. 따라서 불가피하게 props drilling이 발생했습니다.
  • DataAnalysis.js / EventAnalysis.js / IndexAnalysis.js.는 서로 다른 데이터 구조와 필터 옵션을 가지고 있습니다. 이 모든 차이점이 Analytics.js와 GeneratorDrawer.js에서 'If' 구조문에 의해 핸들링되고 있었습니다.

따라서 아래와 같이 리팩터링을 해보았습니다.

리팩터링 이후의 코드 구성

개념도만으로도 복잡도가 많이 줄어든 것을 확인 할 수 있었습니다. 

 

  • 우선 Drawer 컴포넌트를 작은 세개의세 개의 컴포넌트로 나누었습니다.(DataDrawer.js / EventDrawer.js / IndexDrawer.js). 그리고 이 작은 세 개의 컴포넌트들이 각자의 비즈니스를 처리하도록 해 Analytics.js는 단순히 컴포넌트의 이동에만 관여할 뿐 Drawer와 관련된 비즈니스 로직을 다루지 않도록 했습니다.
  • 리덕스 스토어에 데이터와 필터 옵션들을 저장해 prop drilling을 없앴습니다.
  • 각각의 컴포넌트가 데이터와 필터 옵션을 불러오고 업데이트 할 수 있기 때문에 상위 컴포넌트에서 If 구문을 통한 분기 처리가 필요 없어졌습니다.

이번 애널리틱스 기능 구현은 지금까지 만든 기능 중에 가장 힘든 작업이었던 것 같습니다. 

 

다른 경험이 많은 개발자분이 맡으셨다면 쉽게 구현할 수 있었겠지만, 아직 애기 개발자인 저로서는 많은 생각을 하게 만드는 작업이었네요. 

 

다음부터는 무작정 코드 구현보다는 미리 개념도를 어느 정도 그려보고 작업에 들어가도록 해야겠습니다.