관리 메뉴

CASSIE'S BLOG

가이드 6강 Spring Security v.2 본문

카테고리 없음

가이드 6강 Spring Security v.2

ITSCASSIE1107 2024. 10. 15. 21:14

바로 실습

자바 코드에서 서비스단에서 Primary 어노테이션이 어떤 기능을 가져?

@Primary 어노테이션은 스프링 프레임워크에서 의존성 주입 시 어떤 빈(Bean)을 기본적으로 사용할지를 지정하는 데 사용됩니다.

스프링은 한 타입에 대해 여러 개의 빈이 정의된 경우, 어느 빈을 사용할지 모호할 수 있는데, 이때 @Primary를 사용하면 해당 빈이 기본으로 선택되도록 설정할 수 있습니다. 즉, 같은 타입의 여러 빈이 존재할 때 @Primary가 붙은 빈이 우선적으로 주입됩니다.

예를 들어, 다음과 같은 두 개의 서비스 빈이 있다고 가정할 때:

@Service
public class ServiceA implements MyService {
    // ...
}

@Service
@Primary
public class ServiceB implements MyService {
    // ...
}


여기서 MyService 타입의 빈이 주입될 때, 기본적으로 ServiceB가 주입됩니다. 왜냐하면 ServiceB에 @Primary 어노테이션이 붙어 있기 때문입니다.

@Primary는 같은 타입의 빈이 여러 개 있을 때 사용하며, 특정 빈을 명시적으로 주입하고 싶으면 @Qualifier 어노테이션을 함께 사용할 수도 있습니다.

서비스단이 여러개 있으면 Primary 어노테이션으로 정해주는거야? 어떤 걸 서비스단으로 쓰는지?

네, 맞습니다! 서비스 단(Service layer)에 여러 개의 구현체가 있을 때, 스프링에서 어느 구현체를 사용할지 결정하는 방법 중 하나가 @Primary 어노테이션입니다.

예를 들어, 동일한 인터페이스를 구현한 여러 서비스 클래스가 있을 때, 스프링이 자동으로 의존성 주입을 할 때 어떤 구현체를 사용할지 명확하지 않을 수 있습니다. 이때 @Primary 어노테이션을 사용하면 그 구현체를 기본으로 사용하도록 지정할 수 있습니다.


Repository class에 query 어노테이션 이용해서 쿼리문 쓰는게
아니라 왜 interface에 그거를 적어?

@Query 어노테이션을 Repository 인터페이스에 사용하는 이유는 JPA의 동작 방식과 관련이 있습니다. JPA에서 Repository는 일반적으로 인터페이스로 정의되며, 이 인터페이스는 JPA가 자동으로 구현을 생성해주는 역할을 합니다. 이를 통해 개발자는 복잡한 구현 로직 없이도 데이터베이스와의 상호작용을 쉽게 처리할 수 있습니다.

인터페이스에 쿼리문을 작성하는 이유는 다음과 같습니다:

1. 자동 구현 생성
JPA Repository 인터페이스는 Spring Data JPA가 내부적으로 구현체를 생성해줍니다. 즉, 인터페이스에 쿼리를 작성하면 Spring Data JPA가 런타임에 자동으로 해당 쿼리를 실행하는 코드를 생성합니다. 따라서 인터페이스에 쿼리를 넣으면 별도의 구현 클래스를 만들 필요 없이 바로 사용 가능합니다. 이는 코드 양을 줄이고, 관리하기 쉽게 만듭니다.

예를 들어, 인터페이스에서 아래와 같은 메서드를 정의하면:

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.username = ?1")
    User findByUsername(String username);
}

Spring Data JPA가 자동으로 findByUsername 메서드에 해당하는 구현체를 생성하고, 이를 실행합니다.

2. 관심사의 분리
인터페이스에 쿼리를 정의하는 것은 비즈니스 로직과 데이터베이스 접근 로직을 분리하는 데 도움을 줍니다. Repository는 오로지 데이터 접근을 담당하며, 이 역할은 Repository 인터페이스에 작성된 메서드와 쿼리로 명확하게 분리됩니다. 이를 통해 서비스 계층에서는 비즈니스 로직에만 집중할 수 있게 됩니다.

3. 유지 보수의 용이성
인터페이스에 쿼리를 넣으면 코드가 간결해지고 유지보수가 쉬워집니다. JPA Repository 인터페이스를 확장하면 기본적인 CRUD (Create, Read, Update, Delete) 작업을 모두 처리할 수 있기 때문에, 추가적인 쿼리 작성이 필요할 때는 @Query 어노테이션을 사용해 필요한 쿼리만 정의하면 됩니다. 이 방식은 별도의 구현 클래스를 만들고, 그곳에 SQL을 작성하는 것보다 훨씬 효율적입니다.

4. 추상화된 데이터 접근
Repository 인터페이스는 데이터베이스와의 직접적인 의존성을 줄이고 추상화를 제공합니다. 인터페이스에 쿼리를 작성하면 데이터베이스 접근 방식이 추상화되고, 실제 데이터베이스가 무엇인지에 상관없이 동일한 방식으로 접근할 수 있습니다. 이는 애플리케이션이 데이터베이스 변경이 필요할 때 더 유연하게 대응할 수 있게 만듭니다.

5. JPA Repository의 컨벤션
Spring Data JPA의 철학은 "관심사 분리"와 "반복 코드 최소화"입니다. 인터페이스 기반의 Repository 패턴을 사용하면 데이터 접근 계층을 깔끔하고 명확하게 정의할 수 있습니다. 이를 통해 인터페이스에 비즈니스 로직과 관련 없는 데이터 접근 로직을 선언적으로 정의하고, 서비스 계층에서는 해당 메서드들을 간결하게 호출할 수 있습니다.

결론적으로, 인터페이스에 @Query를 사용하는 것은 Spring Data JPA의 자동화된 Repository 생성 기능을 활용하기 위한 설계 패턴입니다. 이 방식은 구현 클래스를 만들지 않고도 데이터베이스와 상호작용할 수 있게 하며, 유지보수와 코드 관리를 보다 쉽게 만듭니다.


@Query("SELECT u FROM User u WHERE u.username = ?1")

여기서 u가 무슨 뜻이야? User u에서 u를 select해라? 좀 이상하지않아?

네, 처음 보면 약간 헷갈릴 수 있지만, 여기서 u는 JPQL (Java Persistence Query Language)에서 사용하는 엔티티에 대한 별칭(alias) 입니다.

자세히 설명하자면:
@Query("SELECT u FROM User u WHERE u.username = ?1")

User u에서 User는 JPA 엔티티 클래스를 의미합니다. 이 클래스는 데이터베이스의 테이블과 매핑된 객체입니다.
u는 User 엔티티의 별칭(alias) 이며, 이후 쿼리에서 이 u를 사용해 해당 엔티티의 필드에 접근합니다.
쿼리의 동작 방식:
SELECT u: User 엔티티 객체 u를 선택합니다. 즉, 데이터베이스에서 User 테이블의 한 행에 해당하는 엔티티 객체를 선택한다는 뜻입니다.
FROM User u: User 엔티티로부터 데이터를 조회하겠다는 의미이며, 여기서 u는 User 엔티티의 별칭입니다. 이제 쿼리의 나머지 부분에서 u를 통해 User 엔티티의 필드들에 접근할 수 있습니다.
WHERE u.username = ?1: u.username은 User 엔티티의 username 필드를 의미하며, ?1은 메서드 파라미터로 전달된 첫 번째 값을 의미합니다.
즉, 전체 쿼리는 "User 엔티티에서 username이 주어진 값과 일치하는 User 객체를 선택하라"는 의미입니다.

왜 별칭을 사용하는가?
별칭(alias)은 쿼리에서 코드를 간결하고 읽기 쉽게 만들기 위해 사용됩니다. 만약 여러 엔티티를 조인하거나, 엔티티의 여러 필드를 사용할 때 별칭이 있으면 필드 접근을 더 쉽게 할 수 있습니다.

예를 들어, 별칭 없이 쿼리를 작성한다면:

SELECT User FROM User WHERE User.username = ?1


UserPricipal이면 aliss up로 땀


반응형