1. 소개

이 사용방법(예제)에서는 데이터베이스에 대한 연결을 구성하는 다양한 방법을 살펴보겠습니다. 우리는 Spring BootSpring Data MongoDB를 사용할 것입니다 . Spring의 유연한 구성을 탐색하면서 각 접근 방식에 대해 서로 다른 애플리케이션을 만들 것입니다. 결과적으로 가장 적합한 것을 선택할 수 있습니다.

2. 연결 테스트

애플리케이션 구축을 시작하기 전에 테스트 클래스를 생성합니다. 재사용할 몇 가지 상수부터 시작하겠습니다.

public class MongoConnectionApplicationLiveTest {
    private static final String HOST = "localhost";
    private static final String PORT = "27017";
    private static final String DB = "baeldung";
    private static final String USER = "admin";
    private static final String PASS = "password";

    // test cases
}

테스트는 애플리케이션을 실행한 다음 "items" 라는 컬렉션에 문서를 삽입하려고 시도하는 것으로 구성됩니다 . 문서를 삽입한 후 데이터베이스에서 "_id" 를 수신 하고 테스트가 성공한 것으로 간주합니다. 이를 위한 도우미 메서드를 만들어 보겠습니다.

private void assertInsertSucceeds(ConfigurableApplicationContext context) {
    String name = "A";

    MongoTemplate mongo = context.getBean(MongoTemplate.class);
    Document doc = Document.parse("{\"name\":\"" + name + "\"}");
    Document inserted = mongo.insert(doc, "items");

    assertNotNull(inserted.get("_id"));
    assertEquals(inserted.get("name"), name);
}

우리 메서드는 MongoTemplate 인스턴스를 검색할 수 있도록 응용 프로그램에서 Spring 컨텍스트를 받습니다 . 그런 다음 Document.parse() 를 사용하여 문자열에서 간단한 JSON 문서를 작성합니다 .

이렇게 하면 저장소나 문서 클래스를 만들 필요가 없습니다. 그런 다음 삽입 후 삽입된 문서의 속성이 우리가 기대하는 속성인지 확인합니다.

3. application.properties를 통한 최소 설정

첫 번째 예는 연결을 구성하는 가장 일반적인 방법입니다. application.properties 에 데이터베이스 정보를 제공하기만 하면 됩니다 .

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=baeldung
spring.data.mongodb.username=admin
spring.data.mongodb.password=password

사용 가능한 모든 속성은 Spring Boot의 MongoProperties 클래스 에 있습니다 . 이 클래스를 사용하여 기본값을 확인할 수도 있습니다. 응용 프로그램 인수를 통해 속성 파일에서 모든 구성을 정의할 수 있습니다. 다음 섹션에서 이것이 어떻게 작동하는지 살펴보겠습니다.

애플리케이션 클래스에서 시작하고 실행하는 데 특별한 것은 필요하지 않습니다.

@SpringBootApplication
public class SpringMongoConnectionViaPropertiesApp {

    public static void main(String... args) {
        SpringApplication.run(SpringMongoConnectionViaPropertiesApp.class, args);
    }
}

이 구성은 데이터베이스 인스턴스에 연결하는 데 필요한 전부입니다. @SpringBootApplication 어노테이션에는 @EnableAutoConfiguration 이 포함 됩니다 . 애플리케이션이 클래스 경로를 기반으로 하는 MongoDB 애플리케이션임을 발견하는 작업을 처리합니다.

이를 테스트하기 위해 SpringApplicationBuilder를 사용하여  애플리케이션 컨텍스트에 대한 참조를 얻을 수 있습니다. 그런 다음 연결이 유효한지 확인하기 위해 이전에 만든 assertInsertSucceeds 메서드를 사용합니다.

@Test
public void whenPropertiesConfig_thenInsertSucceeds() {
    SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class)
    app.run();

    assertInsertSucceeds(app.context());
}

결국 우리 애플리케이션은 application.properties 파일을 사용하여 성공적으로 연결되었습니다.

3.1. 명령줄 인수로 속성 재정의

명령줄 인수를 사용하여 응용 프로그램을 실행할 때 속성 파일을 재정의할 수 있습니다 . 이들은 java 명령 , mvn 명령 또는 IDE 구성 으로 실행될 때 애플리케이션에 전달됩니다 . 이를 제공하는 방법은 사용 중인 명령에 따라 다릅니다.

mvn을 사용하여 Spring Boot 애플리케이션을 실행하는 예를 살펴보겠습니다 .

mvn spring-boot:run -Dspring-boot.run.arguments='--spring.data.mongodb.port=7017 --spring.data.mongodb.host=localhost'

이를 사용하려면 속성을 spring-boot.run.arguments 인수 에 대한 값으로 지정합니다  . 동일한 속성 이름을 사용하지만 앞에 두 개의 대시가 붙습니다. Spring Boot 2부터는 여러 속성을 공백으로 구분해야 합니다. 마지막으로 명령을 실행한 후 오류가 없어야 합니다.

이 방식으로 구성된 옵션은 항상 속성 파일보다 우선합니다. 이 옵션은 속성 파일을 변경하지 않고 애플리케이션 매개변수를 변경해야 할 때 유용합니다. 예를 들어 자격 증명이 변경되어 더 이상 연결할 수 없는 경우입니다.

테스트에서 이를 시뮬레이션하기 위해 애플리케이션을 실행하기 전에 시스템 속성을 설정할 수 있습니다. 또한 properties 메서드 로 application.properties를 재정의할 수 있습니다 .

@Test
public void givenPrecedence_whenSystemConfig_thenInsertSucceeds() {
    System.setProperty("spring.data.mongodb.host", HOST);
    System.setProperty("spring.data.mongodb.port", PORT);
    System.setProperty("spring.data.mongodb.database", DB);
    System.setProperty("spring.data.mongodb.username", USER);
    System.setProperty("spring.data.mongodb.password", PASS);

    SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class);
      .properties(
        "spring.data.mongodb.host=oldValue",
        "spring.data.mongodb.port=oldValue",
        "spring.data.mongodb.database=oldValue",
        "spring.data.mongodb.username=oldValue",
        "spring.data.mongodb.password=oldValue"
      );
    app.run();

    assertInsertSucceeds(app.context());
}

결과적으로 시스템 속성이 더 우선하므로 속성 파일의 이전 값은 응용 프로그램에 영향을 미치지 않습니다. 이것은 코드를 변경하지 않고 새로운 연결 세부 정보로 애플리케이션을 다시 시작해야 할 때 유용할 수 있습니다.

3.2. 연결 URI 속성 사용

개별 호스트, 포트 등 대신 단일 속성을 사용할 수도 있습니다.

spring.data.mongodb.uri="mongodb://admin:password@localhost:27017/baeldung"

이 속성에는 초기 속성의 모든 값이 포함되므로 5개를 모두 지정할 필요가 없습니다. 기본 형식을 확인해 보겠습니다.

mongodb://<username>:<password>@<host>:<port>/<database>

URI의 데이터베이스 부분은 보다 구체적으로 기본 auth DB 입니다 . 가장 중요한 것은 spring.data.mongodb.uri 속성을 호스트, 포트 및 자격 증명에 대한 개별 속성과 함께 지정할 수 없다는 것입니다. 그렇지 않으면 애플리케이션을 실행할 때 다음 오류가 발생합니다.

@Test
public void givenConnectionUri_whenAlsoIncludingIndividualParameters_thenInvalidConfig() {
    System.setProperty(
      "spring.data.mongodb.uri", 
      "mongodb://" + USER + ":" + PASS + "@" + HOST + ":" + PORT + "/" + DB
    );

    SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaPropertiesApp.class)
      .properties(
        "spring.data.mongodb.host=" + HOST,
        "spring.data.mongodb.port=" + PORT,
        "spring.data.mongodb.username=" + USER,
        "spring.data.mongodb.password=" + PASS
      );

    BeanCreationException e = assertThrows(BeanCreationException.class, () -> {
        app.run();
    });

    Throwable rootCause = e.getRootCause();
    assertTrue(rootCause instanceof IllegalStateException);
    assertThat(rootCause.getMessage()
      .contains("Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified"));
}

결국 이 구성 옵션은 더 짧을 뿐만 아니라 때때로 필요합니다. 일부 옵션은 연결 문자열을 통해서만 사용할 수 있기 때문입니다. 예를 들어 mongodb+srv를 사용하여 복제 세트에 연결합니다. 따라서 다음 예제에서는 이 간단한 구성 속성만 사용합니다.

4. MongoClient를 사용한 Java 설정

MongoClient는 MongoDB 데이터베이스에 대한 연결을 나타내며 항상 내부에서 생성됩니다. 그러나 프로그래밍 방식으로 설정할 수도 있습니다. 더 장황하지만 이 접근 방식에는 몇 가지 장점이 있습니다. 다음 섹션에서 살펴보겠습니다.

4.1. AbstractMongoClientConfiguration을 통해 연결

첫 번째 예에서는 애플리케이션 클래스의 Spring Data MongoDB에서 AbstractMongoClientConfiguration 클래스를 확장합니다 .

@SpringBootApplication
public class SpringMongoConnectionViaClientApp extends AbstractMongoClientConfiguration {
    // main method
}

다음으로 필요한 속성을 주입해 보겠습니다.

@Value("${spring.data.mongodb.uri}")
private String uri;

@Value("${spring.data.mongodb.database}")
private String db;

명확히 하기 위해 이러한 속성은 하드 코딩될 수 있습니다. 또한 예상되는 Spring Data 변수와 다른 이름을 사용할 수 있습니다. 가장 중요한 것은 이번에는 혼합할 수 없는 개별 연결 속성 대신 URI를 사용하고 있다는 것입니다. 따라서 이 애플리케이션에 대해 application.properties를 재사용할 수 없으며 다른 곳으로 이동 해야 합니다 .

AbstractMongoClientConfiguration에서는 getDatabaseName() 을 재정의해야 합니다  . URI에 데이터베이스 이름이 필요하지 않기 때문입니다.

protected String getDatabaseName() {
    return db;
}

이 시점에서 기본 Spring 데이터 변수를 사용하고 있기 때문에 이미 데이터베이스에 연결할 수 있습니다. 또한 MongoDB는 데이터베이스가 존재하지 않는 경우 데이터베이스를 생성합니다. 테스트해 봅시다:

@Test
public void whenClientConfig_thenInsertSucceeds() {
    SpringApplicationBuilder app = new SpringApplicationBuilder(SpringMongoConnectionViaClientApp.class);
    app.web(WebApplicationType.NONE)
      .run(
        "--spring.data.mongodb.uri=mongodb://" + USER + ":" + PASS + "@" + HOST + ":" + PORT + "/" + DB,
        "--spring.data.mongodb.database=" + DB
      );

    assertInsertSucceeds(app.context());
}

마지막으로 mongoClient()를 재정의하여 기존 구성보다 이점을 얻을 수 있습니다. 이 메소드는 URI 변수를 사용하여 MongoDB 클라이언트를 빌드합니다. 그렇게 하면 직접 참조할 수 있습니다. 예를 들어 연결에서 사용할 수 있는 모든 데이터베이스를 나열할 수 있습니다.

@Override
public MongoClient mongoClient() {
    MongoClient client = MongoClients.create(uri);
    ListDatabasesIterable<Document> databases = client.listDatabases();
    databases.forEach(System.out::println);
    return client;
}

이 방법으로 연결을 구성하는 것은 MongoDB 클라이언트 생성을 완전히 제어하려는 경우에 유용합니다.

4.2. 사용자 정의 MongoClientFactoryBean 생성

다음 예제에서는 MongoClientFactoryBean을 생성합니다 .  이번에는 연결 구성을 유지하기 위해 custom.uri 라는 속성을 생성합니다 .

@SpringBootApplication
public class SpringMongoConnectionViaFactoryApp {

    // main method

    @Bean
    public MongoClientFactoryBean mongo(@Value("${custom.uri}") String uri) {
        MongoClientFactoryBean mongo = new MongoClientFactoryBean();
        ConnectionString conn = new ConnectionString(uri);
        mongo.setConnectionString(conn);

        MongoClient client = mongo.getObject();
        client.listDatabaseNames()
          .forEach(System.out::println);
        return mongo;
    }
}

이 접근 방식을 사용하면 AbstractMongoClientConfiguration을 확장할 필요가 없습니다 . 또한 MongoClient 의 생성을 제어할 수 있습니다. 예를 들어 mongo.setSingleton(false) 를 호출하면 mongo.getObject() 를 호출할 때마다 싱글톤 대신 새 클라이언트를 얻게 됩니다 .

4.3. MongoClientSettingsBuilderCustomizer로 연결 세부 정보 설정

마지막 예에서는 MongoClientSettingsBuilderCustomizer를 사용할 것입니다 .

@SpringBootApplication
public class SpringMongoConnectionViaBuilderApp {

    // main method

    @Bean
    public MongoClientSettingsBuilderCustomizer customizer(@Value("${custom.uri}") String uri) {
        ConnectionString connection = new ConnectionString(uri);
        return settings -> settings.applyConnectionString(connection);
    }
}

우리는 이 클래스를 사용하여 연결의 일부를 사용자 정의하지만 나머지는 여전히 자동 구성합니다. 프로그래밍 방식으로 몇 가지 속성만 설정해야 할 때 유용합니다.

5. 결론

이 기사에서는 Spring Data MongoDB가 제공하는 다양한 도구를 살펴보았습니다. 우리는 그것들을 사용하여 다양한 방식으로 연결을 만들었습니다. 또한 구성이 의도한 대로 작동하는지 확인하기 위해 테스트 케이스를 구축했습니다. 한편 구성 우선 순위가 연결 속성에 어떤 영향을 미칠 수 있는지 확인했습니다.

그리고 항상 그렇듯이 소스 코드는 GitHub에서 사용할 수 있습니다 .

res – Persistence (eBook) (cat=Persistence)