Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

DevYGwan

Spring Boot에서 다중 데이터베이스 구성 본문

Study/Spring

Spring Boot에서 다중 데이터베이스 구성

YGwan 2025. 3. 3. 21:29

 저희는 기본적으로 IoT 데이터의 경우 대용량 데이터이기 때문에 NoSQL 기반의 데이터베이스 인 ScyllaDB을 사용하여 데이터를 관리했습니다. 그러다보니 기본적인 데이터 (유저 데이터, 장비 Meta 데이터 등)도 ScyllaDB을 사용해서 개발을 진행했습니다. 하지만 NoSQL이다보니, 정형화 된 데이터와 트랜잭션 처리가 RDB보다 효율적이지 못해 이번에 추가적인 "승인" 도메인을 개발하면서 RDB을 반영하기로 결정했습니다.

 RDB을 반영하면서 고민한 사항은 크게 3가지 입니다.

  1. 어떤 RDB을 사용할까?
  2. DB 서버가 다른데, 다른 서버 간의 트랜잭션을 관리 할 일이 있을까?
  3. 백엔드 서버는 어떻게 처리할까? 하나로 가져갈까 DB 별로 분리해서 가져갈까?

 이렇게 3가지를 고민했습니다. 고민하고 내린 결과는 1번의 경우는 Postgres로 하기로 결정했습니다. Postgres를 선택한 이유는 저희 사수님이 Postgres가 익숙한 이유도 있었지만, jsonb을 지원해 Json 데이터를 효율적으로 관리할 수 있다는 장점이 있었고 List 데이터도 지원해 다른 RDB에 비해 지원하는 부분이 많아서 Postgres을 선택하게 되었습니다.

 두번째의 경우에는 지금 현재는 전체적인 데이터를 다 ScyllaDB로 관리하고 있지만, 이번 기회에 IoT에서 올라오는 실시간 데이터들은 ScyllaDB에서 관리하고 그 밖의 데이터들은 Postgres로 관리하기로 결정해 이 두개를 같은 트랜잭션으로 관리할 일이 없어 이 부분에 대한 문제는 고려하지 않는 방향으로 결정했습니다. 두개의 다른 DB 서버 간 트랜잭션 관리를 하는 리소스 보다는 아에 역할을 분리해 서로 다른 역할로 가져가는게 더 좋은 방향이라고 생각했기 때문입니다.

 마지막의 경우에는 사실 고민을 많이 했습니다. 두 DB의 역할을 아에 분리했으니 아에 별도의 서버로 관리하는게 더 좋지 않을까에 대한 고민을 많이 했습니다. 하지만 이 부분도 생각보다 쉽게 결론이 지어졌습니다. 별도의 서버로 관리한다는 것은 단순 백엔드 처리 관점에서는 좋을 수 있지만, 인프라 관점에서는 두개의 별도의 서버를 추가로 관리해야되는 추가적인 고려 사항이 존재합니다. 이후에는 이를 별도로 관리해야 될수도 있겠지만, 현재는 굳이? 그렇게 관리하는게 오히려 인프라 적으로 서버가 터진다거나, 서버 리소스를 더 잡아먹는 등의 단점이 더 많아 하나의 백엔드 서버에 두개의 DB 서버를 연결하기로 결정했습니다.

 

결론 : 하나의 백엔드 서버에 2개의 DB 서버를 연결하자!

 

그렇다면, 어떻게 하나의 백엔드 서버에 2개의 DB을 연결할 수 있을까요?

 


 

 하나의 백엔드 서버에 2개의 DB 서버 연결 방법을 설명하기 전에 간단하게, 개별적으로 ScyllaDB와 PostgresSQL을 연결하는 방법에 대해서 설명드리도록 하겠습니다.

 

ScyllaDB 연결 방법

  • ScyllaDB는 Cassandra와 호환되므로 spring-boot-starter-data-cassandra 의존성 추가
  • ScyllaDB 전용 환경 변수 추가
  • Spring Boot에서 엔티티 & Repository 생성 
  • Docker로 ScyllaDB 실행 후, Keyspace 및 테이블 생성
# ScyllaDB 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-cassandra'

# ScyllaDB 설정 환경 변수
spring:
  data:
    cassandra:
      contact-points: [연결할 호스트 주소]
      port: [사용 포트]
      keyspace-name: [연결한 keyspace 이름]
      schema-action: [스키마 생성 전략]
      local-datacenter: [데이터 센터]

 

ScyllaDB에 관한 구체적인 설명은 이후에 추가로 정리하도록 하겠습니다.

 

PostgresSQL 연결 방법

  • PostgresSQL 의존성 & JPA 의존성 추가
  • Postgres 전용 환경 변수 추가
  • Spring Boot에서 엔티티 & Repository 생성
# PostgresSQL 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'

# postgres 설정 환경 변수
spring:
  datasource:
    url: [RDB_URL]
    username: [RDB_USERNAME]
    password: [RDB_PASSWORD]
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: create // update, validate, none 등 존재
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect

 

 이렇게 개별적으로 DB을 연결하는 방법을 정리했습니다. 사실 이 부분은 기본적으로 Spring Boot을 통해 서버 개발을 해본 사람이라면 익숙한 방법일 것이라고 생각합니다. 그렇다면, 지금부터 하나의 백엔드 서버가 이 2개의 DB을 연결하는 방법에 대해서 설명드리도록 하겠습니다.

 


Spring Boot에서 다중 데이터베이스 구성 방법

 기본적으로 Spring Boot는 하나의 데이터소스만을 사용할 수 있습니다. 하지만 2개 이상의 다중 데이터베이스 연결도 불가능 한 것은 아닙니다. 하지만 주의해야 할 점은 "다중 데이터베이스를 연결할 경우 이들에 대한 설정을 각각 관리해야된다." 입니다.

 

ScyllaConfig 파일

@Configuration
@EnableCassandraRepositories(
    basePackages = "com.ygwan.scylla" // ScyllaDB용 Repository 패키지
)
@EnableCassandraAuditing
public class ScylladbConfig extends AbstractCassandraConfiguration {

    @Value("${spring.data.cassandra.keyspace-name}")
    private String keyspaceName;

    @Value("${spring.data.cassandra.contact-points}")
    private String contactPoints;

    @Value("${spring.data.cassandra.port}")
    private int port;

    @Value("${spring.data.cassandra.username}")
    private String username;

    @Value("${spring.data.cassandra.password}")
    private String password;

    @Value("${spring.data.cassandra.local-datacenter}")
    private String localDatacenter;

    @Override
    protected String getKeyspaceName() {
        return keyspaceName;
    }

    @Override
    protected String getContactPoints() {
        return contactPoints;
    }

    @Bean
    @Override
    public CqlSessionFactoryBean cassandraSession() {
        // ScyllaDB와 연결되는 CQL Session을 설정
        ...
        cassandraSession.setSessionBuilderConfigurer(builder -> 
            builder.addTypeCodecs(new InstantToTruncatedMillisCodec())
        );
    }
}
  • 기본적으로 AbstractCassandraConfiguration 클래스를 상속받아 구현
  • com.ygwan.rdb 패키지에서 Table & Repository 을 찾아 활성화한다.

 

PostgresConfig 파일

@Configuration
@EnableJpaRepositories(
    basePackages = PostgresConfig.PACKAGE_TO_SCAN,
    entityManagerFactoryRef = "postgresEntityManager",
    transactionManagerRef = "postgresTransactionManager"
)
@EnableJpaAuditing
public class PostgresConfig {

    public static final String PACKAGE_TO_SCAN = "com.ygwan.rdb";

    @Value("${spring.jpa.properties.hibernate.dialect}")
    private String hibernateDialect;

    @Value("${spring.jpa.properties.hibernate.hbm2ddl.auto}")
    private String jpaHbm2ddlAuto;

    @Value("${spring.jpa.show-sql}")
    private String jpaShowSql;

    @Value("${spring.jpa.properties.hibernate.default_schema}")
    private String defaultSchema;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.postgres")
    public DataSource postgresDataSource() {
    	// 데이터베이스와의 연결을 관리하는 객체
        // 환경 변수로 관리되는 Postgres 연결 정보를 가져와 연결 
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean postgresEntityManager() {
        // JPA의 EntityManager를 생성하는 Bean
        // PostgreSQL Datasource 설정
        // Hibernate 설정 적용
    }

    @Bean
    public PlatformTransactionManager postgresTransactionManager() {
        // JPA 트랜잭션을 관리하는 TransactionManager를 생성
        // PostgreSQL과 연동된 EntityManagerFactory를 설정하여 데이터베이스 트랜잭션을 제어할 수 있도록 설정
    }
}
  • JPA Repository를 활성화하고, 사용할 EntityManagerFactoryTransactionManager를 설정한다.
  • com.ygwan.rdb 패키지에서 Entity & Repository 을 찾아 활성화한다.

 

 

기본적으로 다중 DB 연결을 보면 @Primary을 사용하라는 것을 많이 볼 수 있습니다.
이는 같은 DB을 여러개 연결하려고 할 때, 우선순위를 둬야하기 때문에 필요합니다.
저같은 경우, 다른 DB 2개를 연결 했기 때문에 @Primary 어노테이션이 필요하지 않습니다. ( RDB + NoSQL이므로)

 

위의 설정을 완료하면, 하나의 Spring Boot 서버에 다중 데이터베이스를 연결할 수 있습니다.
그렇다면, 이러한 다중 데이터베이스는 권장되는 사항일까요?

 

정답은, 필요한 경우에만 다중 데이터베이스를 사용하는 것이 권장됩니다. 저같이 RDB + NoSQL을 사용하여 정형 데이터와 비정형 데이터를 관리할 때는 다중 데이터베이스를 권장하기도 합니다. 하지만 기본적으로 다중 데이터베이스는

  • 트랜잭션 관리 복잡성 증가
  • 코드 복잡성 증가
  • 성능 저하 위험

등의 문제점이 있어 그렇게 권장되진 않습니다.

 


 정리

 이렇게 하나의 Spring Boot 서버에 다중 DB 연결하는 방법을 정리해보았습니다. 저는 항상 DB 여러개가 필요한 경우 별도의 서버를 둬서 관리한 적은 있어도, 하나의 서버에 DB 여러개를 연결해 본 적은 없어 이번 경험이 되게 신선했습니다. 또한, 개발에서 선택지를 고를 때 단순히 성능만을 기준으로 선택지를 두는 것이 아니라 관리의 복잡성, 인프라 비용 등 여러 개를 종합적으로 고려해 최종 선택하는 것이 중요하다는 것을 알게 되었습니다. 어떤 선택지를 선택하든 trade - off 는 분명 존재할 수 있습니다. 이 때 여러 경험을 바탕으로 최적의 선택지를 선택하는 것이 중요하다는 것을 알게 되었습니다.