본문 바로가기

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의 강력한 기능을 활용하여 효과적인 멀티 테넌트 시스템을 설계해 보세요!

 

반응형