필터, 인터셉터, AOP를 사용해보자! (24.05.14)

YJ·2024년 5월 14일
post-thumbnail

블로그 작성법
목표 > 공부한 내용 > 얻었고, 앞으로 이걸 해봐야지 적기

✋ 수업 목표

  • Java Enum 타입에 대해 배워보자.
  • 내부 클래스를 선언하는 이유에 대해 배워보자.
  • 필터, 인터셉터, AOP에 대해 알아보자.

🤔 공부한 내용

Enum

상수(매개변수1, 매개변수2); // 외부 상수: 객체
private final 상수;

enum ENUMDEMO { // 외부에서 쓸 수 있는 상수를 만들 수 있는 틀
private final 상수;
EnumDemo(매개변수) {
this.상수 = 매개변수;
}
}

외부에서 쓰고 싶은 방법 EnumDemo.상수

참고자료
우아한기술블로그-Java Enum 활용기

내부 클래스 (클래스 안에 클래스 선언하기)의 장점

코드

package com.shoppingmall.shoppingmall.member;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public class ApiResult<T> {
    boolean success;
    T response;
    ApiError error;
}

class ApiError {
    String message;
    HttpStatus httpStatus;
}

장점

  • 국소적으로 사용되는 클래스
  • 캡슐화
  • 감싸고 있는 클래스 필드
  • 코드 구조 깔끔

406 에러

406 에러는 주로 Response 리턴 값을 바꾸면 발생한다.

  • DTO
  • ResponseEntity
  • 자체 제작 ResponseEntity
    1) 결과 값을 클라이언트에서 역직렬화하기 실패
    JSON과 Java의 Mapping
    2) 내부 클래스?
    3) ApiResult 구조 이상?

해결 방법
Response Format 클래스들에 getter를 추가해준다.

왜 getter를 Response Format 클래스에 추가하면 해결될까?

스프링은 잭슨 라이브러리를 사용하여
프론트로 응답할 때, Object -> JSON 형식으로 변환하여 반환한다.
이때, Object의 필드 값을 잭슨 라이브러리가 JSON으로 변환하기 위해 필요한데, 필드를 가져오기 위한 get 메서드가 구현되어 있지 않아서
406 에러가 발생한 것이다.
따라서, 반환하는 클래스에서는 객체에 대해 getter를 구현해줌으로써
JSON으로 올바르게 변환하여 응답될 수 있다.

not enclosing class

해결

내부 클래스를 static으로 선언하였다.
이것이 내부 클래스의 장점이다.

밖에서 내부 클래스 객체를 생성하기 위해서는
내부 클래스에 static을 선언하여 해결할 수 있다.

InvalidDefinitionException

이 문제 역시 getter를 구현함으로써 해결할 수 있다.

Jasckson 라이브러리는 어떻게 동작할까?

참고자료
https://blog.naver.com/hj_kim97/222391370482

Response Format 응답 코드 리팩토링

import org.springframework.http.HttpStatus;

public class ApiUtils<T> {
    public ApiResult<T> success(T data) {
        return new ApiResult(true, data, null);
    }

    public ApiResult error(String message, HttpStatus httpStatus) {
        return new ApiResult<>(false, null, new ApiResult.ApiError(message, httpStatus));
    }
}

지금 형태는
ApiUtils -> ApiResult -> ApiError 형태이다.

이렇게 고치는 편이 더 좋겠다.

ApiUtils 
   
     -> ApiResult
	 
     -> ApiError

제네릭 메소드

반환 타입이 제네릭 클래스로 만든 객체일 때

메소드 선언부 반환타입 앞에 <T>

class GenericsMethod {
  	static <T> GenericsClass<T> returnGenericsObject() {
  		return new GenericsClass<T>();
  	}
  }
  
class GenericsClass {
  	T field;
  }

제네릭 클래스는 필드의 타입을 제네릭으로 사용해야 할때
제네릭 메서드는 반환 타입, 매개변수 타입을 제네릭으로 사용해야 할때

AOP

Aspect Oriented Programming: 관점 지향 프로그래밍

네이버 스토어에서 구매하기 버튼을 누른다고 가정하자.

구매하기 : 버튼 클릭 > 상품id, 수량 ... > 구매 로직 .. DB
문의하기 : 버튼 클릭 > 아이디, 상품 id ... > 문의 로직 .. DB
찜하기 : 버튼 클릭 > 아이디, 상품 id ... > ... DB

각각의 개발자들이 이러한 관점에 대해서 생각을 하겠지.

지금까지의 관점을 가로 관점 이라고 생각하자.
이제 세로 관점을 생각해보자.

구매하기 버튼을 눌러보자.

로그인 체크를 진행한다.
구매하기 : 버튼 클릭 > 로그인 여부 체크 > 상품id, 수량 ... > 구매 로직 ..DB

문의하기, 찜하기 역시 로그인이 먼저 필요하다.
구매하기 : 버튼 클릭 > 로그인 여부 체크 > 상품id, 수량 ... > 구매 로직 .. DB
문의하기 : 버튼 클릭 > 로그인 여부 체크 > 아이디, 상품 id ... > 문의 로직 .. DB
찜하기 : 버튼 클릭 > 로그인 여부 체크 > 아이디, 상품 id ... > ... DB

만약에 3명의 개발자가 각각 로그인 여부 체크 로직을 짠다면?
동일한 로직을 각자가 개발할 것이다.
그러면, 로그인 여부 체크 로직이 3개나 생기는거 아닌가?

여기서 나온게 AOP이다.
로직에서 공통된 부분을 뽑아내서 개발 하는 것이다.
위 3가지 로직에서 공통된 부분은 로그인 여부 체크 부분이다.

공통된 부분은 어떻게 구현해야 할까?

새로운 개발자를 구한다.
이 개발자는 로그인 여부 담당자로 임명한다.
로그인 여부 담당자는 로그인 여부 체크만 할 것 이다.

이제 4명의 개발자가 생긴다.
구매하기 담당자
문의하기 담당자
찜하기 담당자
로그인 담당자

위 3명의 담당자는 로그인 담당자에게 로그인 하는 부분만 달라고 한 후 사용한다.

이를 Spring에서 제공해준다.

이제 다음과 같은 상황을 생각하자.
1. 로그인을 요구하는 부분이 매우 많아질 경우
2. 로직 중간에 로그인 세션이 만료될 경우

이러한 상황으로 인해 우리는
로그인 요청을 언제 어디서든 산발적으로 호출할 것이다.

호출되는 위치마다 직접 로그인을 구현할 것인가?
아니다.
Spring에게 단순히 로그인 요청 기능 줘라고 어노테이션을 사용하면 된다. 그러면 Spring은 해당 기능을 언제 어디서든 제공해줄 것 이다.

Spring이 제공하는 공통 기능(프로세스) 처리 방안 3가지

로그인 체크, 인코딩 변환, 중복 기능
1) 필터
2) 인터셉터
3) AOP

cf. 프로그래밍 용어: 현실 세상

필터
1. 잘못된 요청 처리
2. 인코딩 체크

인터셉터
1. 체크하고 돌려주고
2. 성능 체크

AOP
1. 기능들을 곳곳에 심어주고 싶을 때

필터

  1. Filter 등록 확인

    Filter - init
    : Filter가 등록될 때 호출되는 메소드

  2. 어떤 url로 요청이 올 때 필터를 거칠 것인지 등록

  3. 요청

  4. DispatcherServlet 초기화가 완료 된 후 요청 처리 전, 후에 필터 메서드 호출

참고자료
https://songacoding.tistory.com/138

인터셉터


1. 필터 요청 전 호출
2. 인터셉터 preHandle 호출
3. 컨트롤러 호출
4. 인터셉터 postHandle 호출
5. 인터셉터 완료 호출

인터셉트를 적용하기 위해 @Configuration 파일을 추가하였다.

필터에는 chain이 있다면 인터셉터에는 registry가 있다.

  • 여기서부터 Spring Security가 시작된다.
    (Security는 자기만의 필터와 인터셉터, AOP가 구현되어 있다. 그거를 불러다가 사용하는게 Spring Security)

AOP

  1. AOP 다운로드
    https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop/3.2.5

  2. 요청

  3. 결과

알쓸송잡
	프로젝트 기술서
    * 내가 자소서, 이력서, 포트폴리오 쓰기 위한 베이스
    * 회사에 따라서 제출하라고도함
    * 1) 이슈 (문제, 특정 기술 여러 개 중 선택) - 해결 방안 (기술 선택)
    * 2) 설계 (컴포넌트, ERD, 패키지 구조) - 깃허브 리드미
    * 3) 주요 기능 [내 기능]
    
    면접에서는 접속사 없이, 부정어 없이 (하지만, 그런데)

	이력서 (명사형)
    장점: 프로젝트 경험 <-> 기술 스택
    프로젝트 경험: 개요(기술스택, 모둘, API 한문장), 기간, 역할, 기능, 이슈, 해결방안
    해결방안이 없는 이슈는 제기하면 안된다.
    학력, 교육, 이수, 자격증
    경력에 잘한 프로젝트 적어도 된다.
    
    포트폴리오 (문장형) - 디자인 x, 까만 바탕에 하얀 글씨만 아니면 됨
    조금 더 풀어서 작성해도 된다.
    적당한 양: PPT 기준으로 1 페이지
    
    백엔드
    남들이 이해 잘되는 코드를 작성
    클린 코드(코드 캡처)
    성능, 예외 처리, 메소드 추출 잘한 곳 스크린 샷
    
    프론트엔드
    컴포넌트 구조
    
    * 개인 프로젝트
    최소 3주 / 1달 : 개인 프로젝트
    1. 지금 하는 것 복습 겸 따라가기
    2. 기능 조금 추가
    3. 블로그 카테고리 하나 만들어서 고민거리, 진행상황 스프린트 회고
    
    
    

😉 앞으로 이걸 해봐야지

오늘은 Enum을 사용하는 이유와 내부 클래스의 장점, 그리고 필터, 인터셉터, AOP에 대해 배워보았다.
필터, 인터셉터, AOP가 어느 라이프 사이클에서 돌아가는지 확인하고, 이것을 어떻게 사용해야할지 고민해봐야겠다. 그리고, 내부 클래스를 구현함으로써 코드를 간결하게, 필드로써 활용해보는 연습을 가져야겠다.

profile
dev

0개의 댓글