Multi-tenancy Architecture

유녜쥬·2025년 3월 14일

DB

목록 보기
7/9

Multi-tenancy Architecture

  • 여러 사용자가 하나의 시스템을 공유하면서도,각자의 데이터를 독립적으로 관리할 수 있도록 하는 아키텍처 (tenant : 거주자)

1. Shared Database, Shared Schema (1 DB, 1 schema)

  • 동일한 DB 사용
  • table을 사용자별로 구분
  • 같은 DB 안에 여러 tenant 존재
  • 시작 단계의 소규모 SaaS에서 유용

2. Shared Database, Seperate Schema (1 DB, n schema)

  • 동일한 DB 사용
  • tenant마다 다른 schema를 사용하여 데이터 분리
  • SaaS (Software as a Service)

3. n DB, d schema

  • 각 사용자가 자신만의 DB를 가짐
  • 사용자가 접속할 때마다 고유한 DB 사용
  • 각 사용자가 독립적인 DB를 가질 수 있어, 데이터 간섭 없이 각 사용자의 데이터를 독립적으로 관리
  • 고객 맞춤형 SaaS(보안 요구 사항이 매우 높은 경우 등)에서 유용

사용자마다 DB 분리하는 방법

동적 데이터 소스 변경

  • AbstractRountingDataSource -> 동적으로 데이터 소스 선택
  • 사용자의 sessionId나 기타 식별자를 기준으로 적잘한 DB 선택
  1. DataSourceRouting 설정
public class DataSourceRouting extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // 사용자별로 다르게 DB를 선택하는 로직
        String userId = SessionUtils.getUserId(); // 세션 또는 다른 기준으로 사용자 ID를 가져옴
        return userId;
    }
}
  1. DynamicDataSourceConfig 설정
@Configuration
public class DynamicDataSourceConfig {

    @Bean
    public DataSource dataSource() {
        DataSourceRouting dataSourceRouting = new DataSourceRouting();
        Map<Object, Object> dataSourceMap = new HashMap<>();

        // DB 설정 예시: 여러 개의 DB 연결을 설정
        DataSource userDb1 = createDataSource("jdbc:mysql://localhost:3306/userdb1", "user", "password");
        DataSource userDb2 = createDataSource("jdbc:mysql://localhost:3306/userdb2", "user", "password");
        
        dataSourceMap.put("user1", userDb1);
        dataSourceMap.put("user2", userDb2);
        
        dataSourceRouting.setTargetDataSources(dataSourceMap);
        dataSourceRouting.setDefaultTargetDataSource(userDb1);  // 기본 DB 설정
        return dataSourceRouting;
    }

    private DataSource createDataSource(String url, String username, String password) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
  1. SessionUtils
public class SessionUtils {

    public static String getUserId() {
        // 세션에서 사용자 ID를 가져오는 방법
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return (String) request.getSession().getAttribute("userId");
    }
}

각 DB에 대한 설정

  • 사용자가 처음 로그인할 때 해당 사용자의 DB를 생성하거나 연결

동적 DB 변경에 따른 트랜잭션 관리

  • 각 DB마다 별도로 트랜잭션을 관리할 수 있도록 설정
profile
Junior Backend Developer

0개의 댓글