본문 바로가기

좌충우돌 개발기!/VOC 리팩터링

VOC 리팩터링 프롤로그

현재 상황

현 직장에 처음 이직했을 때, 소스를 보고 1번, 이 소스가 3개월 전부터 만들어지고 있는 리팩터링된 소스라는 것에 2번 놀랐다. 외부업체에서 맡아서 만들었는데, 자신들의 프레임워크를 적용해놓았다고 한다. 

 

이전 소스의 경우, java 6 + Jrun4(WAS 역할)를 사용하였고 그냥 JSP만으로 개발해 놓았던 것을 java 8 + Spring 기반으로 재구성해놓았다고 한다.

 

그나마 Spring으로 사용했으니 유지/보수가 수월하겠지.. 라고 생각했으나, Spring은 도무지 왜 넣어놓았는지 모르도록 만들어 놓았다. 자세한 히스토리는 잘 모르겠으나, 기간을 맞추기 위해 날림으로 만들어 놓았다는 것이 선명하게 느껴지는 소스였다.

 

보통은 위와 같은 MVC패턴을 사용하여 어플리케이션을 제작한다. Spring 프레임워크를 사용한다면 더더욱.

 

 

현재 시스템의 경우에는 이런 형태인데, 비즈니스 로직이 전부 JS로 짜여져있다. 화면 1개당 JSP + JS 한 쌍의 구조를 가지고 있으며 JS에서 특정 서블릿을 호출하여 DB를 조회, 데이터를 가져오고 있다. 당연히 DTO 따위는 없으며, 트랜잭션 처리도 JS에서 하고 있다. Controller는 그냥 JSP 맵핑용에 불과하며, 단순히 DB를 조회 후 데이터를 가져와 그대로 반환하다보니 데이터 정제도 JS에서 전부 해야한다.

(왜냐면 이렇게 되도록 외부업체의 프레임워크가 만들어져있기 때문이다.)

 

 

현 시스템의 문제점

  • 유지/보수의 높은 진입 장벽
    > 일단 가장 큰 문제는 외부업체 전용 프레임워크를 사용한다는 점이다. 해당 프레임워크를 사용하는 한, 위의 구조대로 밖에 갈 수 없다. 이후에 해당 시스템을 맡는 사람은 서비스 로직을 분석하기도 바쁜데 생전 처음보는 로직(다른데 가서 쓰지도 않는 무쓸모 소스)을 분석하는 데 시간을 낭비해야 한다. 보편적인 MVC 구조도 아니기 때문에 분석 시간은 더욱 늘어나게 된다.

 

  • FE와 BE의 구분이 불명확함
    > JS에서 서비스로직을 처리하다보니 BE에서 해야할 일을 FE에서 처리하고 있다. BE에서 트랜잭션 처리 및 데이터 정제와 같은 행위를 끝낸 후에 필요한 데이터만 FE에 뿌려주는 것이, 소스 재활용이나 보안면에서 훨씬 뛰어나다. 즉, 현재 시스템은 그와 반대라는 소리다. JS에서 동적쿼리를 작성하려고 하니, 분기문을 작성하여 부분 부분 쿼리를 변경하고 있어 쿼리 또한 노출되고 있다.

 

  • IE기반의 소스
    > 지금까지 IE에 맞추어 개발하고, 예전 소스들을 그대로 사용하다보니 ES6↑기반의 브라우저(크롬, 엣지, 웨일 등)에서 동작하지 않는 기능이 굉장히 많다. 이전 회사가 광고 회사다 보니 브라우저 이슈에 굉장히 민감했는데(모든 브라우저에서 동작해야 하니), 생각보다 IE의 비중이 높아 요즘 세상에 누가 IE를 쓰는지 굉장히 궁금했었다. 현재 회사와 같은 곳들 때문에 IE 점유율이 유지되는 것이겠지.. 
    MS에서 22.06.15 이후 IE 서비스를 종료하겠다 선언한 지금, 이는 서비스 운영에서 가장 큰 리스크이다. 

 

  • 똑같은 내용의 로직(쿼리)
    > 소스를 보다보면 같은 내용의 쿼리가 빈번하다. 쿼리ID를 외부업체 나름의 네이밍룰을 사용해서 코드네임 형식으로 지어놨는데, 문제는 지들도 ID만 봐서는 무슨 쿼리인지 알 수 없었는지 똑같은 쿼리를 ID만 바꿔서 또 만들어놨다. JS 로직도 똑같은데, 뭐 이 부분은 다른 회사도 마찬가지라 그냥 그러려니 함.

 

  • 정규화가 안 된 테이블들
    > 2008년부터 사용했던 것 같은데 그냥 컬럼 하나씩 늘려서 대충 썼던 것 같다. 그 결과.. 22년 현재, 한 테이블의 컬럼이 85개라는 어마무시한 괴물이 탄생하고 말았다. 똑같은 데이터 여기에 넣고 저기에 넣고, 만들어놓고 안쓰고. 데이터량도 얼마 되지 않는데 조회에 걸리는 시간이 너무 오래 걸려 튜닝도 필요한 것 같다.

 

  • 문제가 발생 시 확인이 번거로움
    > 앞서 Controller가 JSP 맵핑용이라고 말했었다. 특정 서블릿으로 들어오면, Controller는 그에 맞는 JSP만 반환해준다. 따라서 JSP만 존재한다면 해당 서블릿은 에러가 날 일이 없다.

 

필자는 모니터링 도구로 Scouter를 사용하는데, 서버로 들어오는 요청들을 모니터링 할 수 있다. 저 점들 하나하나가 서블릿으로 들어온 요청들이며, 해당 서블릿에서 에러가 날 경우 빨간색으로 점(빨콩)을 찍어 바로 확인 가능하도록 해준다.

 

문제는 화면 그리기용(단순 JSP 맵핑용) 서블릿은 에러가 나지 않고, DB 조회용 서블릿은 거의 모든 화면에서 쿼리만 다르게하여 사용하다보니 빨콩이 찍히는 서블릿은 거의 DB 조회용 서블릿이다. 원래대로라면 서블릿만 보고 어느 화면, 어떤 기능에서 문제가 발생했는지 알 수 있어야하는데, 공통 서블릿으로 처리하다보니 SQL을 확인해서 어디에 쓰는 SQL인지 확인 후, 어떤 화면의 어떤 기능인지를 파악해야하는 번거로움이 있다.

 

해결하기 위하여 해야할 일

  • 외부업체의 프레임워크 걷어내기
    > 너무 쓰잘데기 없는 프레임워크에 의존적이다. 물론 해당 프레임워크가 화면을 만들기에 편한 점도 있지만, 불편한 점이 훨씬 더 크다. 화면을 그리는 곳만 참고하여 공통으로 따로 빼서 사용해야할 것 같다.

 

  • FE와 BE의 책임 구분을 명확하게 하기
    > FE에서는 BE에 데이터를 요청하고, BE는 요청에 따라 데이터를 정제하여 넘겨준다. FE에서는 해당 데이터를 뿌려주는 작업만 한다. 화면에서 일어나는 일은 FE가, 요청 처리는 BE가.
    책임 구분을 명확히 하여 문제가 생겼을 경우, 어느 곳에서 발생했는지 바로 알 수 있도록 해야할 듯 하다.

 

  • ES6↑문법으로 재구성
    > 요즘 브라우저에 맞게 현재 사용되지 않는 기능들을 전부 변경하고, ES6 이후 추가된 기능들을 사용하여 코드를 줄이고 보다 직관적으로 알 수 있도록 재구성 해야한다.

 

  • MVC패턴을 적용한 프레임워크 사용
    > 프레임워크를 제대로 사용하여 MVC패턴을 적용. 유지보수하기 더욱 쉽게 만들어야한다. 익숙한 방법으로 서비스 로직을 빠르게 파악할 수 있고 코드를 재사용하기 용이하며, 프레임워크가 알아서 다 해주니까 쓸데없는 곳에 시간 뺏기지 않아도 된다.

 

  • 객체지향적으로 구성
    > 간단한 로직에도 SQL을 짜야한다는 수고스러움이 개발자에게는 스트레스로 다가온다. JAVA가 객체지향언어인만큼 ORM을 사용하여 보다 객체지향적으로 개발할 수 있도록 한다.

 

  • 테이블 정규화
    > 솔직히 컬럼 85개는 선 넘었다. 정규화를 통해 좀 더 데이터를 정형화시켜 관리하도록 한다.

 

  • 배포 자동화
    > Git, Jenkins 등을 통하여 CI/CD 환경을 구축하도록 한다.

 

 

사용 예정 스펙

  • 언어 : Java 11
  • Framework : Spring boot 2.6
  • WAS : Embedded Tomcat 9
  • Web Server : Apache 2.4
  • Template Engine : Thymeleaf
  • ORM : Spring Data JPA
  • CI/CD : Git, Jenkins