- μ΄λλ―Ό API λ©μλ μ€ν μ νμ μμ²/μλ΅ λ°μ΄ν°λ₯Ό λ‘κΉ ν©λλ€.
- λ‘κΉ λ΄μ©μλ λ€μμ΄ ν¬ν¨λμ΄μΌ ν©λλ€:
- μμ²ν μ¬μ©μμ ID
- API μμ² μκ°
- API μμ² URL
- μμ² λ³Έλ¬Έ(
RequestBody)- μλ΅ λ³Έλ¬Έ(
ResponseBody)
@Aspect : AOP ν΄λμ€λ₯Ό μ μνλ μ΄λ
Έν
μ΄μ
μΌλ‘ κ³΅ν΅ κ΄μ¬μ¬λ₯Ό λ΄λ μν μ νλ€.@Pointcut : κ΄μ¬ λμ λ©μλλ₯Ό μ§μ νλ μ΄λ
Έν
μ΄μ
@Pointcut("execution(* μμΉ ννμ)")
public void startPoint() {}
볡μ‘ν μμΉ ννμμ @Pointcut μ μ¬μ©νμ¬ λ©μλλ‘ μΆμνν΄ μ΄λ¦μ λΆμΌ μ μλ€.
μ΄λ κ² μ μλ λ©μλλ€μ Advice μμ "startPoint()" μ²λΌ μ¬μ¬μ©νμ¬ μ½κ² μ μ©ν μ μλ€.
Advice : ꡬ체μ μΈ μ€νλ‘μ§μ λν΄ μ μνλ©° μλ μ΄λ
Έν
μ΄μ
μ λ°λΌ μ€ν μμ μ μ νλ€.@Before : λ©μλ μ€ν μ λμ@After : λ©μλ μ€ν ν λμ@Around : λ©μλ μ€ν μ νμ λμνλ©° μ€νμ μ§μ μ μ΄ν μ μλ€@AfterReturning : λ©μλκ° μ±κ³΅μ μΌλ‘ λ°νλ ν λμ@AfterThrowing : λ©μλμμ μμΈκ° λ°μνμ λ λμLoggingAspect@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class LoggingAspect {
private final ObjectMapper objectMapper;
@Pointcut("execution(* org.example.expert.domain.user.controller.UserAdminController.*(..)) ||"
+ " execution(* org.example.expert.domain.comment.controller.CommentAdminController.*(..))")
public void adminMethod() {}
@Around("adminMethod()")
public Object beforeLogging(ProceedingJoinPoint joinPoint) throws Throwable {
//μ€λ λ μμμ request κ°μ²΄ κ°μ Έμ€κΈ°
HttpServletRequest request = ((ServletRequestAttributes)Objects.requireNonNull(
RequestContextHolder.getRequestAttributes())).getRequest();
//μ€νμ€μΈ λ©μλ μ 보
Method joinMethod = ((MethodSignature)joinPoint.getSignature()).getMethod();
//λ©μλ νλΌλ―Έν° μ 보 λ° μ€μ κ°
Parameter[] params = joinMethod.getParameters();
Object[] args = joinPoint.getArgs();
//μμ², μλ΅ λ°λκ°μ λ΄μ λ¬Έμμ΄ null -> κ°μ΄ μκ±°λ μ§λ ¬ν μ€ν¨
String requestBody = null;
String responseBody = null;
// μμ² λ³Έλ¬Έ μ§λ ¬ν μλ
try {
for (int i = 0; i < args.length; i++) {
if (params[i].isAnnotationPresent(RequestBody.class)) {
requestBody = objectMapper.writeValueAsString(args[i]);
}
}
} catch (JsonProcessingException e) {
log.warn("requestBody μ§λ ¬ν μ€ν¨ : {}", e.getMessage());
}
String url = request.getRequestURI();
log.info("[Method Before] path={}, timestamp={}, requestBody={} ", url, LocalDateTime.now(), requestBody);
//μ€μ λ©μλ μ€ν λ° κ²°κ³Ό μ μ₯
Object result = joinPoint.proceed();
// μλ΅ λ³Έλ¬Έ μ§λ ¬ν μλ
try {
responseBody = objectMapper.writeValueAsString(result);
} catch (JsonProcessingException e) {
log.warn("responseBody μ§λ ¬ν μ€ν¨ : {}", e.getMessage());
}
log.info("[Method After] path={}, timestamp={}, responseBody={} ", url, LocalDateTime.now(), responseBody);
return result;
}
}
μ΄λλ―Ό μμ²μ΄ νμν λ©μλλ€μ λν΄ κ³΅ν΅ λ‘κΉ
λ‘μ§μ μννλ Aspect μ΄λ€.
@Around μ΄λλ°μ΄μ€λ₯Ό νμ©ν΄ λ©μλ μ€ν μ νμ μμ²κ³Ό μλ΅ λ°μ΄ν°λ₯Ό νλ²μ μ²λ¦¬ν μ μλλ‘ κ΅¬μ±νλ€.
λ©μλ μ€νμ RequestBody μ΄λ
Έν
μ΄μ
μ΄ λΆμ νλΌλ―Έν°λ₯Ό μ°Ύμ μμ² λ³Έλ¬Έμ μΆμΆνκ³ μ€ν ν λ°νκ°λ μ§λ ¬νν΄ μλ΅ λ³Έλ¬ΈμΌλ‘ λ‘κ·Έμ λ¨κΈ΄λ€.