ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 횡단 관심사
    2022. 3. 21. 23:19

    회사에서 구축하는 웹에 큰 문제가 있었다.

     

    메뉴버튼을 통해 페이지에 접속하면 해당 메뉴바가 적절히 펼쳐지고 서브메뉴가 선택상태로 변경되지만 url을 통해 직접 접근할경우엔 메뉴가 펼쳐지지 않는 문제였다.

     

    코드를 분석해보니 메뉴를 직접 클릭할 경우 펼쳐야할 메뉴정보를 controller로 전달하고 controller에서 model에 담아 페이지를 열때 해당 메뉴를 자동으로 펼치도록 로직이 작성되어 있었다.

     

    메뉴는 동적으로 생성 및 수정 삭제가 가능하며 url과 메뉴이름 메뉴코드등을 db에 저장하고있다.

     

    일단 해당 현상을 해결할 핵심 아이디어는 HttpServletRequest에 담겨있는 requestURI 정보를 토대로 db에서 메뉴코드를 찾아서 메뉴코드가 파라미터로 넘어오지 않더라도 어떤 메뉴가 호출된 것인지 알려주는 방법을 떠올렸다.

     

    문제는 이 공통코드를 컨트롤러마다 전부 추가해주는건 무리라는 것이다. 컨트롤러가 셀수없이 많고 페이지를 추가할때 모두가 이 내용을 숙지하고 코드를 추가한다는 보장이 없다.

     

    처음 떠올린건 Spring AOP를 통해 횡단관심사를 처리하는 방법이었다.

    하지만 여기에도 문제는 있었다 포인트컷 설정을 위해 해당방법을 사용할 모든 컨트롤러를 구분해야 한다는 것이고 이것또한 불가능에 가깝지만 어찌어찌 전부 찾아서 조인포인트로 지정해준다고 하더라도 애너테이션 기반으로 AOP를 작성한다면 페이지를 추가할때마다 해당 애너테이션을 붙여줘야 한다는 점이다.

     

    어떻게하면 기존 코드를 건드리지 않고 메뉴정보가 담기지 않았을떄만 메뉴정보를 넣어줄 수 있을까를 고민하다가 Spring interceptor를 이용한 처리방법이 떠올랐다.

     

    메뉴정보는 같은이름의 키값으로 model에 담기며 각 페이지의 jsp마다 해당 model 키값으로 메뉴를 찾아 펼쳐주게된다. 즉 interceptor의 post handle을 통해 model에 메뉴값이 존재하지 않는다면 그때 찾아서 매핑해주면 되는 것이다.

     

    여기까지 로직을 작성하고나니 정상적으로 동작했지만 문제가 한가지 생겼다. 로딩속도가 눈에띄도록 느려졌다는 것이다. 

     

    조금 분석을해보니 웹에서 사용하는 수많은 ajax에도 해당 로직이 적용되어 계속 db에 select문을 실행시키게 된다. ajax를 구분할 수 있는 방법이 뭐가있을지 고민해봤지만 header에도 따로 구분할만한 데이터가 담기지 않아서 이방법은 포기하고 다른쪽으로 생각을 돌렸다.

     

    바로, was 실행시에 한번만 모든 메뉴정보를 조회해서 캐싱해두고 각 http request마다 db에 접근하지않고 해당 캐시를 통해서 값을 찾는 것이다. key는 uri로, value는 해당 메뉴의 코드로 캐시를 만들고 적용했다. 그리고 메뉴를 수정, 삭제, 삽입하는 로직이 끝났을때 interceptor가 가지고있는 캐시를 새로 로드하도록 작성했다.

     

    결과는 성공적이다. 로딩속도는 전과 차이가 전혀없을만큼 빨라졌으며 모든 페이지에 url을 통해 직접 접근하더라도 정상적으로 메뉴가 펼쳐졌다. 또 한 기존에 그 어떤 코드도 수정하지 않고 정상적으로 적용할 수 있었다.

     

    사실 컨트롤러 전체적인 코드를 수정하고 메뉴자체를 모듈화하고 메뉴만을 위한 인터셉터를 두는게 좋을것이다. 하지만 할 일이 많은관계로 시간이 나면 그때 다른 여러 문제점과 같이 수정해야할 과제이다.

     

    횡단 관심사 = AOP라는 공식을 머리에 넣어뒀었는데 인터셉터역시 http요청의 횡단관심사를 해결할 수 있는 좋은 옵션이라는걸 다시한번 상기하는 기회가 되었다.

Designed by Tistory.