이번 프로젝트에서 인터셉터를 추가하란 과제 발제로, 인터셉터에 대한 개념을 간략하게나마 조사하고 코드에 적용해보기로 함.
하지만 역시 개념과 실제 코드 적용은 쉽지 않았고, 계속 에러가 발생.
특히 JwtFilter와 Interceptor의 역할분담이 가장 난감했다.
우선 과제발제부터 차근히 정리해보기로 하고, 하나씩 풀어나가기로 함.
📚<과제 요구사항>
1. 어드민 사용자만 접근할 수 있는 특정 API에는 접근할 때마다 접근 로그를 기록해야 합니다.(댓글 삭제 API, 유저권한 변경 API)
2. 요청 정보(HttpServletRequest)를 사전 처리합니다.
3. 어드민 권한 여부를 확인하여 인증되지 않은 사용자의 접근을 차단합니다.
4. 인증 성공 시, 요청 시각과 URL을 로깅하도록 구현하세요.
5. 어드민 인증 여부를 확인합니다.
6. 인증되지 않은 경우 예외를 발생시킵니다.
7. 로깅은Logger클래스를 활용하여 기록합니다.

'Filter는 클라이언의 요청 정보 중에서 Controller에 도달하기 전에 필요 없는 정보를 거르는 역할 이다' 정도의 개념만 알고 있던 나는 Interceptor에 대해 구글링을 했고, 대략적으로 Filter는 servlet 에서 거르는 역할이라면, Interceptor 는 Filter를 거쳐 그 안의 Spring mvc 내부 Context에서 controller 직전에서 다시 한 번 더 거르는 역할이라는 개념을 갖게 됐다.
로깅은 프로그램 실행 도중 발생하는 에러나 정보를 기록하는 개념.
java에서 System.out.println 을 쓰면서 단계별로 에러를 확인하는 절차도 로깅인 셈이다.
과제 요구사항대로 logger클래스를 적용해야 하므로, logger클래스에 대해 조사.
logger 메소드는 이벤트 상황과 중요도에 따라 레벨이 나뉘는데, 총 6가지로 나눈다.
logger.trace("🚀 가장 상세한 로그 (디버깅보다 더 많은 정보)");
logger.debug("🐞 디버깅 정보 (개발할 때 유용)");
logger.info("📢 일반적인 실행 정보 (서비스 동작 관련)");
logger.warn("⚠️ 경고 메시지 (문제가 될 수 있는 상황)");
logger.error("❌ 에러 발생 (예외 등)");
logger.fetal(" 💥 치명적인 에러 (시스템 다운 가능성))"
logger클래스를 생성하면 default로 info가 설정되며, 그보다 낮은 레벨인 debug와 trace는 적용되지 않으므로 쓰지 않거나, 기준을 trace로 낮춰야한다.
1. 어드민 사용자만 접근할 수 있는 특정 API에는 접근할 때마다 접근 로그를 기록해야 합니다.(댓글 삭제 API, 유저권한 변경 API)
❓이미 JwtFilter에서 User정보를 가져와서 권한 없는 User는 제외시켰는데, Interceptor에서 또다시 User 정보를 가져올 필요가 있을까?
gpt에게 물어보니 filter와 interceptor는 구현 목적과 시점이 다르기 때문에 2번 인증이 필요한 경우가 있지만, 이번 경우는 굳이 할 필요 없다함.
(📌둘의 역할을 크게 나누면 filter는 인증, interceptor는 인가로 보면 될 것 같다)
JwtFilter를 다시 읽어보니
JwtFilter.class{
....
httpRequest.setAttribute("userRole", claims.get("userRole"));
이미 request에 userRole값을 넣은 것을 확인.
최종적으로, Interceptor에서 그 값을 꺼내와서 검증 하는 걸로 역할을 분담함.
AdminInterceptor.class{
...
String userRole = (String) request.getAttribute("userRole");
if (!"ADMIN".equals(userRole)) {
User가 ADMIN일 때는 controller가 정상적으로 실행되고, log도 정상 출력됨을 확인.
2. 요청 정보(HttpServletRequest)를 사전 처리합니다.
3. 어드민 권한 여부를 확인하여 인증되지 않은 사용자의 접근을 차단합니다.
4. 인증 성공 시, 요청 시각과 URL을 로깅하도록 구현하세요.
5. 어드민 인증 여부를 확인합니다.
7. 로깅은 Logger 클래스를 활용하여 기록합니다.
하지만 User가 ADMIN이 아닐 때는 Interceptor가 작동되지 않아서,
고민 후 JwtFilter를 자세히 읽어보니 이미 기능이 있음을 확인.
if (url.startsWith("/admin")) {
if (!UserRole.ADMIN.equals(userRole)) {
```
이미 url에 admin이 포함된 경우 filter에서 거르기 때문에, interceptor가 작동하지 않았던 것.
ADMIN은 왜 작동했냐면 filter의 if문에 걸리지 않았기 때문.
결국 이 부분을 주석처리해서 해결함.
6. 인증되지 않은 경우 예외를 발생시킵니다.

->주석으로 처리