Spring-Java/Spring

인터페이스에 의존하는 Repository

현대타운301 2024. 5. 9. 00:13

 

세 줄 요약

- domain 계층의 인터페이스를 의존하게끔 하면 실행 환경에 따른 빈을 주입받을 수 있다.

- 어플리케이션 실행 시점에 주입받을 빈을 결정하기 위해 @Profile 어노테이션을 사용한다.

- @Profile 어노테이션과 application.properties 파일을 매핑시켜 각 실행 환경에 따른 설정을 진행한다.

 


 

어플리케이션 실행 환경

 

테스트 vs 서비스

테스트 환경 : 로컬 개발 환경과 마찬가지로 DB를 사용하지 않는 Repository

서비스 환경 : 각종 서버 간 데이터 공유를 위해 DB를 사용하는 Repository

  → 인터페이스에 의존하면 이처럼 실행 환경에 따른 의존성을 주입받을 수 있습니다.

 

 

인터페이스 의존하기

인터페이스에 의존하지 않으면 application 계층(Service 클래스)에 infrastructure 계층의 빈이 직접 주입됩니다.

infrastructure 계층 방향의 의존성은 사라져야 하기 때문에 domain 계층의 인터페이스를 의존하도록 구조를 변경합니다.

 

인터페이스에 의존하면 infrastructure 방향으로의 의존성은 사라지고, 각 실행 환경에 따른 빈을 주입받을 수 있다.

 


 

Spring Profiles

 

ProductDatabaseRepository와 ProductListRepository 모두 ProductRepository 인터페이스를 구현하고 있습니다.

이러한 상황에서 어플리케이션을 실행하면 다음과 같은 에러 메세지를 볼 수 있습니다.

********************************
APPLICATION FAILED TO START
********************************

Description:

...ProductService required a single bean, but 2 were found:
  - productDatabaseRepository
  - productListRepository

 

인터페이스에 어떤 구현 객체를 주입받을 것인지 정하지 않아서 발생한 에러입니다.

이를 해결하는 방법 중 하나로 Spring Profiles의 '@Profile' 어노테이션을 사용합니다.

 

 

@Profile

특정 환경에서 특정 클래스의 빈이 생성되도록 만들어 주는 어노테이션입니다.

해당 어노테이션을 통해 실행 환경에 따른 빈이 주입될 수 있습니다.

 

ProductDatabaseRepository

@Repository
@Profile("prod")	// Production을 의미하는 'prod' 프로파일
public class ProductDatabaseProduct implements ProductRepository {...}

 

ProductListRepository

@Repository
@Profile("test")	// 로컬 개발 환경의 'test' 프로파일
public class ProductListRepository implements ProductRepository {...}

 

 

application.properties

@Profile 어노테이션은 application.properties 파일의 이름과 매핑되어 각 실행 환경에 따른 설정을 진행합니다.

실행 환경에 따른 의존성 주입을 위해 다음과 같이 설정합니다.

 

application.properties : 어떤 프로파일을 실행할지 결정

spring.profiles.active=test

 

application-test.properties : @Profile("test")에 대한 설정

# spring-boot-starter-jdbc에 의한 DB 자동 연결을 작동하지 않도록 제외시킴
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

 

application-prod.properties : @Profile("prod")에 대한 설정

# DB를 사용하므로 DB관련 설정을 진행
spring.datasource.url=jdbc:mysql://localhost:3306/product_management
spring.datasource.username=root
spring.datasource.password=userpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

 

 

ApplicationRunner

어플리케이션 실행과 동시에 커넥션 풀 생성을 위해 설정해둔 해당 코드 또한 서비스 환경에서 실행 되게끔 변경합니다.

@Bean 어노테이션과 함께 사용되어 spring.profiles.active에 해당하는 프로파일인 경우 커넥션 풀을 생성합니다.

 

Application

@Bean
@Profile("prod")
public ApplicationRunner runner(DataSource dataSource) {...}