트러블 슈팅

AOP 적용에 대한 고찰

수달하나 2024. 6. 18. 23:40

애플리케이션 구조

현재 개발중인 서버는 캐시 서버가 따로 존재하지 않는다.

따라서 캐시관리를 위해 코어 서버에서 직접 캐시를 관리해야 하고 그 과정에서 싱글톤 패턴을 이용해 각 모듈에 맞는 캐시를 따로 관리하고 있다.

 

각각의 모듈을 위와 같이 서로다른 형태의 캐시를 가지고 있고 각 모듈은 각각의 캐시 상태를 통해 복잡한 로직을 수행하고 있다.

 

최근에 모듈A 에서 모듈B의 캐시를 참조해야 하는 상황이 발생했는데 이 부분을 어떻게 해결해야 할 것인지를 고민했다.

개발을 하다보면 하나의 책임만을  수행할 수 있도록하는 단일 책임 원칙을 고수하는것이 원칙인데 이 부분을 지키자니 작은 곳에서 사용하는데 너무 큰 자원을 낭비해야 하는 상황이 발생했고 결국엔 그 부분만 예외적으로 참고할 수 있도록 해당 원칙을 무시하기로 했다.

 

이 부분은 사수께도 말씀을 드렸지만 구조를 변경하게 된다면 잃을 것이 더 많은 상황이라는 것에 동의, 어쩔 수 없는 조치였다. 한편으로는 애초에 캐시 관리에 대한 아키텍처 설계를 좀 다르게 진행했다면 어땠을까 라는 생각을 갖는 계기가 되었다.

 

 

이슈 발생

얼마 지나지 않아서 새로운 이슈가 발생했다. 

각각의 모듈은 각자 다른 캐시를 참고 하고 있고 각 캐시에서 관리하는 자료구조는 모두 상이하다.

캐시는 대부분 ConcurrentHashMap 구현체를 사용해 key, value 쌍으로 데이터를 관리하고 있고 그 데이터의 수는 어마어마하다. 

 

문제는 실제로 애플리케이션 런타임 환경에서 key 가 변경될 수 있는 일이 발생했고 key 변경이 이슈가 다른 캐시에 전파 된다는 것이었다.

속성 변경이 발생하게 되면 각각의 캐시에서는 데이터 구현체의 key 값을 변경 해야 하고 이 과정이 모든 캐시에서 동시다발적으로 발생해야 했다. 

또한 각 캐시는 하나의 속성에 같은 key 값을 갖는 것이 아니고 속성안의 여러 정보들 중 하나의 값으로 key 값을 갖고 있는 상황이었다. 

하나의 큰 속성안에 속성A 와 속성B 가 존재하고 각 속성의 변경여부가 캐시에 영향을 줄 수 있는 이 상황을 어떤 방식으로 해결해야 할 것인지에 대한 생각을 하기로 했다.

 

해결 방법

필요에 따라서 각 캐시는 새로운 자료구조를 추가해야 하는 경우가 빈번하게 발생했고 그에 따라서 업데이트 로직을 매번 구현한다는것이 너무나 번거롭고 개발자의 실수를 유발 할 수 있다는 생각이 들었다.

따라서 자동적으로 변경에 대한 감지를 할 수 있는 방법이 없을까를 고민하다 가장 먼저 떠오른 방법은 AOP를 이용하여 변경을 전파하는 방법 이었다.

AspectJ 를 이용하여 특정 맵을 타겟팅하도록 구현하여 각 클래스의 특정 맵에 대해 업데이트를 수행하도록 하고, 필요한 경우 추가적인 조건을 통해서 타겟팅할 수 있지 않을까 라는 생각을 했다.

 

하지만 문제는 AOP를 이용하는것이 옳은 설계 방법인가에 대한 생각을 하게 됬다.

각 모듈의 캐시 업데이트를 동일한 관점으로 볼 수 있는가에 대한 근거가 부족하다고 생각했다. 

 

 

 

 

 

글 쓰기 순서

1. 현재 캐시 상태

2. 이전에 발생한 문제 다른 모듈에서 다른캐시 참조 -> 아쉬웠던 부분 서술

3. 새롭게 발생한 문제

4. 업데이트 방향성에 대한 고찰

5. 해결 방법

6. aop 적용 방안

7. 아쉬운 부분