본문 바로가기

PHP & Laravel

PHP 8과 Laravel을 활용한 멀티 테넌트(Multi-Tenant) 애플리케이션 개발

반응형

PHP 8과 Laravel을 활용한 멀티 테넌트(Multi-Tenant) 애플리케이션 개발

 

멀티 테넌트(Multi-Tenant) 아키텍처는 하나의 애플리케이션 인스턴스에서 여러 개의 고객(테넌트)을 지원하는 방식입니다. 이를 통해 인프라 비용 절감, 유지보수 편의성, 데이터 격리를 제공할 수 있습니다.

 

Laravel은 PHP 8의 최신 기능과 결합하여 멀티 테넌트 환경을 구축하는 데 강력한 도구를 제공합니다. 이 글에서는 멀티 테넌트 애플리케이션의 개념, 구현 전략, 그리고 Laravel에서의 실전 적용 방법을 다룹니다.

 

1. 멀티 테넌트 애플리케이션이란?

 

멀티 테넌트 아키텍처는 하나의 애플리케이션에서 여러 개의 독립적인 사용자 그룹(테넌트)이 자신의 데이터를 관리할 수 있도록 설계된 방식입니다.

 

1.1 멀티 테넌트 유형

1. 데이터베이스 공유 (Single Database, Shared Schema)

• 모든 테넌트가 동일한 데이터베이스를 사용하며, 테이블에서 tenant_id를 통해 구분

• 비용이 적게 들며, 간단한 구현 가능

2. 스키마 분리 (Single Database, Multiple Schemas)

• 하나의 데이터베이스 안에서 테넌트별로 스키마를 분리

• 데이터 격리 및 보안 강화

3. 데이터베이스 분리 (Multiple Databases)

• 테넌트마다 별도의 데이터베이스를 사용

• 높은 보안성 및 독립성 제공

 

2. Laravel에서 멀티 테넌트 아키텍처 구현 전략

 

Laravel에서는 다음과 같은 방법으로 멀티 테넌트 애플리케이션을 구현할 수 있습니다.

 

2.1 테넌트 식별 방법

 

테넌트를 식별하기 위해 일반적으로 다음의 방법을 사용합니다.

1. 서브도메인 기반 식별 (tenant1.example.com)

2. URL 경로 기반 식별 (example.com/tenant1)

3. 사용자 로그인 기반 식별 (Auth 정보 활용)

 

2.2 서브도메인을 통한 테넌트 구분

 

1) 미들웨어를 이용한 테넌트 식별

 

namespace App\Http\Middleware;



use Closure;

use App\Models\Tenant;



class IdentifyTenant {

    public function handle($request, Closure $next) {

        $host = $request->getHost();  // example: tenant1.example.com

        $subdomain = explode('.', $host)[0];



        $tenant = Tenant::where('subdomain', $subdomain)->first();



        if (!$tenant) {

            abort(404, '테넌트를 찾을 수 없습니다.');

        }



        app()->instance('tenant', $tenant);



        return $next($request);

    }

}

 

미들웨어 등록:

 

// app/Http/Kernel.php

protected $middlewareGroups = [

    'web' => [

        \App\Http\Middleware\IdentifyTenant::class,

    ],

];

 

라우트 설정:

 

Route::middleware('IdentifyTenant')->group(function () {

    Route::get('/dashboard', function () {

        $tenant = app('tenant');

        return "Welcome to " . $tenant->name;

    });

});

 

2.3 데이터베이스 공유 모델 (Shared Schema) 설정

 

모든 테넌트가 동일한 데이터베이스를 사용하고, tenant_id 컬럼을 추가하여 구분합니다.

 

1) 마이그레이션 수정

 

Schema::create('projects', function (Blueprint $table) {

    $table->id();

    $table->unsignedBigInteger('tenant_id');

    $table->string('name');

    $table->timestamps();

});

 

2) 모델 수정 (Global Scope 적용)

 

namespace App\Models;



use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Model;



class Project extends Model {

    protected static function booted() {

        static::addGlobalScope('tenant', function (Builder $builder) {

            $builder->where('tenant_id', session('tenant_id'));

        });

    }

}

 

3) 테넌트 ID 설정 미들웨어 추가

 

public function handle($request, Closure $next) {

    $tenantId = auth()->user()->tenant_id ?? null;

    session(['tenant_id' => $tenantId]);



    return $next($request);

}

2.4 데이터베이스 분리 방식 적용 (Multiple Databases)

 

각 테넌트별로 별도의 데이터베이스를 연결하려면 동적으로 연결을 변경해야 합니다.

 

1) 동적 데이터베이스 연결 설정

 

use Illuminate\Support\Facades\DB;



public function switchDatabase($tenant) {

    config([

        'database.connections.tenant' => [

            'driver' => 'mysql',

            'host' => $tenant->db_host,

            'database' => $tenant->db_name,

            'username' => $tenant->db_user,

            'password' => $tenant->db_pass,

        ],

    ]);



    DB::purge('tenant');

    DB::reconnect('tenant');

}

 

2) Eloquent 모델에서 동적 연결 적용

 

namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class TenantModel extends Model {

    protected $connection = 'tenant';

}

 

3. 멀티 테넌트 애플리케이션 성능 최적화

 

멀티 테넌트 시스템에서는 성능 최적화가 중요합니다.

1. 캐싱 적용

• Redis를 활용한 테넌트별 데이터 캐싱

• Cache::put('tenant_1_projects', $projects, 3600);

2. 쿼리 최적화

• 테넌트 관련 쿼리에 인덱스 추가

• ALTER TABLE projects ADD INDEX idx_tenant_id (tenant_id);

3. 로드 밸런싱 적용

• 여러 데이터베이스 인스턴스를 활용한 로드 분산

 

4. 멀티 테넌트 구현 시 고려할 보안 요소

 

멀티 테넌트 시스템에서 보안은 필수적입니다. 다음과 같은 보안 요소를 고려해야 합니다.

1. 데이터 격리 강화

• 테넌트 ID를 항상 검증

• 잘못된 테넌트 접근 방지

2. 액세스 제어

• Laravel의 Policy와 Gates를 활용하여 테넌트 권한 관리

3. 서브도메인 인증

• 테넌트별 SSL 인증서 적용

 

5. 결론

 

Laravel과 PHP 8을 활용한 멀티 테넌트 애플리케이션을 구축하면 유연성과 확장성을 극대화할 수 있습니다.

 

핵심 요약:

• 서브도메인 또는 URL 기반으로 테넌트 구분

• 공유 DB, 스키마 분리, DB 분리 전략 비교

• 성능 최적화를 위한 캐싱 및 로드 밸런싱 적용

• 보안을 고려한 테넌트별 데이터 격리

 

Laravel의 강력한 기능을 활용하여 효과적인 멀티 테넌트 시스템을 설계해 보세요!

 

반응형