샤딩은 대규모 데이터베이스를 작은 단위의 여러 데이터베이스(샤드)로 분할하여 관리하는 기법입니다. 이는 데이터베이스의 성능을 향상시키고, 확장성을 높이기 위해 사용됩니다. 쉽게 말해, 하나의 큰 데이터베이스를 여러 개의 작은 데이터베이스로 나누어 각각의 샤드가 전체 데이터의 일부분만을 담당하게 하는 것입니다.
대부분의 경우, 수평 샤딩이 많이 사용됨.
a. 샤드 키(Sharding Key) 선택
샤딩을 위해 데이터를 어떻게 분할할지 결정하는 샤드 키를 선택해야 합니다. 샤드 키는 데이터를 분배할 기준이 되는 속성입니다. 예를 들어, 사용자 ID, 지역, 이메일 도메인 등이 될 수 있습니다.
b. 샤드 매핑(Shard Mapping) 설정
샤드 키를 기준으로 데이터를 어떤 샤드에 저장할지 매핑하는 규칙을 결정합니다. 일반적으로 해시(Hash) 기반이나 범위(Range) 기반으로 나뉩니다.
c. 데이터 접근 계층 구현
샤딩된 데이터베이스에 접근하기 위해 데이터 접근 계층(Data Access Layer) 을 구현해야 합니다. spring 에는 Spring Data나 MyBatis 등을 사용하여 이를 관리할 수 있습니다.
ex) 샤드 키에 따라 다른 데이터소스를 선택하는 방법
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.shard1")
public DataSource shard1DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "datasource.shard2")
public DataSource shard2DataSource() {
return DataSourceBuilder.create().build();
}
// 샤드 선택 로직
@Bean
public DataSource routingDataSource() {
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override
protected Object determineCurrentLookupKey() {
return ShardContext.getCurrentShard();
}
};
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("shard1", shard1DataSource());
targetDataSources.put("shard2", shard2DataSource());
routingDataSource.setTargetDataSources(targetDataSources);
return routingDataSource;
}
}
d. 트래픽 분산 및 로드 밸런싱
여러 샤드에 대한 트래픽을 효율적으로 분산시키기 위해 로드 밸런서를 설정할 수 있습니다. 이는 각 샤드의 부하를 고르게 유지하고, 특정 샤드에 과부하가 걸리는 것을 방지합니다.
<!-- Maven 의존성 추가 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>5.0.0</version>
</dependency>
# application.yml 설정 예시
spring:
shardingsphere:
datasource:
names: shard1, shard2
shard1:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/shard1
username: user
password: pass
shard2:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/shard2
username: user
password: pass
sharding:
tables:
user:
actual-data-nodes: shard${0..1}.user
table-strategy:
inline:
sharding-column: user_id
algorithm-expression: user_${user_id % 2}
취업 준비를 위해 실습을 통해 Java와 Spring을 활용한 백엔드 개발 역량을 키우는 것은 매우 중요합니다. 특히 데이터베이스 샤딩과 같은 고급 개념을 실습해보면 실무에 큰 도움이 될 것입니다. 아래에 신입 개발자가 실습할 만한 프로젝트 아이디어와 단계별 가이드를 제공해드리겠습니다.
목표: Spring Boot를 사용하여 간단한 사용자 관리 시스템을 구축하고, Apache ShardingSphere를 활용하여 데이터베이스 샤딩을 구현해봅니다.
user-sharding-system/
├── src/
│ ├── main/
│ │ ├── java/com/example/sharding/
│ │ │ ├── controller/
│ │ │ ├── entity/
│ │ │ ├── repository/
│ │ │ ├── service/
│ │ │ └── ShardingApplication.java
│ │ └── resources/
│ │ ├── application.yml
│ │ └── schema.sql
│ └── test/
└── pom.xml
Spring Initializr를 사용하여 새로운 Spring Boot 프로젝트를 생성합니다.
프로젝트 설정:
application.yml 파일에 기본 데이터베이스 설정을 추가합니다.spring:
datasource:
shard1:
url: jdbc:mysql://localhost:3306/shard1
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
shard2:
url: jdbc:mysql://localhost:3306/shard2
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
shard1과 shard2라는 두 개의 데이터베이스를 생성합니다.CREATE DATABASE shard1;
CREATE DATABASE shard2;
pom.xml에 ShardingSphere 관련 의존성을 추가합니다.<dependencies>
<!-- 기존 의존성들 -->
<!-- ShardingSphere 의존성 추가 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-spring-boot-starter</artifactId>
<version>5.0.0</version>
</dependency>
</dependencies>
application.yml에 ShardingSphere 설정을 추가합니다.spring:
shardingsphere:
datasource:
names: shard1, shard2
shard1:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/shard1
username: your_username
password: your_password
shard2:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/shard2
username: your_username
password: your_password
sharding:
tables:
user:
actual-data-nodes: shard${0..1}.user
table-strategy:
inline:
sharding-column: id
algorithm-expression: user_${id % 2}
package com.example.sharding.entity;
import javax.persistence.*;
@Entity
@Table(name = "user")
public class User {
@Id
private Long id;
private String name;
private String email;
// Getters and Setters
}
package com.example.sharding.repository;
import com.example.sharding.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
package com.example.sharding.service;
import com.example.sharding.entity.User;
import com.example.sharding.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User saveUser(User user){
return userRepository.save(user);
}
public List<User> getAllUsers(){
return userRepository.findAll();
}
}
package com.example.sharding.controller;
import com.example.sharding.entity.User;
import com.example.sharding.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User createUser(@RequestBody User user){
return userService.saveUser(user);
}
@GetMapping
public List<User> getUsers(){
return userService.getAllUsers();
}
}
애플리케이션 실행:
사용자 데이터 생성:
curl을 사용하여 여러 사용자 데이터를 생성합니다.curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"id":1,"name":"Alice","email":"alice@example.com"}'
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"id":2,"name":"Bob","email":"bob@example.com"}'
샤드 데이터베이스 확인:
shard1.user과 shard2.user 테이블을 확인하여 데이터가 올바르게 분배되었는지 확인합니다.SELECT * FROM shard1.user;
SELECT * FROM shard2.user;
id 값에 따라 user_0 또는 user_1 테이블에 데이터가 분배되었는지 확인합니다.샤드 키 변경 실습:
수평 샤딩과 수직 샤딩 비교:
샤딩 장애 시나리오 테스트:
성능 테스트:
ShardingSphere의 고급 기능 활용:
위의 실습을 통해 데이터베이스 샤딩의 기본 개념을 이해하고, Java와 Spring 환경에서 실제로 적용해보는 경험을 쌓을 수 있습니다. 샤딩 외에도 다양한 백엔드 개발 기술을 꾸준히 학습하고, 작은 프로젝트를 통해 실력을 키워나가면 취업 준비에 큰 도움이 될 것입니다. 화이팅하세요!