- 데이터(Data)
- 9.1. SQL 데이터베이스(SQL Databases)
- 9.1.1. 데이터소스 구성(Configure a DataSource) 임베디드 데이터베이스 지원(Embedded Database Support) 프로덕션 데이터베이스에 연결(Connection to a Production Database) 데이터소스 구성(DataSource Configuration) 커넥션 풀 지원(Supported Connection Pools) JNDI 데이터소스 커넥션(Connection to a JNDI DataSource)
- 9.1.2. JdbcTemplate 사용(Using JdbcTemplate)
- 9.1.3. JPA와 스프링 데이터 JPA(JPA and Spring Data JPA) 엔터티 클래스(Entity Classes) 스프링 데이터 JPA 리포지터리(Spring Data JPA Repositories) 스프링 데이터 Envers 리포지터리(Spring Data Envers Repositories) JPA 데이터베이스 생성 및 삭제(Creating and Dropping JPA Databases) 뷰에서 보기에서 엔터티매니저 열기(Open EntityManager in View)
- 9.1.4. 스프링 데이터 JDBC(Spring Data JDBC)
- 9.1.5. H2의 웹 콘솔 사용하기(Using H2’s Web Console) H2 콘솔 경로 변경(Changing the H2 Console’s Path) 보안 애플리케이션에서 H2 콘솔에 접근(Accessing the H2 Console in a Secured Application)
- 9.1.6. jOOQ 사용하기(Using jOOQ) 코드 제너레이션(Code Generation) DSLContext사용하기(Using DSLContext) jOOQ SQL 다이얼렉트(jOOQ SQL Dialect) jOOQ 커스터마이징(Customizing jOOQ)
- 9.1.7. R2DBC 사용하기(Using R2DBC) 임베디드 데이터베이스 지원(Embedded Database Support) 데이터베이스클라이언트 사용하기(Using DatabaseClient) 스프링 데이터 R2DBC 리포지터리(Spring Data R2DBC Repositories)
- 9.2. NoSQL 기술을 활용한 작업(Working with NoSQL Technologies)
- 9.2.1. 레디스(Redis) Redis에 연결(Connecting to Redis)
- 9.2.2. 몽고DB(MongoDB) MongoDB 데이터베이스에 연결(Connecting to a MongoDB Database) 몽고템플릿(MongoTemplate) 스프링 데이터 MongoDB 리포지터리(Spring Data MongoDB Repositories)
- 9.2.3. 네오4j(Neo4j) 네오4j 데이터베이스 연결(Connecting to a Neo4j Database) 스프링 데이터 네오4j 리포지터리(Spring Data Neo4j Repositories)
- 9.2.4. 엘라스틱서치(Elasticsearch) REST 클라이언트를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch Using REST clients) 스프링 데이터를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch by Using Spring Data) 스프링 데이터 엘라스틱서치 리포지터리(Spring Data Elasticsearch Repositories)
- 9.2.5. 카산드라(Cassandra) 카산드라에 연결(Connecting to Cassandra) 스프링 데이터 카산드라 리포지터리(Spring Data Cassandra Repositories)
- 9.2.6. 카우치베이스(Couchbase) 카우치베이스애 연결(Connecting to Couchbase) 스프링 데이터 카우치베이스 리포지터리(Spring Data Couchbase Repositories)
- 9.2.7. LDAP LDAP 서버에 연결(Connecting to an LDAP Server) 스프링 데이터 LDAP 리포지터리(Spring Data LDAP Repositories) 임베디드 인메모리 LDAP 서버(Embedded In-memory LDAP Server)
- 9.2.8. 인플럭스DB(InfluxDB) 인플럭스DB에 연결(Connecting to InfluxDB)
- 9.3. 다음에 읽을 내용(What to Read Next) ***
- 9.1. SQL 데이터베이스(SQL Databases)
9. 데이터(Data)
스프링 부트는 SQL 및 NoSQL 등 다양한 데이터 기술과 통합할 수 있다.
9.1. SQL 데이터베이스(SQL Databases)
스프링 프레임워크는 Jdbc템플릿(JdbcTemplate)을 사용해 직접 JDBC 접근부터 하이버네이트(Hibernate)와 같은 완전한 “객체 관계형 매핑” 기술에 이르기까지 SQL 데이터베이스 작업에 대해 광범위하게 지원한다. 스프링 데이터는 인터페이스에서 직접 리포지터리를 구현하고 컨벤션을 사용하여 메서드명에서 쿼리를 생성하는 추가 기능 레벨을 제공한다.
9.1.1. 데이터소스 구성(Configure a DataSource)
자바의 javax.sql.DataSource
인터페이스는 데이터베이스 연결 작업의 표준을 제공한다. 전통적으로 데이터소스(DataSource)는 일부 자격 증명(credential)과 함께 URL을 사용하여 데이터베이스 커넥션을 설정한다.
일반적으로 데이터소스(DataSource) 구성을 완전히 제어하는 고급 예제는 “방법(How-to)” 장을 참고하자.
임베디드 데이터베이스 지원(Embedded Database Support)
인메모리 임베디드 데이터베이스를 사용하여 애플리케이션을 개발하는 것이 편리한 경우가 많다. 분명히 인메모리 데이터베이스는 영구 저장소를 제공하지 않는다. 애플리케이션이 시작될 때 데이터베이스를 채워야 하고 애플리케이션이 종료되면 데이터를 버릴 준비를 해야 한다.
“방법(How-to)” 섹션에는 데이터베이스를 초기화하는 방법에 대한 장이 포함되어 있다.
스프링 부트는 임베디드 H2, HSQL 및 Derby 데이터베이스를 자동 구성(auto-configure)할 수 있다. 연결 URL을 제공할 필요가 없다. 사용하려는 임베디드 데이터베이스에 대한 빌드 의존성만 포함하면 된다. 클래스패스에 여러 개의 임베디드 데이터베이스가 있는 경우 spring.datasource.embedded-database-connection
구성 프로퍼티을 설정하여 어느 것이 사용되는지 제어하자. 프로퍼티를 none으로 설정하면 임베디드 데이터베이스의 자동 구성이 비활성화된다.
테스트에서 이 기능을 사용하는 경우, 사용하는 애플리케이션 컨텍스트 수에 관계없이 전체 테스트 스위트에서 동일한 데이터베이스가 재사용된다는 것을 알 수 있다. 각 컨텍스트에 별도의 임베디드 데이터베이스가 있는지 확인하려면 spring.datasource.generate-unique-name
을 true로 설정해야 한다.
예를 들어 일반적인 POM 의존성은 다음과 같다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
임베디드 데이터베이스를 자동 구성하려면, spring-jdbc
에 대한 의존성이 필요하다. 이 예제에서는 spring-boot-starter-data-jpa
를 통해 전이적으로 끌어온다.
어떤 이유로든 임베디드 데이터베이스에 대한 연결 URL을 구성하는 경우 데이터베이스의 자동 종료가 비활성화되어 있는지 확인하자. H2를 사용하는 경우 DB_CLOSE_ON_EXIT=FALSE
를 사용해야 한다. HSQLDB를 사용하는 경우 shutdown=true
가 사용되지 않는지 확인해야 한다. 스프링 부트가 데이터베이스가 닫힐 때 제어할 수 있는 데이터베이스 자동 종료를 비활성화하면, 데이터베이스에 대한 접근이 더 이상 필요하지 않을 때 발생할 수 있도록 보장한다.
프로덕션 데이터베이스에 연결(Connection to a Production Database)
풀링 데이터소스(DataSource)를 사용하여 프로덕션 데이터베이스 커넥션을 자동으로 구성할 수도 있다.
데이터소스 구성(DataSource Configuration)
데이터소스(DataSource)
구성은 spring.datasource.*
의 외부 구성 프로퍼티스에 의해 제어된다. 예를 들어 application.properties
에서 다음 내용을 선언할 수 있다.
프로퍼티스(Properties)
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
Yaml
spring:
datasource:
url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
최소 spring.datasource.url
프로퍼티에 URL을 지정해야 한다. 그렇지 않으면 스프링 부트는 임베디드 데이터베이스를 자동 구성하려고 시도한다.
스프링 부트는 URL에서 대부분 데이터베이스에 대한 JDBC 드라이버 클래스를 추론할 수 있다. 특정 클래스를 지정해야 하는 경우 spring.datasource.driver-class-name
프로퍼티를 사용할 수 있다.
풀링 데이터소스(DataSource)를 생성하려면 유효한 드라이버(Driver) 클래스가 사용 가능한지 확인할 수 있어야 하므로 작업을 수행하기 전에 이를 확인해야 한다. 즉, spring.datasource.driver-class-name=com.mysql.jdbc.Driver
를 설정한 경우 해당 클래스를 로드할 수 있어야 한다.
지원되는 옵션에 대한 자세한 내용은 데이터소스프로퍼티스(DataSourceProperties)를 참조하자. 이는 실제 구현과 관계없이 작동하는 표준 옵션이다. 각각의 접두사(spring.datasource.hikari., spring.datasource.tomcat., spring.datasource.dbcp2.* 및 spring.datasource.oracleucp.*)를 사용하여 구현별 설정을 미세 조정하는 것도 가능하다. 자세한 내용은 사용 중인 커넥션 풀 구현 설명서를 참고하자.
예를 들어, 톰캣 커넥션 풀을 사용하는 경우 다음 예와 같이 다양한 추가 설정을 커스텀할 수 있다.
프로퍼티스(Properties)
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true
Yaml
spring:
datasource:
tomcat:
max-wait: 10000
max-active: 50
test-on-borrow: true
이렇게 하면 사용 가능한 커넥션이 없는 경우 예외가 발생하기 전에 10000ms를 기다리도록 풀이 설정되고, 최대 커넥션 수를 50으로 제한하고 풀에서 커넥션을 빌리기 전에 연결의 유효성을 검사한다.
커넥션 풀 지원(Supported Connection Pools)
스프링 부트는 특정 구현을 선택하기 위해 다음 알고리즘을 사용한다.
- 우리는 성능과 동시성(concurrency) 때문에 히카리CP(HikariCP)를 선호한다. 히카리CP(HikariCP)를 사용할 수 있으면 항상 이를 선택한다.
- 그렇지 않고, 톰캣 풀링 데이터소스(DataSource)를 사용할 수 있으면 이를 사용한다.
- 그렇지 않고 Commons DBCP2를 사용할 수 있으면 이를 사용한다.
- 히카리CP(HikariCP), 톰캣, DBCP2 중 어느 것도 사용할 수 없고 오라클 UCP를 사용할 수 있으면 이를 사용한다.
spring-boot-starter-jdbc
또는 spring-boot-starter-data-jpa
“스타터”를 사용하는 경우 자동으로 히카리CP에 대한 의존성을 얻는다.
spring.datasource.type
프로퍼티을 설정하면 해당 알고리즘을 완전히 우회하고 사용할 커넥션 풀을 지정할 수 있다. Tomcat-jdbc가 기본적으로 제공되므로 이는 톰캣 컨테이너에서 애플리케이션을 실행하는 경우 특히 중요하다.
추가 커넥션 풀은 항상 데이터소스빌더(DataSourceBuilder)를 사용하여 수동으로 구성할 수 있다. 자체 데이터소스(DataSource) 빈을 정의하면 자동 구성이 발생하지 않는다. 데이터소스빌더(DataSourceBuilder)는 다음 커넥션 풀을 지원한다.
- 히카리CP(HikariCP)
- 톰캣 풀링 데이터소스(Tomcat pooling Datasource)
- Commons DBCP2
- Oracle UCP & OracleDataSource
- 스프링 프레임워크의 심플드라이버데이터소스(SimpleDriverDataSource)
- H2 JdbcDataSource
- PostgreSQL PGSimpleDataSource
- C3P0
JNDI 데이터소스 커넥션(Connection to a JNDI DataSource)
스프링 부트 애플리케이션을 애플리케이션 서버에 배포하는 경우, 서버의 기능을 사용하여 데이서소스(DataSource)를 구성 및 관리하고 JNDI를 사용하여 접근할 수 있다.
spring.datasource.jndi-name
프로퍼티는 spring.datasource.url
, spring.datasource.username
및 spring.datasource.password
프로퍼티스의 대안으로 사용되어 특정 JNDI 위치에서 데이터소스(DataSource)에 접근할 수 있다. 예를 들어, application.properties
의 다음 내용에서는 JBoss AS 정의 데이터소스(DataSource)에 접근하는 방법을 보여준다.
프로퍼티스(Properties)
spring.datasource.jndi-name=java:jboss/datasources/customers
Yaml
spring:
datasource:
jndi-name: "java:jboss/datasources/customers"
9.1.2. JdbcTemplate 사용(Using JdbcTemplate)
스프링의 JdbcTemplate 및 NamedParameterJdbcTemplate 클래스는 자동으로 구성되며 다음 예제와 같이 @Autowire를 자신의 빈에 직접 연결할 수 있다.
자바
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void doSomething() {
this.jdbcTemplate ...
}
}
코틀린
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val jdbcTemplate: JdbcTemplate) {
fun doSomething() {
jdbcTemplate.execute("delete from customer")
}
}
다음 예제와 같이 spring.jdbc.template.*
프로퍼티스를 사용하여 템플릿의 일부 프로퍼티스를 커스텀할 수 있다.
프로퍼티스(Properties)
spring.jdbc.template.max-rows=500
Yaml
spring:
jdbc:
template:
max-rows: 500
NamedParameterJdbcTemplate은 뒤에서 동일한 JdbcTemplate 인스턴스를 재사용한다. 둘 이상의 JdbcTemplate이 정의되고 기본 후보가 없으면 NamedParameterJdbcTemplate이 자동 구성되지 않는다.
9.1.3. JPA와 스프링 데이터 JPA(JPA and Spring Data JPA)
자바 퍼시스턴스(Persistence) API는 객체를 관계형 데이터베이스에 “매핑”할 수 있는 표준 기술이다. spring-boot-starter-data-jpa
POM은 시작하는 빠른 방법을 제공한다. 다음과 같은 주요 의존성을 제공한다.
- 하이버네이트(Hibernate): 가장 인기 있는 JPA 구현 중 하나다.
- 스프링 데이터 JPA: JPA 기반 리포지터리를 구현하는 데 도움이 된다.
- 스프링 ORM: 스프링 프레임워크의 ORM 코어 지원이다.
여기서는 JPA 또는 스프링 데이터에 대해 너무 많은 세부 사항을 다루지 않는다. spring.io
의 “Accessing Data with JPA” 가이드와 스프링 데이터 JPA와 하이버네이트 레퍼런스 문서를 읽어보자.
엔터티 클래스(Entity Classes)
전통적으로 JPA “Entity” 클래스는 persistence.xml 파일에 지정된다. 스프링 부트에서는 이 파일이 필요하지 않으며 대신 “Entity Scanning”이 사용된다. 기본적으로 기본 구성 클래스(@EnableAutoConfiguration 또는 @SpringBootApplication으로 어노테이션이 달린 패키지) 아래의 모든 패키지가 검색된다.
@Entity
, @Embeddable
또는 @MappedSuperclass
로 어노테이션이 달린 모든 클래스가 고려된다. 일반적인 엔터티 클래스는 다음 예와 유사하다.
자바
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
// ... 추가 멤버에는 종종 @OneToMany 매핑이 포함된다.
protected City() {
// JPA 사양에 필요한 인수 없는(no-args) 생성자
// 직접 사용되어서는 안 되기 때문에 protected로 선언한다.
}
public City(String name, String state) {
this.name = name;
this.state = state;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
// ... 기타 등등.
}
코틀린
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.Id
import java.io.Serializable
@Entity
class City : Serializable {
@Id
@GeneratedValue
private val id: Long? = null
@Column(nullable = false)
var name: String? = null
private set
// ... etc
@Column(nullable = false)
var state: String? = null
private set
// ... 추가 멤버에는 종종 @OneToMany 매핑이 포함된다.
protected constructor() {
// JPA 사양에 필요한 인수 없는(no-args) 생성자
// 직접 사용되어서는 안 되기 때문에 protected로 선언한다.
}
constructor(name: String?, state: String?) {
this.name = name
this.state = state
}
}
@EntityScan
어노테이션을 사용하여 엔터티 스캐닝 위치를 커스텀할 수 있다. “스프링 구성에서 @Entity 정의 분리(Separate @Entity Definitions from Spring Configuration)” 방법을 참고하자.
스프링 데이터 JPA 리포지터리(Spring Data JPA Repositories)
스프링 데이터 JPA 리포지터리는 데이터에 접근하기 위해 정의할 수 있는 인터페이스다. JPA 쿼리는 메소드명에서 자동으로 생성된다. 예를 들어 CityRepository 인터페이스는 주어진 주의 모든 도시를 찾기 위해 findAllByState(String state) 메소드를 선언할 수 있다.
더 복잡한 쿼리의 경우 스프링 데이터의 쿼리(Query) 어노테이션을 사용하여 메서드에 어노테이션을 달 수 있다.
스프링 데이터 리포지터리는 일반적으로 리포지터리(Repository) 또는 CrudRepository 인터페이스를 상속한다. 자동 구성을 사용하는 경우 기본 구성 클래스(@EnableAutoConfiguration 또는 @SpringBootApplication 어노테이션이 달린 클래스)가 포함된 패키지에서 리포지터리가 검색된다.
다음 예는 일반적인 스프링 데이터 리포지터리 인터페이스 정의를 보여준다.
자바
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
코틀린
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
interface CityRepository : Repository<City?, Long?> {
fun findAll(pageable: Pageable?): Page<City?>?
fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?
}
스프링 데이터 JPA 리포지터리는 default, deferred 및 lazy의 세 가지 부트스트래핑(bootstrapping) 모드를 지원한다. deferred 또는 lazy 부트스트래핑을 활성화하려면, spring.data.jpa.repositories.bootstrap-mode
프로퍼티를 각각 deferred 또는 lazy로 설정하자. deferred 혹은 lazy 부트스트래핑을 사용할 때 자동 구성된 엔터티매니저팩토리빌더(EntityManagerFactoryBuilder)는 컨텍스트의 에이싱크태스크익스큐터(AsyncTaskExecutor)(있는 경우)를 부트스트랩 익스큐터로 사용한다. 둘 이상이 존재하는 경우 applicationTaskExecutor
라는 이름이 사용된다.
deferred 또는 lazy 부트스트랩을 사용하는 경우, 애플리케이션 컨텍스트 부트스트랩 단계 후 JPA 인프라에 대한 접근을 연기(defer) 해야 한다. 스마트이니셜라이징싱글톤(SmartInitializingSingleton)을 사용하여 JPA 인프라가 필요한 모든 초기화를 호출할 수 있다. 스프링 빈으로 생성된 JPA 컴포넌트(예: 컨버터)의 경우 오브젝트프로바이더(ObjectProvider)를 사용하여 의존성을 지연(delay)시킨다.
우리는 스프링 데이터 JPA의 표면만 살펴보았다. 자세한 내용은 스프링 데이터 JPA 레퍼런스 문서를 참고하자.
스프링 데이터 Envers 리포지터리(Spring Data Envers Repositories)
스프링 데이터 Envers를 사용할 수 있는 경우 JPA 리포지터리는 일반적인 Envers 쿼리를 지원하도록 자동 구성된다.
스프링 데이터 Envers를 사용하려면 다음 예제와 같이 리포지터리가 리비전리포지터리(RevisionRepository)에서 상속됐는지 확인하자.
자바
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;
public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {
Page<Country> findAll(Pageable pageable);
}
코틀린
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
import org.springframework.data.repository.history.RevisionRepository
interface CountryRepository : RevisionRepository<Country?, Long?, Int>, Repository<Country?, Long?> {
fun findAll(pageable: Pageable?): Page<Country?>?
}
자세한 내용은 스프링 데이터 Envers 레퍼런스 문서를 참고하자.
JPA 데이터베이스 생성 및 삭제(Creating and Dropping JPA Databases)
기본적으로 JPA 데이터베이스는 임베디드 데이터베이스(H2, HSQL 또는 Derby)를 사용하는 경우에만 자동으로 생성된다. spring.jpa.*
프로퍼티스를 사용하여 JPA 설정을 명시적으로 구성할 수 있다. 예를 들어, 테이블을 생성하고 삭제하려면 application.properties
에 다음 줄을 추가할 수 있다.
프로퍼티스(Properties)
spring.jpa.hibernate.ddl-auto=create-drop
Yaml
spring:
jpa:
hibernate.ddl-auto: "create-drop"
이에 대한 하이버네이트 자체의 내부 프로퍼티명은 hibernate.hbm2ddl.auto
이다. spring.jpa.properties.*
를 사용하여 다른 하이버네이트 기본 프로퍼티와 함께 설정할 수 있다(접두사는 엔터티 매니저(entity manager)에 추가하기 전에 제거된다). 다음 줄은 하이버네이트에 대한 JPA 프로퍼티스을 설정하는 예를 보여준다.
프로퍼티스(Properties)
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
Yaml
spring:
jpa:
properties:
hibernate:
"globally_quoted_identifiers": "true"
위 예제는 hibernate.globally_quoted_identifiers
프로퍼티에 대한 true
값을 하이버네이트 엔터티 매니저에 전달한다.
기본적으로, DDL 익스큐션(또는 유효성 검사(validation))은 애플리케이션컨텍스트(ApplicationContext)가 시작될 때까지 연기된다. spring.jpa.generate-ddl
플래그도 있지만 하이버네이트 자동 구성이 활성화된 경우에는 사용되지 않는다. ddl-auto
설정이 더 세밀하기 때문이다.
뷰에서 엔터티매니저 열기(Open EntityManager in View)
웹 애플리케이션을 실행하는 경우 스프링 부트는 기본적으로 오픈엔터티매니저인뷰인터셉터(OpenEntityManagerInViewInterceptor)
를 등록하여 “뷰에서 엔터디매니저 열기(Open EntityManager in View)” 패턴을 적용하여 웹 뷰에서 지연 로딩(lazy loading)을 허용한다. 이 동작을 원하지 않으면 application.properties
에서 spring.jpa.open-in-view
를 false
로 설정해야 한다.
9.1.4. 스프링 데이터 JDBC(Spring Data JDBC)
스프링 데이터에는 JDBC에 리포지터리 지원이 포함되어 있으며 CrudRepository의 메서드에 대한 SQL을 자동으로 생성한다. 고급 쿼리의 경우 @Query 어노테이션이 제공된다. 스프링 부트는 필요한 의존성이 클래스패스에 있을 때 스프링 데이터의 JDBC 리포지터리를 자동으로 구성한다. spring-boot-starter-data-jdbc
단일 의존성을 프로젝트에 추가할 수 있다. 필요한 경우 @EnableJdbcRepositories 어노테이션 또는 앱스트랙트Jdbc컨피규레이션(AbstractJdbcConfiguration) 하위 클래스를 애플리케이션에 추가하여 스프링 데이터 JDBC 구성을 제어할 수 있다.
스프링 데이터 JDBC에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
9.1.5. H2의 웹 콘솔 사용하기(Using H2’s Web Console)
H2 데이터베이스는 스프링 부트가 자동으로 구성할 수 있는 브라우저 기반 콘솔을 제공한다. 다음 조건이 충족되면 콘솔이 자동으로 구성된다.
- 서블릿 기반 웹 애플리케이션을 개발 중이다.
com.h2database:h2
가 클래스패스에 있다.- 스프링 부트의 개발자 도구를 사용하고 있다.
스프링 부트 개발자 도구를 사용하지 않지만 여전히 H2 콘솔을 사용하고 싶다면 spring.h2.console.enabled
프로퍼티를 true
값으로 구성할 수 있다.
H2 콘솔은 개발 중에만 사용하기 위한 것이므로 프로덕션에서는 spring.h2.console.enabled
가 true
로 설정되지 않도록 주의해야 한다.
H2 콘솔 패스 변경(Changing the H2 Console’s Path)
기본적으로 콘솔은 /h2-console
로 사용할 수 있다. spring.h2.console.path
프로퍼티를 사용하여 콘솔 패스를 커스텀할 수 있다.
보안 애플리케이션에서 H2 콘솔에 접근(Accessing the H2 Console in a Secured Application)
H2 콘솔은 프레임을 사용하며, 개발 전용이므로 CSRF 보호 조치를 구현하지 않는다. 애플리케이션이 스프링 시큐리티를 사용하는 경우 이를 다음과 같이 구성해야 한다.
- 콘솔 요청에 대해 CSRF 보호를 비활성화한다.
- 콘솔의 응답에서
X-Frame-Options
헤더를SAMEORIGIN
으로 설정한다. CSRF 및 X-Frame-Options 헤더에 대한 자세한 내용은 스프링 시큐리티 레퍼런스 가이드에서 확인할 수 있다.
간단한 설정에서는, 다음과 같은 시큐리티필터체인(SecurityFilterChain)을 사용할 수 있다.
자바
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Profile("dev")
@Configuration(proxyBeanMethods = false)
public class DevProfileSecurityConfiguration {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher(PathRequest.toH2Console());
http.authorizeHttpRequests(yourCustomAuthorization());
http.csrf((csrf) -> csrf.disable());
http.headers((headers) -> headers.frameOptions((frame) -> frame.sameOrigin()));
return http.build();
}
}
코틀린
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain
@Profile("dev")
@Configuration(proxyBeanMethods = false)
class DevProfileSecurityConfiguration {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
fun h2ConsoleSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http.authorizeHttpRequests(yourCustomAuthorization())
.csrf { csrf -> csrf.disable() }
.headers { headers -> headers.frameOptions { frameOptions -> frameOptions.sameOrigin() } }
.build()
}
}
H2 콘솔은 개발 중에만 사용하도록 고안됐다. 프로덕션 환경에서 CSRF 보호를 비활성화하거나 웹 사이트에 프레임을 허용하면 심각한 보안 위험이 발생할 수 있다.
PathRequest.toH2Console()
은 콘솔패스가 커스텀된 경우에도 올바른 요청 일치자(request matcher)를 반환한다.
9.1.6. jOOQ 사용하기(Using jOOQ)
jOOQ(Object Oriented Querying)는 데이터베이스에서 자바 코드를 생성하고 플루언트 API를 통해 타입이 안전한 SQL 쿼리를 작성할 수 있게 해주는 데이터 긱커리(Data Geekery)의 인기 제품이다. 상용 버전과 오픈 소스 버전 모두 스프링 부트와 함께 사용할 수 있다.
코드 제너레이션(Code Generation)
jOOQ 타입 세이프 쿼리를 사용하려면, 데이터베이스 스키마에서 자바 클래스를 생성해야 한다. jOOQ 사용자 메뉴얼을 따를 수 있다. jooq-codegen-maven
플러그인을 사용하고 spring-boot-starter-parent
“상위 POM”도 사용하는 경우 플러그인의
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
...
</executions>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/yourdatabase</url>
</jdbc>
<generator>
...
</generator>
</configuration>
</plugin>
DSLContext사용하기(Using DSLContext)
jOOQ에서 제공하는 플루언트(Fluent) API는 org.jooq.DSLContext
인터페이스를 통해 시작된다. 스프링 부트는 DSLContext를 스프링 빈으로 자동 구성하고 이를 애플리케이션 데이터소스(DataSource)에 연결한다. DSLContext를 사용하려면 다음 예제와 같이 DSLContext를 주입할 수 있다.
자바
import java.util.GregorianCalendar;
import java.util.List;
import org.jooq.DSLContext;
import org.springframework.stereotype.Component;
import static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;
@Component
public class MyBean {
private final DSLContext create;
public MyBean(DSLContext dslContext) {
this.create = dslContext;
}
}
코틀린
import org.jooq.DSLContext
import org.springframework.stereotype.Component
import java.util.GregorianCalendar
@Component
class MyBean(private val create: DSLContext) { }
jOOQ 매뉴얼은 DSLContext를 보유하기 위해 create
변수를 사용하는 경향이 있다.
다음 예와 같이 DSLContext를 사용하여 쿼리를 구성할 수 있다.
자바
public List<GregorianCalendar> authorsBornAfter1980() {
return this.create.selectFrom(AUTHOR)
.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
.fetch(AUTHOR.DATE_OF_BIRTH);
코틀린
fun authorsBornAfter1980(): List<GregorianCalendar> {
return create.selectFrom<Tables.TAuthorRecord>(Tables.AUTHOR)
.where(Tables.AUTHOR?.DATE_OF_BIRTH?.greaterThan(GregorianCalendar(1980, 0, 1)))
.fetch(Tables.AUTHOR?.DATE_OF_BIRTH)
}
jOOQ SQL 다이얼렉트(jOOQ SQL Dialect)
spring.jooq.sql-dialect
프로퍼티스가 구성되지 않은 경우 스프링 부트는 데이터 소스에 사용할 SQL 언어를 결정한다. 스프링 부트가 다이얼렉트(Dialect)을 감지할 수 없으면 DEFAULT를 사용한다.
스프링 부트는 오픈 소스 버전의 jOOQ에서 지원하는 다이얼렉트만 자동 구성할 수 있다.
jOOQ 커스터마이징(Customizing jOOQ)
org.jooq.Configuration
@Bean
을 생성하기 전에 호출될 자체 디폴트컨피규레이션커스터마이저(DefaultConfigurationCustomizer)
빈을 정의하여 보다 고급 커스텀을 수행할 수 있다. 이는 자동 구성에 의해 적용되는 모든 항목보다 우선한다.
jOOQ 구성을 완전히 제어하려면 자신만의 org.jooq.Configuration @Bean을 생성할 수도 있다.
9.1.7. R2DBC 사용하기(Using R2DBC)
R2DBC(Reactive Relational Database Connectivity) 프로젝트는 관계형 데이터베이스에 리액티브 프로그래밍 API를 제공한다. R2DBC의 io.r2dbc.spi.Connection
은 논블럭킹 데이터베이스 커넥션 작업을 위한 표준 방법을 제공한다. 커넥션은 jdbc의 데이터소스(DataSource)
와 유사한 커넥션팩토리(ConnectionFactory)
를 사용하여 제공된다.
커넥션팩토리(ConnectionFactory)
구성은 spring.r2dbc.*
의 외부 구성 프로퍼티스에 의해 제어된다. 예를 들어 application.properties
에 다음 내용을 선언할 수 있다.
프로퍼티스(Properties)
spring.r2dbc.url=r2dbc:postgresql://localhost/test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
Yaml
spring:
r2dbc:
url: "r2dbc:postgresql://localhost/test"
username: "dbuser"
password: "dbpass"
스프링 부트는 R2DBC의 커넥션 팩토리 디스커버리에서 드라이버를 가져오므로, 드라이버 클래스명을 지정할 필요가 없다.
최소한 URL은 제공되어야 한다. URL에 지정된 정보는 이름, 사용자 이름, 비밀번호 및 풀링 옵션과 같은 개별 프로퍼티스보다 우선한다.
“방법(How-to)” 장에는 데이터베이스를 초기화하는 방법에 대한 섹션이 포함되어 있다.
커넥션팩토리(ConnectionFactory)
에 의해 생성된 커넥션을 커스텀하려면, 즉 중앙 데이터베이스 구성에서 구성하기를 원하지 않거나 구성할 수 없는 특정 파라미터를 설정하려면 커넥션팩토리옵션즈빌더커스터마이저(ConnectionFactoryOptionsBuilderCustomizer)
@Bean을 사용할 수 있다. 다음 예제에서는 애플리케이션 구성에서 나머지 옵션을 가져오는 동안 데이터베이스 포트를 수동으로 오버라이드하는 방법을 보여준다.
자바
import io.r2dbc.spi.ConnectionFactoryOptions;
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
}
}
코틀린
import io.r2dbc.spi.ConnectionFactoryOptions
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class MyR2dbcConfiguration {
@Bean
fun connectionFactoryPortCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
return ConnectionFactoryOptionsBuilderCustomizer { builder ->
builder.option(ConnectionFactoryOptions.PORT, 5432)
}
}
}
다음 예에서는 일부 포스트그레(Postgre)SQL 연결 옵션을 설정하는 방법을 보여준다.
자바
import java.util.HashMap;
import java.util.Map;
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyPostgresR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
Map<String, String> options = new HashMap<>();
options.put("lock_timeout", "30s");
options.put("statement_timeout", "60s");
return (builder) -> builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);
}
}
코틀린
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class MyPostgresR2dbcConfiguration {
@Bean
fun postgresCustomizer(): ConnectionFactoryOptionsBuilderCustomizer {
val options: MutableMap<String, String> = HashMap()
options["lock_timeout"] = "30s"
options["statement_timeout"] = "60s"
return ConnectionFactoryOptionsBuilderCustomizer { builder ->
builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options)
}
}
}
커넥션팩토리(ConnectionFactory)
빈을 사용할 수 있으면 일반 JDBC 데이터소스(DataSource) 자동 구성이 백오프(back off)된다. JDBC 데이터소스(DataSource) 자동 구성을 유지하고 리액티브 애플리케이션에서 블락킹 JDBC API를 사용할 위험이 있는 경우 애플리케이션의 @Configuration 클래스에 @Import(DataSourceAutoConfiguration.class)를 추가하여 다시 활성화하자.
임베디드 데이터베이스 지원(Embedded Database Support)
JDBC 지원과 마찬가지로 스프링 부트는 리액티브 사용을 위해 임베디드 데이터베이스를 자동으로 구성할 수 있다. 연결 URL을 제공할 필요가 없다. 다음 예제와 같이 사용하려는 임베디드 데이터베이스에 대한 빌드 의존성만 포함하면 된다.
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
<scope>runtime</scope>
</dependency>
테스트에서 이 기능을 사용하는 경우, 사용하는 애플리케이션 컨텍스트 수에 관계없이 전체 테스트 스위트에서 동일한 데이터베이스가 재사용된다는 것을 알 수 있다. 각 컨텍스트에 별도의 임베디드 데이터베이스가 있는지 확인하려면 spring.r2dbc.generate-unique-name
을 true
로 설정해야 한다.
데이터베이스클라이언트 사용하기(Using DatabaseClient)
데이터베이스클라이언트(DatabaseClient) 빈은 자동으로 구성되며 다음 예제와 같이 이를 자신의 빈에 직접 @Autowire할 수 있다.
자바
import java.util.Map;
import reactor.core.publisher.Flux;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final DatabaseClient databaseClient;
public MyBean(DatabaseClient databaseClient) {
this.databaseClient = databaseClient;
}
public Flux<Map<String, Object>> someMethod() {
return this.databaseClient.sql("select * from user").fetch().all();
}
}
코틀린
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.stereotype.Component
import reactor.core.publisher.Flux
@Component
class MyBean(private val databaseClient: DatabaseClient) {
fun someMethod(): Flux<Map<String, Any>> {
return databaseClient.sql("select * from user").fetch().all()
}
}
스프링 데이터 R2DBC 리포지터리(Spring Data R2DBC Repositories)
스프링 데이터 R2DBC 리포지터리는 데이터에 접근하기 위해 정의할 수 있는 인터페이스다. 쿼리는 메서드명에서 자동으로 생성된다. 예를 들어 CityRepository 인터페이스는 주어진 주의 모든 도시를 찾기 위해 findAllByState(String state) 메소드를 선언할 수 있다.
더 복잡한 쿼리의 경우 스프링 데이터의 쿼리 어노테이션을 사용하여 메서드에 어노테이션을 달 수 있다.
스프링 데이터 리포지터리는 일반적으로 리포지터리(Repository) 또는 Crud리포지터리(CrudRepository) 인터페이스에서 상속된다. 자동 구성을 사용하는 경우 기본 구성 클래스(@EnableAutoConfiguration 또는 @SpringBootApplication 어노테이션이 달린 클래스)가 포함된 패키지에서 리포지터리가 검색된다.
다음 예는 일반적인 스프링 데이터 리포지터리 인터페이스 정의를 보여준다.
자바
import reactor.core.publisher.Mono;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);
}
코틀린
import org.springframework.data.repository.Repository
import reactor.core.publisher.Mono
interface CityRepository : Repository<City?, Long?> {
fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): Mono<City?>?
}
우리는 스프링 데이터 R2DBC의 표면만 거의 살펴보았다. 자세한 내용은 스프링 데이터 R2DBC 레퍼런스 문서를 참고하자.
9.2. NoSQL 기술을 활용한 작업(Working with NoSQL Technologies)
스프링 데이터는 다음을 포함하여 다양한 NoSQL 기술에 접근하는 데 도움이 되는 추가 프로젝트를 제공한다.
- 몽고DB(MongoDB)
- 네오4j(Neo4J)
- 엘라스틱서치(Elasticsearch)
- 레디스(Redis)
- 젬파이어 또는 지오드(GemFire or Geode)
- 카산드라(Cassandra)
- 카우치베이스(Couchbase)
- LDAP
스프링 부트는 레디스, 몽고DB, 네오4j, 엘라스틱서치, 카산드라, 카우치베이스, LDAP 및 인플럭스DB(InfluxDB)에 대한 자동 구성을 제공한다. 또한 아파치 지오드(Geode)용 스프링 부트는 아파치 지오드에 대한 자동 구성을 제공한다. 다른 프로젝트를 활용할 수 있지만 직접 구성해야 한다. spring.io/projects/spring-data
에서 해당 레퍼런스 문서를 확인하자.
9.2.1. 레디스(Redis)
레디스는 캐시, 메시지 브로커 및 다양한 기능을 갖춘 키-값 저장소다. 스프링 부트는 레티스(Lettuce) 및 제디스(Jedis) 클라이언트 라이브러리에 대한 기본 자동 구성과 스프링 데이터 레디스에서 제공하는 추상화를 제공한다.
편리한 방법으로 의존성을 수집하기 위해 spring-boot-starter-data-redis
“스타터(Starter)”가 있다. 기본적으로 레티스(Lettuce)를 사용한다. 해당 스타터는 기존 애플리케이션과 리액티브 애플리케이션을 모두 처리한다.
다른 저장소와의 일관성을 위해 리액티브 지원하는 spring-boot-starter-data-redis-reactive
“스타터”를 제공한다.
레디스에 연결(Connecting to Redis)
다른 스프링 빈과 마찬가지로 자동 구성된 레디스커넥션팩토리(RedisConnectionFactory), 스트링레디스템플릿(StringRedisTemplate) 또는 바닐라 레디스템플릿(RedisTemplate) 인스턴스를 삽입할 수 있다. 다음 예제는 이러한 빈의 예를 보여준다.
자바
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final StringRedisTemplate template;
public MyBean(StringRedisTemplate template) {
this.template = template;
}
public Boolean someMethod() {
return this.template.hasKey("spring");
}
}
코틀린
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val template: StringRedisTemplate) {
fun someMethod(): Boolean {
return template.hasKey("spring")
}
}
기본적으로 인스턴스는 localhost:6379에서 레디스 서버에 연결한다. 다음 예제와 같이 spring.data.redis.*
프로퍼티스를 사용하여 커스텀 커넥션 세부 정보를 지정할 수 있다.
프로퍼티스(Properties)
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.username=user
spring.data.redis.password=secret
Yaml
spring:
data:
redis:
host: "localhost"
port: 6379
database: 0
username: "user"
password: "secret"
또한 고급 커스텀을 위해 레티스클라이언트컨피규레이션빌드커스터마이저(LettuceClientConfigurationBuilderCustomizer)를 구현하는 임의수의 빈을 등록할 수도 있다. 클라이언트리소스빌더커스터마이저(ClientResourcesBuilderCustomizer)를 사용하여 클라이언트리소스(ClientResources)를 커스텀할 수도 있다. 제디스(Jedis)를 사용하는 경우 제디스클라이언트컨피규레이션빌더커스터마이저(JedisClientConfigurationBuilderCustomizer)도 사용할 수 있다. 또는 레디스스탠다드어론컨피규레이션(RedisStandaloneConfiguration), 레디스센티널컨피규레이션(RedisSentinelConfiguration) 또는 레디스클러스터컨피규레이션(RedisClusterConfiguration) 타입의 빈을 등록하여 구성을 완전히 제어할 수 있다.
자동 구성된 타입 중 자신만의 @Bean을 추가하면 기본값이 대체된다(빈 이름 redisTemplate
을 기반으로 하는 레디스템플릿(RedisTemplate)의 경우 제외).
기본적으로 commons-pool2가 클래스패스에 있으면 풀링된 커넥션 팩토리가 자동으로 구성된다.
자동 구성된 레디스커넥션팩토리(RedisConnectionFactory)는 다음 예제와 같이 프로퍼티스을 설정하여 서버와의 통신에 SSL을 사용하도록 구성할 수 있다.
프로퍼티스(Properties)
spring.data.redis.ssl.enabled=true
Yaml
spring:
data:
redis:
ssl:
enabled: true
이 예에 표시된 대로 커스텀 SSL 신뢰 자료를 SSL 번들에서 구성하고 레디스커넥션팩토리(RedisConnectionFactory)에 적용할 수 있다.
프로퍼티스(Properties)
spring.data.redis.ssl.bundle=example
Yaml
spring:
data:
redis:
ssl:
bundle: "example"
9.2.2. 몽고DB(MongoDB)
몽고DB는 기존 테이블 기반 관계형 데이터 대신 JSON과 유사한 스키마를 사용하는 오픈 소스 NoSQL 문서 데이터베이스다. 스프링 부트는 spring-boot-starter-data-mongodb
및 spring-boot-starter-data-mongodb
리액티브 “스타터”를 포함하여 몽고DB 작업에 대한 여러 가지 편의사항을 제공한다.
몽고DB 데이터베이스에 연결(Connecting to a MongoDB Database)
몽고DB 데이터베이스에 접근하려면 자동 구성된 org.springframework.data.mongodb.MongoDatabaseFactory
를 삽입할 수 있다. 기본적으로 인스턴스는 mongodb://localhost/test
에서 몽고DB 서버에 연결을 시도한다. 다음 예에서는 몽고DB 데이터베이스에 연결하는 방법을 보여준다.
자바
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final MongoDatabaseFactory mongo;
public MyBean(MongoDatabaseFactory mongo) {
this.mongo = mongo;
}
public MongoCollection<Document> someMethod() {
MongoDatabase db = this.mongo.getMongoDatabase();
return db.getCollection("users");
}
}
코틀린
import com.mongodb.client.MongoCollection
import org.bson.Document
import org.springframework.data.mongodb.MongoDatabaseFactory
import org.springframework.stereotype.Component
@Component
class MyBean(private val mongo: MongoDatabaseFactory) {
fun someMethod(): MongoCollection<Document> {
val db = mongo.mongoDatabase
return db.getCollection("users")
}
}
몽고클라이언트(MongoClient)를 직접 정의한 경우 적합한 몽고데이터베이스팩토리(MongoDatabaseFactory)를 자동 구성하는 데 사용된다.
자동 구성된 몽고클라이언트(MongoClient)는 몽고클라이언트세팅즈(MongoClientSettings) 빈을 사용하여 생성된다. 몽고클라이언트세팅즈(MongoClientSettings)를 직접 정의한 경우 수정 없이 사용되며 spring.data.mongodb
속성은 무시됩니다. 그렇지 않으면 MongoClientSettings가 자동으로 구성되고 spring.data.mongodb
프로퍼티스가 적용된다. 두 경우 모두 하나 이상의 몽고클라이언트세팅즈빌더커스터마이저(MongoClientSettingsBuilderCustomizer) 빈을 선언하여 몽고클라이언트세팅즈(MongoClientSettings) 구성을 미세 조정할 수 있다. 각각은 몽고클라이언트세팅즈(MongoClientSettings)를 빌드하는 데 사용되는 MongoClientSettings.Builder
와 함께 순서대로 호출된다.
다음 예제와 같이 spring.data.mongodb.uri
프로퍼티스를 설정하여 URL을 변경하고 복제본 세트와 같은 추가 설정을 구성할 수 있다.
프로퍼티스(Properties)
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
Yaml
spring:
data:
mongodb:
uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"
또는 개별 프로퍼티스를 사용하여 커넥션 세부 정보를 지정할 수 있다. 예를 들어 application.properties에서 다음 설정을 선언할 수 있다.
프로퍼티스(Properties)
spring.data.mongodb.host=mongoserver1.example.com
spring.data.mongodb.port=27017
spring.data.mongodb.additional-hosts[0]=mongoserver2.example.com:23456
spring.data.mongodb.database=test
spring.data.mongodb.username=user
spring.data.mongodb.password=secret
Yaml
spring:
data:
mongodb:
host: "mongoserver1.example.com"
port: 27017
additional-hosts:
- "mongoserver2.example.com:23456"
database: "test"
username: "user"
password: "secret"
다음 예에 표시된 대로 프로퍼티스를 설정하여 서버와의 통신에 SSL을 사용하도록 자동 구성된 몽고클라이언트(MongoClient)를 구성할 수 있다.
프로퍼티스(Properties)
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.enabled=true
Yaml
spring:
data:
mongodb:
uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"
ssl:
enabled: true
이 예에 표시된 대로 커스텀 SSL 신뢰 자료(trust material)를 SSL 번들로 구성하고 몽고클라이언트(MongoClient)에 적용할 수 있다.
프로퍼티스(Properties)
spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.bundle=example
Yaml
spring:
data:
mongodb:
uri: "mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test"
ssl:
bundle: "example"
Tip
spring.data.mongodb.port를 지정하지 않으면 기본값 27017이 사용된다. 위 예제에서 이 줄을 삭제할 수 있다.
host:port 구문을 사용하여 호스트 주소의 일부로 포트를 지정할 수도 있다. 추가 호스트 항목의 포트를 변경해야 하는 경우 이 포맷을 사용해야 한다.
스프링 데이터 몽고DB를 사용하지 않는 경우 몽고데이터베이스팩토리(MongoDatabaseFactory)를 사용하는 대신 몽고클라이언트(MongoClient) 빈을 주입할 수 있다. 몽고DB 연결 설정을 완전히 제어하려면 자체 몽고데이터베이스팩토리(MongoDatabaseFactory) 또는 몽고클라이언트(MongoClient) 빈을 선언할 수도 있다.
리액티브 드라이버를 사용하는 경우 SSL에 네티(Netty)가 필요하다. 자동 구성은 네티를 사용할 수 있고 사용할 팩토리가 아직 커스텀되지 않은 경우 이 팩토리를 자동으로 구성한다.
몽고템플릿(MongoTemplate)
스프링 데이터 몽고DB는 스프링의 JdbcTemplate과 디자인이 매우 유사한 몽고템플릿(MongoTemplate) 클래스를 제공한다. JdbcTemplate과 마찬가지로 스프링 부트는 다음과 같이 템플릿을 삽입할 수 있도록 빈을 자동 구성한다.
자바
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final MongoTemplate mongoTemplate;
public MyBean(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public MongoCollection<Document> someMethod() {
return this.mongoTemplate.getCollection("users");
}
}
코틀린
import com.mongodb.client.MongoCollection
import org.bson.Document
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val mongoTemplate: MongoTemplate) {
fun someMethod(): MongoCollection<Document> {
return mongoTemplate.getCollection("users")
}
}
자세한 내용은 몽고오퍼레이션(MongoOperations) 자바독(Javadoc)을 참고하자.
스프링 데이터 MongoDB 리포지터리(Spring Data MongoDB Repositories)
스프링 데이터에는 몽고DB에 대한 리포지터리 지원이 포함되어 있다. 앞서 설명한 JPA 리포지터리와 마찬가지로 기본 원칙은 쿼리가 메서드명을 기반으로 자동으로 구성된다는 것이다.
실제로 스프링 데이터 JPA와 스프링 데이터 몽고DB는 모두 동일한 공통 인프라를 공유한다. 이전의 JPA 예제를 사용할 수 있으며, City가 이제 JPA @Entity가 아닌 몽고DB 데이터 클래스라고 가정하면 다음 예제와 같이 동일한 방식으로 작동한다.
자바
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
코틀린
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
interface CityRepository :
Repository<City?, Long?> {
fun findAll(pageable: Pageable?): Page<City?>?
fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?
}
@EntityScan 어노테이션을 사용하여 문서 스캔 위치를 커스텀할 수 있다.
풍부한 객체 매핑 기술을 포함하여 스프링 데이터 몽고DB에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
9.2.3. 네오4j(Neo4j)
네오4j는 일급 관계(first class relationship)로 연결된 노드의 풍부한 데이터 모델을 사용하는 오픈 소스 NoSQL 그래프 데이터베이스로, 기존 RDBMS 접근 방식보다 연결된 빅 데이터(connected big data)에 더 적합하다. 스프링 부트는 spring-boot-starter-data-neo4j
“스타터(Starter)”를 포함하여 네오4j 작업에 대한 몇 가지 편의성을 제공한다.
네오4j 데이터베이스 연결(Connecting to a Neo4j Database)
네오4j 서버에 접근하려면 자동 구성된 org.neo4j.driver.Driver
를 삽입할 수 있다. 기본적으로 인스턴스는 Bolt 프로토콜을 사용하여 localhost:7687에서 네오4j 서버에 연결을 시도한다. 다음 예제는 무엇보다도 세션에 대한 접근를 제공하는 네오4j 드라이버를 삽입하는 방법을 보여준다.
자바
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Values;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final Driver driver;
public MyBean(Driver driver) {
this.driver = driver;
}
public String someMethod(String message) {
try (Session session = this.driver.session()) {
return session.executeWrite((transaction) ->
transaction.run(
"CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
Values.parameters("message", message)
).single()
.get(0)
.asString()
);
}
}
}
코틀린
import org.neo4j.driver.*
import org.springframework.stereotype.Component
@Component
class MyBean(private val driver: Driver) {
fun someMethod(message: String?): String {
driver.session().use { session ->
return@someMethod session.executeWrite { transaction: TransactionContext ->
transaction
.run(
"CREATE (a:Greeting) SET a.message = \$message RETURN a.message + ', from node ' + id(a)",
Values.parameters("message", message)
).single()[0]
.asString()
}
}
}
}
spring.neo4j.*
프로퍼티스를 사용하여 드라이버의 다양한 측면을 구성할 수 있다. 다음 예제에서는 사용할 URI 및 크레덴셜(credential)을 구성하는 방법을 보여준다.
프로퍼티스(Properties)
spring.neo4j.uri=bolt://my-server:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
Yaml
spring:
neo4j:
uri: "bolt://my-server:7687"
authentication:
username: "neo4j"
password: "secret"
자동 구성된 드라이버는 컨피그빌더(ConfigBuilder)를 사용하여 생성된다. 구성을 미세 조정하려면 하나 이상의 컨피그빌더커스터마이저(ConfigBuilderCustomizer) 빈을 선언하자. 각각은 드라이버를 빌드하는 데 사용되는 컨피그빌더(ConfigBuilder)와 함께 순서대로 호출된다.
스프링 데이터 네오4j 리포지터리(Spring Data Neo4j Repositories)
스프링 데이터에는 네오4j에 대한 리포지터리 지원이 포함되어 있다. 스프링 데이터 네오4j에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
스프링 데이터 네오4j는 다른 많은 스프링 데이터 모듈과 마찬가지로 스프링 데이터 JPA와 공통 인프라를 공유한다. 이전 JPA 예제를 사용하여 City를 JPA @Entity가 아닌 스프링 데이터 네오4j @Node로 정의할 수 있으며 리포지터리 추상화는 다음 예제와 같이 동일한 방식으로 작동한다.
자바
import java.util.Optional;
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface CityRepository extends Neo4jRepository<City, Long> {
Optional<City> findOneByNameAndState(String name, String state);
}
코틀린
import org.springframework.data.neo4j.repository.Neo4jRepository
import java.util.Optional
interface CityRepository : Neo4jRepository<City?, Long?> {
fun findOneByNameAndState(name: String?, state: String?): Optional<City?>?
}
spring-boot-starter-data-neo4j
“스타터(Starter)”는 리포지터리 지원과 트랜잭션 관리를 가능하게 한다. 스프링 부트는 Neo4jTemplate 또는 ReactiveNeo4jTemplate 빈을 사용하여 클래식 및 리액티브 네오4j 리포지터리를 모두 지원한다. 프로젝트 리액터(Project Reactor)를 클래스패스에서 사용할 수 있으면 리액티브 스타일도 자동으로 구성된다.
@Configuration-bean
에서 각각 @EnableNeo4jRepositories
및 @EntityScan
을 사용하여 리포지터리 및 엔터티를 찾기 위한 위치를 커스텀할 수 있다.
Note
리액티브 스타일을 사용하는 애플리케이션에서는 리액티브트랜젝션매니저(ReactiveTransactionManager)가 자동으로 구성되지 않는다. 트랜잭션 관리를 활성화하려면 구성에 다음 빈을 정의해야 한다.
자바
import org.neo4j.driver.Driver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
@Configuration(proxyBeanMethods = false)
public class MyNeo4jConfiguration {
@Bean
public ReactiveNeo4jTransactionManager reactiveTransactionManager(
Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider
) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}
}
코틀린
import org.neo4j.driver.Driver
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager
@Configuration(proxyBeanMethods = false)
class MyNeo4jConfiguration {
@Bean
fun reactiveTransactionManager(
driver: Driver,
databaseNameProvider: ReactiveDatabaseSelectionProvider
): ReactiveNeo4jTransactionManager {
return ReactiveNeo4jTransactionManager(driver, databaseNameProvider)
}
}
9.2.4. 엘라스틱서치(Elasticsearch)
엘라스틱서치는 오픈 소스, 분산형 RESTful 검색 및 분석 엔진이다. 스프링 부트는 엘라스틱서치 클라이언트에 대한 기본 자동 구성을 제공한다. 스프링 부트는 여러 클라이언트를 지원한다.
- 공식 로우레벨 REST 클라이언트
- 공식 자바 API 클라이언트
- 스프링 데이터 엘라스틱서치에서 제공하는
리액티브엘라스틱서치클라이언트(ReactiveElasticsearchClient)
스프링 부트는 전용 “스타터”인 spring-boot-starter-data-elasticsearch
를 제공한다.
REST 클라이언트를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch Using REST clients)
엘라스틱서치는 클러스터를 쿼리하는 데 사용할 수 있는 두 가지 REST 클라이언트, 즉 org.elasticsearch.client:elasticsearch-rest-client
모듈의 로우 레벨 클라이언트와 co.elastic.clients:elasticsearch-java
의 자바 API 클라이언트를 제공한다. 또한 스프링 부트는 org.springframework.data:spring-data-elasticsearch
모듈에서 리액티브 클라이언트에 대한 지원을 제공한다. 기본적으로 클라이언트는 localhost:9200
을 대상으로 한다. 다음 예제와 같이 spring.elasticsearch.*
프로퍼티스를 사용하여 클라이언트 구성 방법을 추가로 조정할 수 있다.
프로퍼티스(Properties)
spring.elasticsearch.uris=https://search.example.com:9200
spring.elasticsearch.socket-timeout=10s
spring.elasticsearch.username=user
spring.elasticsearch.password=secret
Yaml
spring:
elasticsearch:
uris: "https://search.example.com:9200"
socket-timeout: "10s"
username: "user"
password: "secret"
레스트클라이언트를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch Using RestClient)
클래스패스에 elasticsearch-rest-client
가 있으면 스프링부트는 레스트클라이언트(RestClient) 빈을 자동 구성하고 등록한다. 이전에 설명한 프로퍼티스 외에도 레스트클라이언트(RestClient)를 조정하기 위해 고급 커스텀를 위해 레스트클라이언트빌더커스터마이저(RestClientBuilderCustomizer)를 구현하는 임의의 수의 빈을 등록할 수 있다. 클라이언트 구성을 완전히 제어하려면 레스트클라이언트빌더(RestClientBuilder) 빈을 정의해야 한다.
프로퍼티스(Properties)
spring.elasticsearch.restclient.sniffer.interval=10m
spring.elasticsearch.restclient.sniffer.delay-after-failure=30s
Yaml
spring:
elasticsearch:
restclient:
sniffer:
interval: "10m"
delay-after-failure: "30s"
엘라스틱서치클라이언트를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch Using ElasticsearchClient)
클래스패스에 co.elastic.clients:elasticsearch-java
가 있는 경우 스프링 부트는 엘라스틱서치클라이언트(ElasticsearchClient) 빈을 자동 구성하고 등록한다.
엘라스틱서치클라이언트(ElasticsearchClient)는 이전에 설명한 레스트클라이언트(RestClient)에 의존하는 전송을 사용한다. 따라서 이전에 설명한 프로퍼티스를 사용하여 엘라스틱서치클라이언트(ElasticsearchClient)를 구성할 수 있다. 또한 트랜스포트옵션(TransportOptions) 빈을 정의하여 전송 동작을 추가로 제어할 수 있다.
리액티브엘라스틱서치클라이언트를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch using ReactiveElasticsearchClient)
스프링 데이터 엘라스틱서치는 리액치브 방식으로 엘라스틱서치 인스턴스를 쿼리하기 위해 리액티브엘라스틱서치클라이언트(ReactiveElasticsearchClient)를 제공한다. 클래스패스에 스프링 데이터 엘라스틱서치 및 리액터가 있는 경우 스프링 부트는 리액티브엘라스틱서치클라이언트(ReactiveElasticsearchClient)를 자동으로 구성하고 등록한다.
리액티브엘라스틱서치클라이언트(ReactiveElasticsearchclient)는 이전에 설명한 레스트클라이언트(RestClient)에 의존하는 전송을 사용한다. 따라서 이전에 설명한 프로퍼티스를 사용하여 리액티브엘라스틱서치클라이언트(ReactiveElasticsearchClient)를 구성할 수 있다. 또한 트랜스포트옵션(TransportOptions) 빈을 정의하여 전송 동작을 추가로 제어할 수 있다.
스프링 데이터를 사용하여 엘라스틱서치에 연결(Connecting to Elasticsearch by Using Spring Data)
엘라스틱서치에 연결하려면 엘라스틱서치클라이언트(ElasticsearchClient) 빈을 정의하고 스프링 부트에서 자동 구성하거나 애플리케이션에서 수동으로 제공해야 한다(이전 절 참고). 이 구성을 사용하면 다음 예제와 같이 엘라스틱서치템플릿(ElasticsearchTemplate)을 다른 스프링 빈처럼 주입할 수 있다.
자바
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final ElasticsearchTemplate template;
public MyBean(ElasticsearchTemplate template) {
this.template = template;
}
public boolean someMethod(String id) {
return this.template.exists(id, User.class);
}
}
코틀린
import org.springframework.stereotype.Component
@Component
class MyBean(private val template:
org.springframework.data.elasticsearch.client.erhlc.ElasticsearchRestTemplate ) {
fun someMethod(id: String): Boolean {
return template.exists(id, User::class.java)
}
}
spring-data-elasticsearch
및 리액터가 있는 경우 스프링 부트는 리액티브엘라스틱서치클라이언트(ReactiveElasticsearchClient) 및 리액티브엘라스틱서치템플릿(ReactiveElasticsearchTemplate)을 빈으로 자동 구성할 수도 있다. 이는 다른 REST 클라이언트의 리액티브와 동일하다.
스프링 데이터 엘라스틱서치 리포지터리(Spring Data Elasticsearch Repositories)
스프링 테이버에는 엘라스틱서치(Elasticsearch)에 대한 리포지터리를 지원한다. 앞서 설명한 JPA 리포지터리와 마찬가지로 기본 원칙은 쿼리가 메서드명 기반으로 자동으로 구성된다는 것이다.
실제로, 스프링 데이터 JPA와 스프링 데이터 엘라스틱서치는 모두 동일한 공통 인프라를 공유한다. 이전의 JPA 예제를 사용할 수 있으며 City가 이제 JPA @Entity가 아닌 엘라스틱서치 @Document 클래스라고 가정하면 동일한 방식으로 작동한다.
스프링 데이터 엘라스틱서치에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
스프링 부트는 엘라스틱서치레스트템플릿(ElasticsearchRestTemplate) 또는 리액티브엘라스틱서치템플릿(ReactiveElasticsearchTemplate) 빈을 사용하여 클래식 및 리액티브 엘라스틱서치 리포지터리를 모두 지원한다. 필요한 의존성이 존재하는 경우 이러한 빈은 스프링 부트에 의해 자동 구성될 가능성이 높다.
엘라스틱서치 리포지터리를 백업하기 위해 자체 템플릿을 사용하려는 경우 이름이 “elasticsearchTemplate”라면 경우 자체 엘라스틱서치레스트템플릿(ElasticsearchRestTemplate) 또는 엘라스틱서치오퍼레이션(ElasticsearchOperations) @Bean을 추가할 수 있다. 빈명이 “reactiveElasticsearchTemplate”인 리엑티브엘라스틱서치템플릿(ReactiveElasticsearchTemplate) 및 리액티브엘라스틱서치오퍼레이션(ReactiveElasticsearchOperations)에도 동일하게 적용된다.
다음 프로퍼티스을 사용하여 리포지터리 지원을 비활성화하도록 선택할 수 있다.
프로퍼티스(Properties)
spring.data.elasticsearch.repositories.enabled=false
Yaml
spring:
data:
elasticsearch:
repositories:
enabled: false
9.2.5. 카산드라(Cassandra)
카산드라는 많은 상용 서버에서 대량의 데이터를 처리하도록 설계된 오픈 소스 분산 데이터베이스 관리 시스템이다. 스프링 부트는 카산트라에 대한 자동 구성과 스프링 데이터 카산드라가 제공하는 추상화를 제공한다. 편리한 방법으로 의존성을 수집하기 위한 spring-boot-starter-data-cassandra
“스타터”가 있다.
카산드라에 연결(Connecting to Cassandra)
다른 스프링 빈과 마찬가지로 자동 구성된 카산드라템플릿(CassandraTemplate) 또는 카산드라 Cql세션(Cassandra CqlSession)
인스턴스를 주입할 수 있다. spring.cassandra.*
프로퍼티스를 사용하여 커넥션을 커스텀할 수 있다. 일반적으로 다음 예와 같이 keyspace-name
및 contact-point
와 로컬 데이터 센터명을 제공한다.
프로퍼티스(Properties)
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1:9042,cassandrahost2:9042
spring.cassandra.local-datacenter=datacenter1
Yaml
spring:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1:9042,cassandrahost2:9042"
local-datacenter: "datacenter1"
모든 지점의 포트가 동일한 경우 다음 예제와 같이 줄여(shortcut)쓸 수 있고 호스트명만 지정할 수 있다.
프로퍼티스(Properties)
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
Yaml
spring:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1,cassandrahost2"
local-datacenter: "datacenter1"
이 두 가지 예제는 포트 기본값이 9042로 동일하다. 포트를 구성해야 하는 경우 spring.cassandra.port
를 사용하자.
다음 예제에 표시된 대로 프로퍼티스를 설정하여 서버와의 통신에 SSL을 사용하도록 자동 구성된 Cql세션(CqlSession)을 구성할 수 있다.
프로퍼티스(Properties)
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.ssl.enabled=true
Yaml
spring:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1,cassandrahost2"
local-datacenter: "datacenter1"
ssl:
enabled: true
다음 예제에 표시된 대로 커스텀 SSL 신뢰 자료(trust material)를 SSL 번들에서 구성하고 Cql세션(CqlSession)에 적용할 수 있다.
프로퍼티스(Properties)
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.ssl.bundle=example
Yaml
spring:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1,cassandrahost2"
local-datacenter: "datacenter1"
ssl:
bundle: "example"
Note
카산드라 드라이버에는 클래스패스의 루트에 application.conf
를 로드하는 자체 구성 인프라가 있다.
스프링 부트는 기본적으로 이러한 파일을 찾지 않지만 spring.cassandra.config
를 사용하여 로드할 수 있다. spring.cassandra.*
와 구성 파일에 프로퍼티가 모두 있는 경우 spring.cassandra.*
의 값이 우선 적용된다.
고급 드라이버 커스텀을 위해 드라이버컨피그로더빌더커스터마이저(DriverConfigLoaderBuilderCustomizer)
를 구현하는 임의 수의 비을 등록할 수 있다. Cql세션(CqlSession)은 Cql세션빌더커스터마이저(CqlSessionBuilderCustomizer) 타입의 빈을 사용하여 커스텀할 수 있다.
Cql세션빌더(CqlSessionBuilder)를 사용하여 여러 Cql세션(CqlSession) 빈을 생성하는 경우, 빌더가 변경 가능(mutable)하므로 각 세션에 대해 새로운 복사본을 주입해야 한다는 점을 명심하자.
다음 코드 목록은 카산드라 빈을 주입하는 방법을 보여준다.
자바
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final CassandraTemplate template;
public MyBean(CassandraTemplate template) {
this.template = template;
}
public long someMethod() {
return this.template.count(User.class);
}
}
코틀린
import org.springframework.data.cassandra.core.CassandraTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val template: CassandraTemplate) {
fun someMethod(): Long {
return template.count(User::class.java)
}
}
카산드라템플릿(CassandraTemplate) 타입의 고유한 @Bean을 추가하면 기본값이 대체된다.
스프링 데이터 카산드라 리포지터리(Spring Data Cassandra Repositories)
스프링 데이터에는 카산드라에 대한 기본 리포지터리 지원이 포함되어 있다. 현재 이는 앞서 설명한 JPA 리포지터리보다 더 제한적이며 @Query 어노테이션이 달린 finder 메서드가 필요하다.
스프링 데이터 카산드라에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
9.2.6. 카우치베이스(Couchbase)
카우치베이스(Couchbase)는 대화형 애플리케이션에 최적화된 오픈 소스, 분산, 다중 모델 NoSQL 문서 지향 데이터베이스다. 스프링부트는 카우치베이스(Couchbase)에 대한 자동 구성과 스프링 데이터 카우치베이스에서 제공하는 추상화를 제공한다. 편리한 방법으로 의존성을 수집하기 위해 spring-boot-starter-data-couchbase
및 spring-boot-starter-data-couchbase-reactive
“스타터”가 있다.
카우치베이스애 연결(Connecting to Couchbase)
카우치베이스 SDK와 일부 구성을 추가하여 클러스터를 얻을 수 있다. spring.couchbase.*
프로퍼티스를 사용하여 커넥션을 커스텀할 수 있다. 일반적으로 다음 예제와 같이 connection string, username, password를 제공한다.
프로퍼티스(Properties)
spring.couchbase.connection-string=couchbase://192.168.1.123
spring.couchbase.username=user
spring.couchbase.password=secret
Yaml
spring:
couchbase:
connection-string: "couchbase://192.168.1.123"
username: "user"
password: "secret"
클러스터인바이런먼트(ClusterEnvironment) 설정 중 일부를 커스텀하는 것도 가능하다. 다음 예제는 새 버킷을 열도록 제한 시간을 변경하고 구성된 SSL 번들을 참조하여 SSL 지원을 활성화한다.
프로퍼티스(Properties)
spring.couchbase.env.timeouts.connect=3s
spring.couchbase.env.ssl.bundle=example
Yaml
spring:
couchbase:
env:
timeouts:
connect: "3s"
ssl:
bundle: "example"
자세한 내용은 spring.couchbase.env.*
프로퍼티스를 확인하자. 더 많은 제어를 위해 하나 이상의 클러스터인바이런먼트빌더커스터마이저(ClusterEnvironmentBuilderCustomizer) 빈을 사용할 수 있다.
스프링 데이터 카우치베이스 리포지터리(Spring Data Couchbase Repositories)
스프링 데이터에는 카우치베이스에 대한 리포지터리 지원이 포함되어 있다. 스프링 데이터 카우치베이스(Spring Data Couchbase)에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
프로퍼티스(Properties)
spring.data.couchbase.bucket-name=my-bucket
Yaml
spring:
data:
couchbase:
bucket-name: "my-bucket"
다음 예에서는 카우치베이스템플릿(CouchbaseTemplate) 빈을 삽입하는 방법을 보여준다.
자바
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final CouchbaseTemplate template;
public MyBean(CouchbaseTemplate template) {
this.template = template;
}
public String someMethod() {
return this.template.getBucketName();
}
}
코틀린
import org.springframework.data.couchbase.core.CouchbaseTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val template: CouchbaseTemplate) {
fun someMethod(): String {
return template.bucketName
}
}
자동 구성에서 제공되는 항목을 오버라이드하기 위해 자체 구성에서 정의할 수 있는 몇 가지 빈이 있다.
- 이름이 카우치베이스매핑컨텍스트(CouchbaseMappingContext)인 카우치베이스매핑컨텍스트(CouchbaseMappingContext) @Bean.
- 이름이 카우치베이스커스텀컨버전(CouchbaseCustomConversions)인 커스텀컨버전(CustomConversions) @Bean.
- 카우치베이스템플릿(CouchbaseTemplate)이라는 이름을 가진 카우치베이스템플릿(CouchbaseTemplate) @Bean.
자신의 구성에 해당 이름을 하드 코딩하지 않으려면, 스프링 데이터 카우치베이스(Couchbase)에서 제공하는 빈네임즈(BeanNames)를 재사용할 수 있다. 예를 들어 다음과 같이 사용할 컨버터를 커스텀할 수 있다.
자바
import org.assertj.core.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseConfiguration {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
public CouchbaseCustomConversions myCustomConversions() {
return new CouchbaseCustomConversions(Arrays.asList(new MyConverter()));
}
}
코틀린
import org.assertj.core.util.Arrays
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.couchbase.config.BeanNames
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions
@Configuration(proxyBeanMethods = false)
class MyCouchbaseConfiguration {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
fun myCustomConversions(): CouchbaseCustomConversions {
return CouchbaseCustomConversions(Arrays.asList(MyConverter()))
}
}
9.2.7. LDAP
LDAP(Lightweight Directory Access Protocol)는 IP 네트워크를 통해 분산된 디렉토리 정보 서비스에 접근하고 유지 관리하기 위한 개방형, 공급업체 중립적, 산업 표준 응용 프로그램 프로토콜이다. 스프링 부트는 호환되는 모든 LDAP 서버에 대한 자동 구성을 제공할 뿐만 아니라 UnboundID의 임베디드 인메모리 LDAP 서버에 대한 지원도 제공한다.
LDAP 추상화는 스프링 데이터 LDAP에서 제공된다. 편리한 방법으로 의존성을 수집하기 위해 spring-boot-starter-data-ldap
“스타터(Starter)”가 있다.
LDAP 서버에 연결(Connecting to an LDAP Server)
LDAP 서버에 연결하려면 다음과 같이 spring-boot-starter-data-ldap
“스타터(Starter)” 또는 spring-ldap-core
에 대한 의존성을 선언한 다음 application.properties
에서 서버의 URL을 선언해야 한다. 다음 예제를 보자:
프로퍼티스(Properties)
spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret
Yaml
spring:
ldap:
urls: "ldap://myserver:1235"
username: "admin"
password: "secret"
연결 설정을 커스텀해야 하는 경우, spring.ldap.base
및 spring.ldap.base-environment
프로퍼티스를 사용할 수 있다.
Ldap컨텍스트소스(LdapContextSource)는 이러한 설정을 기반으로 자동 구성된다. Dir컨텍스트어센티케이션스트래터지(DirContextAuthenticationStrategy) 빈을 사용할 수 있는 경우 자동 구성된 Ldap컨텍스트소스(LdapContextSource)에 연결된다. 예를 들어 풀드컨텍스트소스(PooledContextSource)를 사용하기 위해 이를 커스텀해야 하는 경우에도 자동 구성된 Ldap컨텍스트소스(LdapContextSource)를 주입할 수 있다. 자동 구성된 Ldap템플릿(LdapTemplate)이 이를 사용할 수 있도록 커스텀된 컨텍스트소스(ContextSource)를 @Primary로 플래그 지정해야 한다.
스프링 데이터 LDAP 리포지터리(Spring Data LDAP Repositories)
스프링 데이터에는 LDAP에 대한 리포지터리 지원이 포함되어 있다. 스프링 데이터 LDAP에 대한 자세한 내용은 레퍼런스 문서를 참고하자.
다음 예제와 같이 다른 스프링 비과 마찬가지로 자동 구성된 Ldap템플릿(LdapTemplate) 인스턴스를 주입할 수도 있다.
자바
import java.util.List;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final LdapTemplate template;
public MyBean(LdapTemplate template) {
this.template = template;
}
public List<User> someMethod() {
return this.template.findAll(User.class);
}
}
코틀린
import org.springframework.ldap.core.LdapTemplate
import org.springframework.stereotype.Component
@Component
class MyBean(private val template: LdapTemplate) {
fun someMethod(): List<User> {
return template.findAll(User::class.java)
}
}
임베디드 인메모리 LDAP 서버(Embedded In-memory LDAP Server)
테스트 목적으로 스프링 부트는 UnboundID
에서 인메모리 LDAP 서버의 자동 구성을 지원한다. 서버를 구성하려면 다음과 같이 com.unboundid:unboundid-ldapsdk
의존성을 추가하고 spring.ldap.embedded.base-dn
프로퍼티스를 선언한다.
프로퍼티스(Properties)
spring.ldap.embedded.base-dn=dc=spring,dc=io
Yaml
spring:
ldap:
embedded:
base-dn: "dc=spring,dc=io"
노트
여러 개의 base-dn
값을 정의할 수 있지만 고유 이름에는 일반적으로 쉼표가 포함되므로 올바른 표기법을 사용하여 정의해야 한다. yaml 파일에서는 yaml 목록 표기법을 사용할 수 있다. 프로퍼티스 파일에서는, 프로퍼티스명의 일부로 인덱스를 포함해야 한다.
프로퍼티스(Properties)
spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=vmware,dc=com
Yaml
spring.ldap.embedded.base-dn:
- "dc=spring,dc=io"
- "dc=vmware,dc=com"
기본적으로, 서버는 임의의 포트에서 시작되고 일반 LDAP 지원을 트리거한다. spring.ldap.urls
프로퍼티스를 지정할 필요가 없다.
클래스패스에 Schema.ldif
파일이 있으면 서버를 초기화하는 데 사용된다. 다른 리소스에서 초기화 스크립트를 로드하려는 경우 spring.ldap.embedded.ldif
프로퍼티를 사용할 수도 있다.
기본적으로, 표준 스키마는 LDIF 파일의 유효성을 검사하는 데 사용된다. spring.ldap.embedded.validation.enabled
프로퍼티를 설정하여 유효성 검사를 완전히 끌 수 있다. 커스텀 애트리뷰트가 있는 경우 spring.ldap.embedded.validation.schema
를 사용하여 커스텀 애트리뷰트 타입 또는 객체 클래스를 정의할 수 있다.
9.2.8. 인플럭스DB(InfluxDB)
인플럭스DB는 운영 모니터링, 애플리케이션 메트릭, 사물 인터넷 센서 데이터 및 실시간 분석과 같은 분야에서 시계열 데이터를 빠르고 고가용성으로 저장하고 검색하는 데 최적화된 오픈 소스 시계열 데이터베이스다.
인플럭스DB에 연결(Connecting to InfluxDB)
다음 예제와 같이 influxdb-java
클라이언트가 클래스패스에 있고 데이터베이스의 URL이 설정된 경우 스프링 부트는 인플럭스DB 인스턴스를 자동으로 구성한다.
프로퍼티스(Properties)
spring.influx.url=https://172.0.0.1:8086
Yaml
spring:
influx:
url: "https://172.0.0.1:8086"
인플럭스DB 커넥션에 사용자와 비밀번호가 필요한 경우 spring.influx.user
및 spring.influx.password
프로퍼티스를 적절하게 설정할 수 있다.
인플럭스DB는 OkHttp를 사용한다. 인플럭스DB가 뒤에서 사용하는 http 클라이언트를 조정해야 하는 경우 인플럿트DbOkHttp클라이언트빌더프로바이더(InfluxDbOkHttpClientBuilderProvider) 빈을 등록할 수 있다.
구성에 대한 더 많은 제어가 필요한 경우 인플럭스Db커스터마이저(InfluxDbCustomizer) 빈 등록을 고려하자.
9.3. 다음에 읽을 내용(What to Read Next)
이제 다양한 데이터 기술과 함께 스프링부트를 사용하는 방법에 대해 감이 잡힐 것이다. 여기에서 다양한 메시징 기술에 대한 스프링 부트의 지원과 이를 애플리케이션에서 활성화하는 방법에 대해 읽을 수 있다.