230421 TIL #65 AOP 구현

김춘복·2023년 4월 21일
0

TIL : Today I Learned

목록 보기
65/543
post-custom-banner

230421 Today I Learned

실전 프로젝트 4주차. 오늘 TIL에는 어제 구현한 aop에대해 적어보려 한다.


AOP 구현

  • 문제 : jmeter말고 브라우저에서도 실제 사이트를 이용할 때 서버 응답속도를 체크하고 싶었다.
    그런데 응답 속도를 체크하는 로직을 추가하는 것 때문에 실제 응답속도가 느려지면 안되니 테스트에는 영향이 가지 않게 설계해야 했다.

  • 시도 :

  1. 프론트에서 구현
    ajax 요청을 보낼 때 beforeSend로 startTime을 기록하고 success문에 endTime을 기록해서 응답속도를 체크해 aop를 사용하지 않고 응답속도를 체크하게 구현해봤다.
    하지만 실제 로직의 응답속도보다 더 느리게 찍히고, 중간에 alert가 있으면 그걸 끌 때까지 endTime이 제대로 찍히지 않아서 drop.

  2. admin용 컨트롤러를 따로 만들어서 거기에다가 aop 적용
    이러면 프론트에서 admin회원일경우 따로 admin용 ajax를 만들어 처리해야 되어 drop

  3. test용 컨트롤러를 따로 만들기
    test용 컨트롤러만 따로 만들어서 원래 쓰던 service에 연결해 aop를 적용하지 않게하고, 원래 쓰던 컨트롤러(프론트에 연결되어있는)에만 aop를 적용하는 방법도 있었다.
    그런데 아무리 챌린지 프로젝트라 해도 이방법은 좀 아닌거 같아서 drop

  • 해결 :
    원래 로직에 aop를 걸어두되 파라미터로 받는 userdetails의 userrole 체크를 통해 admin만 시간을 체크하고 jmeter로 테스트를 받게되는 일반 유저는 그냥 바로 실행해두도록 구현했다.
@Aspect
@Component
public class ResponseTimeAop {

  @Around("execution(public * com.example.neticket.reservation.controller.ReservationController.makeReservations(..)) && args(.., userDetails)")
  public Object checkResponseTime(ProceedingJoinPoint joinPoint, UserDetailsImpl userDetails) throws Throwable{

    boolean isAdmin = userDetails.getAuthorities().stream()
        .anyMatch(authority -> authority.getAuthority().equals("ROLE_ADMIN"));

    if (!isAdmin) return joinPoint.proceed();

    long startTime = System.currentTimeMillis();

    try {
      return joinPoint.proceed();
    } finally {
      long responseTime = System.currentTimeMillis() - startTime;
//      responseTime을 http response header에 "X-Response-Time" 키값에다가 value로 삽입해서 반환
      ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      if (requestAttributes != null) {
        HttpServletResponse response = requestAttributes.getResponse();
        if (response != null) {
          response.setHeader("X-Response-Time", String.valueOf(responseTime));
        }
 }}}}
  • 포인트컷은 일단은 컨트롤러의 예매하기 api 메서드 하나에만 적용하고 args(.., userDetails)로 2번째 인자인 userDetails를 받았다.
  • admin이 아니면 바로 원래 api를 실행시키고 admin이면 시작 시간을 재고 api가 완료되면 responseTime을 쟀다.
  • aop에서 측정한 값을 어떻게 클라이언트에게 주는지에 대해 고민을 많이 했다.
    따로 log를 측정할지, Entity를 만들어서 log 기록을 하게 할지, body에 같이 줄지 고민하다가 그냥 response의 header에 값을 주는게 가장 나은 것 같아 채택했다.

  • X-Response-Time 라는 임의의 key에 responseTime을 string으로 넣어 보내면 프론트에서 이 값을 받아 로컬 스토리지에 저장해 다음 페이지에서 보여주게 했다.

  • admin이 아닌 유저도 aop를 거치긴 해서 여기서 성능의 저하나 응답시간의 손해가 있을 수 있다고 생각했는데 간단한 로직이라 그런지 테스트 결과 속도에 크게 지장이 없었다.

  • 이번에는 간단하게만 aop를 적용해봤는데 다르게 쓸 방법이 있는지 찾아보려고 한다.

profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글