본문 바로가기
Web/Spring

[Spring/Java] Spring 인터셉터 구현하기

by char_lie 2024. 4. 20.
반응형

스프링의 여러가지 기능 중 인터셉터 기능을 구현 및 정리해보고자 한다. 앞서 인터셉터 기능을 프론트/리액트를 이용하여구성 해봤으나, 백엔드/스프링에서는 구현해본 경험이 없기에 간략하게 정리하려한다.

코드는 앞서 로그인 구현 시에 작성했던 코드를 사용하였다


 

Spring 인터셉터란?

 

- HTTP 메서드에서 요청을 가로채서 개발자가 원하는 동작을 추가하는 역할

- 주로 공통 로그 처리, 권한 체크 등의 역할에 사용 (ex : 로그인 해야 이용할 수 있는 페이지)

- 로그인 여부에 따른 로그인 페이지 redirect 등 사용 가능

 

HandlerInterceptor

PreHandler()

  • 컨트롤러가 실행되기 전에 실행되며 실행 이전에 요청 정보를 추가하는 경우 사용
  • return 값은 Boolean 타입으로 적용하며 false일 경우 다음 HandlerInterceptor을 실행하지 않음

postHandler()

  • 컨트롤러 실행 후, View가 생성되기 전에 실행되며 컨트롤러에서 View의 정보를 전달하기 위해 작업한 모델의 정보를 참조하거나 변화시 사용
  • PreHandler()가 false일 경우 동작하지 않고, 비동기 요청 처리 시에는 처리되지 않음

afterCompletion()

  • View의 모든 작업이 완료된 후에 실행됨
  • PreHandler()가 false일 경우 동작하지 않고, 비동기 요청 처리 시에는 처리되지 않음

구현하기 (로그인 기능)

인터샙터 생성

import static com.example.demo.global.status.FailCode.DELETED_USER;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.example.demo.Member.Db.Member;
import com.example.demo.Member.Db.MemberRepository;
import com.example.demo.global.exception.GlobalRuntimeException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class LoginInterceptor implements HandlerInterceptor {

    private final MemberRepository memberRepository;
    public LoginInterceptor(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 여러가지 기능 추가 가능 (로그인 여부 확인 등)
        // 아래는 예시로 login으로 들어왔을 때 체크해서 탈퇴된 유저인지 체크하는 로직
        if (request.getRequestURI().equals("/api/auth/login")) {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(request.getInputStream());
        
            String email = rootNode.get("email").asText();
            Member member = memberRepository.findbyEmail(email).orElse(null);

            System.out.println(email);
            if (member != null && member.isDeleted()) {
                throw new GlobalRuntimeException(DELETED_USER);
            }
        }
        return true;
    }
}

인터셉터를 구성해주고 Prehandler를 구현해보았다. 내가 사용한 예시는 탈퇴여부만 간단하게 체크하여 에러를 발생시켜버리는 로직을 작성했다.

사용 예시로는 인증이 안되어있으면 return false를 이용해 동작하지 않게하고, 다른 URI로 리다이렉트 시키는 방법을 사용할 수 있다.

이렇게 작성한 인터셉터를 사용하기 위해서는 등록 과정을 해줘야한다.

반응형

인터샙터 등록

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final LoginInterceptor loginInterceptor;

    public WebMvcConfig(LoginInterceptor loginInterceptor) {
        this.loginInterceptor = loginInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor);
    }
}

여기서 addInterceptors() 매서드를 오버라이딩하여 인터셉터를 registery에 추가해준다.

이때 사용할 수 있는 함수로는

- order() : 인터셉터의 호출 순서 지정(낮을수록 우선순위 높음)

- addPathPatterens() : 인터셉터를 적용할 URI 패턴 지정, "/**"를 통해 모든 경로에 인터셉터를 지정해 줄 수 있다.

- excludePathPatterns() : 인터셉터에서 제외할 패턴을 지정할 수 있다.

 

반응형

댓글