상세 컨텐츠

본문 제목

[nestJS] ValidationPipe에 대해서

카테고리 없음

by esoesmio 2024. 5. 10. 17:10

본문

이 코드는 NestJS 프레임워크에서 사용되는 `BoardStatusValidationPipe`라는 커스텀 파이프를 구현한 것입니다. 이 파이프의 목적은 사용자로부터 받은 입력 값의 유효성을 검증하고, 그 값이 특정 열거형(`enum`) 상태 값들 중 하나인지 확인하는 것입니다. 자세히 살펴보겠습니다.

### `BoardStatusValidationPipe` 클래스 설명

1. **클래스 및 임포트**: 
   `BoardStatusValidationPipe` 클래스는 `PipeTransform` 인터페이스를 구현합니다. 이는 모든 파이프가 구현해야 하는 인터페이스로, `transform` 메서드를 정의해야 합니다. `BadRequestException`은 유효하지 않은 입력에 대해 예외를 발생시키는 데 사용됩니다. `BoardStatus`는 상태를 정의하는 열거형입니다.

2. **`StatusOptions` 배열**:
   이 배열은 유효한 상태 옵션을 저장하며, 여기서는 `BoardStatus.PRIVATE`와 `BoardStatus.PUBLIC` 두 가지 값을 포함합니다.

3. **`transform` 메서드**:
   - 입력 값(`value`)을 대문자로 변환합니다.
   - `isStatusValid` 메서드를 호출하여 값의 유효성을 검사합니다. 유효하지 않으면 `BadRequestException`을 발생시키며, 예외 메시지로 유효하지 않은 값과 함께 에러 메시지를 전달합니다.

4. **`isStatusValid` 메서드**:
   - `StatusOptions` 배열에서 주어진 상태(`status`)의 인덱스를 찾습니다.
   - 인덱스가 -1이면(false가 되어야 함) 해당 상태가 배열에 없다는 것을 의미합니다. 여기서는 로직에 오류가 있는데, `index !== -1`이 되어야 모든 유효한 인덱스를 포함할 수 있습니다. 현재 코드는 오직 `index !== 1`만을 검사하므로 오직 한 가지 상태만 유효하다고 인식됩니다.

### NestJS에서 파이프의 사용 목적

NestJS에서 파이프는 클라이언트로부터 서버로의 데이터 전달 과정에서 데이터 변환(transforming)과 데이터 유효성 검사(validation)를 처리하는 데 사용됩니다. 파이프는 메서드 실행 전에 데이터를 가공하거나 확인하여, 컨트롤러의 비즈니스 로직이 실행되기 전에 데이터가 올바른 형식이거나 조건을 만족하는지 보장합니다.

### Spring Framework와의 대응 개념

Spring Framework에서는 `ControllerAdvice` 또는 `@Valid` 어노테이션과 같은 방법으로 유효성 검사를 처리할 수 있습니다. 또한, `HandlerInterceptor` 인터페이스를 구현하여 요청을 가로채고 전/후 처리를 할 수 있습니다. 이들은 NestJS의 파이프와 유사한 역할을 수행하지만, 구현 방식과 사용 방법에는 차이가 있습니다. Spring에서는 AOP(Aspect-Oriented Programming)를 활용한 접근 방식이 일반적입니다.

 

 

근데 자바의 AOP가 뭐지?

Spring Framework에서 AOP(Aspect-Oriented Programming)는 특정 기능의 모듈화를 가능하게 해주는 프로그래밍 패러다임입니다. AOP는 애플리케이션의 다른 부분에서 발생할 수 있는 공통의 문제들(예: 보안, 로깅, 트랜잭션 관리 등)을 효율적으로 처리하도록 돕습니다. 이를 통해 코드의 재사용성을 높이고, 유지 보수성을 개선할 수 있습니다.

### Spring에서 AOP의 핵심 개념

1. **Aspect**: 특정 기능의 모듈화된 구현체로, 여러 애플리케이션에서 공통적으로 사용될 수 있는 기능(예: 로깅, 보안 체크 등)을 말합니다.

2. **Join Point**: 애플리케이션 실행 중에 aspect가 적용될 수 있는 지점을 말합니다. Spring AOP에서는 메서드 실행이 주요 join point입니다.

3. **Advice**: 특정 join point에 aspect의 코드를 삽입하는 방법을 말합니다. Advice의 유형으로는 `Before`, `After`, `AfterReturning`, `AfterThrowing`, `Around` 등이 있습니다.

4. **Pointcut**: 어떤 join points(보통 메서드 실행)에 advice를 적용할지 정의하는 것입니다. 표현식을 사용해 특정 메서드나 클래스를 선택할 수 있습니다.

5. **Target Object**: Advice가 적용되는 대상 객체입니다.

6. **AOP Proxy**: Spring AOP는 런타임에 프록시를 생성하여 구현된 Aspect의 Advice를 적용합니다. 이 프록시는 대상 객체를 감싸서 호출을 가로채고, 필요에 따라 advice를 실행합니다.

### Spring AOP 예시

#### 예시 1: 메서드 실행 전 로깅
```java

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBeforeMethod(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
}


```
이 예제에서 `@Before` advice는 `com.example.service` 패키지 내의 모든 클래스의 모든 메서드 실행 전에 로그를 출력합니다.

#### 예시 2: 성능 측정
```java

@Aspect
@Component
public class PerformanceAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object returnValue = joinPoint.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature().getName() + " 실행 시간: " + duration + "ms");
        return returnValue;
    }
}


```
`@Around` advice를 사용하여 메서드의 실행 시간을 측정합니다. 메서드가 실행되기 전과 후에 코드를 실행할 수 있으며, `joinPoint.proceed()`는 실제 메서드 호출을 실행합니다.

#### 예시 3: 트랜잭션 관리
```java

@Aspect
@Component
public class TransactionAspect {
    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            // 트랜잭션 시작
            Object result = joinPoint.proceed();  // 실제 메서드 실행
            // 트랜잭션 커밋
            return result;
        } catch (Exception e) {
            // 트랜잭션 롤백
            throw e;
        }
    }
}


```
이 예제에서는 `@Transactional` 어노테이션이 붙은 메서드에 대해 트랜잭션을 관리합니다. 예외가 발생하면 롤백을 수행합니다.

이처럼 Spring AOP를 사용하면, 핵심 비즈니스 로

직에서 공통 관심사를 분리하여 코드의 명확성과 유지 보수성을 향상시킬 수 있습니다.

댓글 영역