@AuthenticationPrincipal과 @PreAuthorize는 모두 인증된 사용자에 대한 정보를 가져오거나 접근 제어를 구현하는 데 사용되지만, 목적과 사용 방식이 다릅니다.

1. @AuthenticationPrincipal

@AuthenticationPrincipal은 현재 인증된 사용자의 정보를 메서드의 파라미터로 주입할 때 사용됩니다. 이를 통해 컨트롤러 메서드 내부에서 인증된 사용자 정보를 직접 사용할 수 있습니다.

예를 들어, @AuthenticationPrincipal을 사용하여 userId를 메서드 파라미터로 전달받으면, 인증된 사용자의 ID 또는 UserDetails 객체를 사용할 수 있게 됩니다.

@DeleteMapping("/posting/{postingId}")
public ResponseEntity<Void> deletePostingById(
        @PathVariable Long postingId,
        @AuthenticationPrincipal String userId) {
    // userId를 통해 현재 사용자 정보를 확인하고 처리
    postingService.deletePostingByUserAndId(userId, postingId);
    return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

주요 특징:

  • 인증된 사용자 객체(UserDetails 또는 userId)를 직접 파라미터로 받습니다.
  • 메서드 내부에서 인증된 사용자의 정보를 활용하여 원하는 로직을 구현할 수 있습니다.
  • @AuthenticationPrincipal은 보통 인증된 사용자 정보를 쉽게 활용하기 위해 컨트롤러 메서드의 파라미터로 주입하는 데 주로 사용됩니다.

2. @PreAuthorize

@PreAuthorize는 메서드 호출 전에 권한을 검사하는 데 사용됩니다. @PreAuthorize는 SpEL(스프링 표현 언어)을 사용하여 권한 조건을 정의하며 해당 조건을 만족해야만 메서드를 실행할 수 있습니다.

예를 들어 특정 게시글의 작성자인 경우에만 삭제할 수 있도록 @PreAuthorize를 사용해 권한을 제한할 수 있습니다.

@PreAuthorize("@postingService.isOwner(authentication, #postingId)")
@DeleteMapping("/posting/{postingId}")
public ResponseEntity<Void> deletePostingById(@PathVariable Long postingId) {
    postingService.deletePostingById(postingId);
    return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

주요 특징:

  • 메서드 실행 전에 권한 조건을 평가하여 접근 제어를 수행합니다.
  • authentication 객체나 파라미터(예: #postingId)를 사용하여 권한 검사 로직을 정의할 수 있습니다.
  • 서비스 또는 리포지토리 메서드에서도 사용할 수 있으며, 메서드 자체에 대한 접근 제어를 수행합니다.

차이점 요약

기능 @AuthenticationPrincipal @PreAuthorize

주요 목적 인증된 사용자 정보 주입 메서드 호출 전 접근 권한 검사
사용 위치 컨트롤러 메서드 파라미터 컨트롤러 또는 서비스 메서드
적용 대상 인증된 사용자 정보 (UserDetails 또는 ID) 권한 검사 조건 (SpEL 사용)
권한 검사 시점 메서드 내부에서 권한 검사 로직을 추가해야 함 메서드 호출 전 권한 검사 자동 수행

 

결국 @AuthenticationPrincipal은 인증된 사용자 정보를 파라미터로 주입하여 로직에서 활용할 때 유용하고 @PreAuthorize는 특정 권한이나 조건을 만족할 때만 메서드를 호출하도록 보장할 때 적합합니다.

'Spring Framework > 에러 해결' 카테고리의 다른 글

data.sql 파일이 삽입되지 않는 문제  (1) 2024.11.29

문제 상황

Spring Boot 애플리케이션에서 H2 메모리 데이터베이스를 사용해 JPA로 테이블을 생성하고, data.sql 파일로 초기 데이터를 삽입하려 했습니다. 하지만 애플리케이션 실행 중 다음과 같은 오류가 발생했습니다.

Table "BOOK" not found (this database is empty)

 

data.sql이 실행될 때 book 테이블이 아직 생성되지 않아 데이터 삽입에 실패한 것입니다. ddl-auto: create 옵션으로 JPA가 테이블을 자동 생성하도록 설정했지만, data.sql이 실행되는 시점이 JPA 테이블 생성 이전이어서 문제가 발생했습니다.

원인 분석

Spring Boot는 기본적으로 데이터베이스 초기화를 데이터 소스 설정 직후에 실행합니다. 따라서, data.sql이 테이블 생성 이전에 실행되어 테이블이 존재하지 않는 상태에서 데이터 삽입을 시도하는 문제가 발생했습니다.

해결 방법

이 문제를 해결하기 위해 defer-datasource-initialization: true 옵션을 추가했습니다. 이 설정은 Spring Boot 2.5 이상에서 제공되며 데이터베이스 초기화가 JPA에 의해 테이블이 생성된 후에 실행되도록 지연시킵니다.

적용 방법

application.yml에 다음 설정을 추가했습니다:

spring:     
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    defer-datasource-initialization: true

이 설정으로 인해 JPA가 테이블을 먼저 생성하고, 이후에 data.sql이 실행되어 데이터가 정상적으로 삽입되었습니다.

결과

defer-datasource-initialization: true 옵션을 사용함으로써 테이블이 생성된 후 데이터가 삽입되도록 순서를 맞춰 문제를 해결할 수 있었습니다.

'Spring Framework > 에러 해결' 카테고리의 다른 글

사용자 인증 권한  (0) 2024.11.29

+ Recent posts