"Laravel 데이터베이스: 시작하기"의 두 판 사이의 차이

365번째 줄: 365번째 줄:


==데이터베이스 CLI 연결==
==데이터베이스 CLI 연결==
데이터베이스의 CLI에 연결하기 위해 <code>db</code> Artisan 명령어를 사용할 수 있습니다:
<syntaxhighlight lang='bash'>
php artisan db
</syntaxhighlight>
필요한 경우, 기본 연결이 아닌 다른 데이터베이스 연결에 연결하기 위해 데이터베이스 연결 이름을 지정할 수 있습니다:
<syntaxhighlight lang='bash'>
php artisan db mysql
</syntaxhighlight>


==데이터베이스 검사==
==데이터베이스 검사==
==데이터베이스 모니터링==
==데이터베이스 모니터링==

2024년 6월 27일 (목) 19:32 판

1 개요

Database: Getting Started
데이터베이스: 시작하기

https://laravel.com/docs/11.x/database

Crystal Clear action info.png 작성 중인 문서입니다.

2 소개

거의 모든 최신 웹 애플리케이션은 데이터베이스와 상호작용합니다. Laravel은 원시 SQL, 유창한 쿼리 빌더, Eloquent ORM을 사용하여 지원되는 다양한 데이터베이스에서 데이터베이스와의 상호작용을 매우 간단하게 만듭니다 . 현재 Laravel은 5개의 데이터베이스에 대한 퍼스트파티 지원을 제공합니다:

2.1 설정

Laravel의 데이터베이스 서비스 설정은 애플리케이션의 config/database.php 설정 파일에 있습니다. 이 파일에서 모든 데이터베이스 연결을 정의하고, 기본적으로 사용할 연결을 지정할 수 있습니다. 이 파일 내 대부분의 설정 옵션은 애플리케이션의 환경변수 값에 의해 결정됩니다. Laravel에서 지원하는 대부분의 데이터베이스 시스템에 대한 예제도 이 파일에 제공됩니다.

기본적으로 Laravel의 샘플 환경 설정은 로컬 머신에서 Laravel 애플리케이션을 개발하기 위한 Docker 구성인 Laravel Sail과 함께 사용할 준비가 되어 있습니다. 그러나 로컬 데이터베이스에 맞게 데이터베이스 설정을 자유롭게 수정할 수 있습니다.

SQLite 설정

SQLite 데이터베이스는 파일시스템 내의 단일 파일에 포함됩니다. 터미널에서 touch 명령어를 사용하여 새로운 SQLite 데이터베이스를 만들 수 있습니다: touch database/database.sqlite. 데이터베이스를 생성한 후에는 환경변수를 설정하여 이 데이터베이스를 가리키도록 할 수 있습니다. DB_DATABASE 환경변수에 데이터베이스의 절대 경로를 지정하면 됩니다:

DB_CONNECTION=sqlite
DB_DATABASE=/절대/경로/데이터베이스.sqlite

기본적으로 외래키 제약조건은 SQLite 연결에 대해 활성화되어 있습니다. 이를 비활성화하려면 DB_FOREIGN_KEYS 환경변수를 false로 설정해야 합니다:

DB_FOREIGN_KEYS=false

Note

Laravel 인스톨러를 사용하여 Laravel 애플리케이션을 생성하고 데이터베이스로 SQLite를 선택하면, Laravel은 자동으로 database/database.sqlite 파일을 생성하고 기본 데이터베이스 마이그레이션을 실행합니다.

Microsoft SQL Server 설정

Microsoft SQL Server 데이터베이스를 사용하려면 sqlsrvpdo_sqlsrv PHP 확장과 Microsoft SQL ODBC 드라이버와 같은 필요한 의존성이 설치되어 있는지 확인해야 합니다.

URL을 사용한 설정

일반적으로 데이터베이스 연결은 host, database, username, password 등 여러 설정 값을 사용하여 설정됩니다. 이러한 각 설정 값에는 해당하는 환경변수가 있습니다. 이는 프로덕션 서버에서 데이터베이스 연결 정보를 구성할 때 여러 환경변수를 관리해야 함을 의미합니다.

AWS 및 Heroku와 같은 일부 관리형 데이터베이스 제공업체는 데이터베이스의 모든 연결 정보를 단일 문자열로 포함하는 단일 데이터베이스 "URL"을 제공합니다. 예제 데이터베이스 URL은 다음과 같이 생겼을 수 있습니다:

mysql://root:password@127.0.0.1/forge?charset=UTF-8

이러한 URL은 일반적으로 표준 스키마 규칙을 따릅니다:

driver://username:password@host:port/database?options

편의를 위해, Laravel은 여러 설정 옵션으로 데이터베이스를 설정하는 대신 이러한 URL을 지원합니다. url(또는 해당하는 DB_URL 환경변수) 설정 옵션이 있으면, 데이터베이스 연결 및 자격증명 정보를 추출하는 데 사용됩니다.

2.2 읽기와 쓰기 연결

때로는 SELECT 문을 위해 하나의 데이터베이스 연결을 사용하고, INSERT, UPDATE, DELETE 문을 위해 다른 연결을 사용하고 싶을 때가 있습니다. Laravel에서는 이를 손쉽게 처리할 수 있으며, raw 쿼리, 쿼리 빌더, Eloquent ORM을 사용하는지에 관계없이 적절한 연결이 항상 사용됩니다.

읽기/쓰기 연결을 어떻게 설정해야 하는지 예제를 통해 살펴보겠습니다:

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '196.168.1.2',
        ],
    ],
    'write' => [
        'host' => [
            '196.168.1.3',
        ],
    ],
    'sticky' => true,
 
    'database' => env('DB_DATABASE', 'laravel'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => env('DB_CHARSET', 'utf8mb4'),
    'collation' => env('DB_COLLATION', 'utf8mb4_0900_ai_ci'),
    'prefix' => '',
    'prefix_indexes' => true,
    'strict' => true,
    'engine' => null,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ]) : [],
],

설정 배열에는 세 개의 키가 추가된 것을 볼 수 있습니다: read, write, sticky. readwrite 키는 배열 값을 가지며, 단일 키인 host를 포함합니다. 읽기 및 쓰기 연결을 위한 나머지 데이터베이스 옵션은 기본 mysql 설정 배열에서 병합됩니다.

기본 mysql 배열의 값을 재정의하려는 경우에만 readwrite 배열에 항목을 배치하면 됩니다. 따라서 이 경우 "읽기" 연결을 위한 호스트로 192.168.1.1이 사용되고, "쓰기" 연결을 위한 호스트로 192.168.1.3이 사용됩니다. 데이터베이스 자격증명, 접두어, 문자 세트, 기본 mysql 배열의 모든 다른 옵션은 두 연결 모두에 걸쳐 공유됩니다. 호스트 설정 배열에 여러 값이 있는 경우 각 요청에 대해 데이터베이스 호스트가 무작위로 선택됩니다.

sticky 옵션

sticky 옵션은 현재 요청 사이클 동안 데이터베이스에 기록된 레코드를 즉시 읽을 수 있도록 허용하는 선택적 값입니다. sticky 옵션이 활성화되고 현재 요청 사이클 동안 데이터베이스에 대해 "쓰기" 작업이 수행된 경우, 이후의 모든 "읽기" 작업은 "쓰기" 연결을 사용합니다. 이를 통해 요청 사이클 동안 데이터베이스에 기록된 데이터를 즉시 다시 읽을 수 있습니다. 이것이 애플리케이션에 필요한 동작인지 여부는 사용자가 결정해야 합니다.

3 SQL 쿼리 실행

데이터베이스 연결을 설정한 후에는, DB 파사드를 사용하여 쿼리를 실행할 수 있습니다. DB 파사드는 각 유형의 쿼리에 대한 메소드를 제공합니다: select, update, insert, delete, statement.

SELECT 쿼리 실행

기본 SELECT 쿼리를 실행하려면 DB 파사드의 select 메서드를 사용할 수 있습니다:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * 애플리케이션의 모든 사용자의 목록을 보여줍니다.
     */
    public function index(): View
    {
        $users = DB::select('select * from users where active = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

select 메소드의 첫 번째 인수는 SQL 쿼리이며, 두 번째 인수는 쿼리에 바인딩해야 하는 매개변수 바인딩입니다. 일반적으로 이는 where 절 제약조건의 값들입니다. 매개변수 바인딩은 SQL 인젝션으로부터 보호를 제공합니다.

select 메소드는 항상 결과 배열을 반환합니다. 배열 내 각 결과는 데이터베이스의 레코드를 나타내는 PHP stdClass 객체입니다:

use Illuminate\Support\Facades\DB;

$users = DB::select('select * from users');

foreach ($users as $user) {
    echo $user->name;
}
스칼라 값 선택

때때로 데이터베이스 쿼리는 단일 스칼라 값으로 결과가 나올 수 있습니다. 레코드 객체에서 쿼리의 스칼라 결과를 가져올 필요 없이 Laravel은 scalar 메소드를 사용하여 이 값을 직접 가져올 수 있습니다:

$burgers = DB::scalar(
    "select count(case when food = 'burger' then 1 end) as burgers from menu"
);
여러 결과 집합 선택

애플리케이션이 여러 결과 집합을 반환하는 저장 프로시저를 호출하는 경우 selectResultSets 메소드를 사용하여 저장 프로시저가 반환한 모든 결과 집합을 가져올 수 있습니다:

[$options, $notifications] = DB::selectResultSets(
    "CALL get_user_options_and_notifications(?)", $request->user()->id
);
명명된 바인딩 사용

매개변수 바인딩을 나타내기 위해 ?를 사용하는 대신 명명된 바인딩을 사용하여 쿼리를 실행할 수 있습니다:

$results = DB::select('select * from users where id = :id', ['id' => 1]);
INSERT 문 실행

insert 문을 실행하려면 DB 파사드의 insert 메소드를 사용할 수 있습니다. select와 마찬가지로 이 메소드는 첫 번째 인수로 SQL 쿼리를, 두 번째 인수로 바인딩을 받습니다:

use Illuminate\Support\Facades.DB;

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Marc']);
UPDATE 문 실행

update 메소드는 기존 데이터베이스 레코드를 업데이트하는 데 사용됩니다. 이 메소드는 영향을 받은 행의 수를 반환합니다:

use Illuminate\Support\Facades\DB;

$affected = DB::update(
    'update users set votes = 100 where name = ?',
    ['Anita']
);
DELETE 문 실행

delete 메소드는 데이터베이스에서 레코드를 삭제하는 데 사용됩니다. update와 마찬가지로 이 메소드는 영향을 받은 행의 수를 반환합니다:

use Illuminate\Support\Facades\DB;

$deleted = DB::delete('delete from users');
일반 문 실행

일부 데이터베이스 문은 값을 반환하지 않습니다. 이러한 유형의 작업에 대해서는 DB 파사드의 statement 메소드를 사용할 수 있습니다:

DB::statement('drop table users');
준비되지 않은 문 실행

때때로 값 바인딩 없이 SQL 문을 실행하고 싶을 수 있습니다. DB 파사드의 unprepared 메소드를 사용하여 이를 달성할 수 있습니다:

DB::unprepared('update users set votes = 100 where name = "Dries"');

Warning

준비되지 않은 문은 매개변수를 바인딩하지 않으므로 SQL 인젝션에 취약할 수 있습니다. 준비되지 않은 문에 사용자가 제어하는 값을 절대 허용해서는 안 됩니다.

암묵적 커밋

트랜잭션 내에서 DB 파사드의 statementunprepared 메소드를 사용할 때 암묵적 커밋을 유발하는 문을 피해야 합니다. 이러한 문은 데이터베이스 엔진이 전체 트랜잭션을 간접적으로 커밋하게 하여 Laravel이 데이터베이스의 트랜잭션 수준을 인식하지 못하게 만듭니다. 이러한 문장의 예로는 데이터베이스 테이블 생성이 있습니다:

DB::unprepared('create table a (col varchar(1) null)');

암묵적 커밋을 유발하는 모든 문 목록은 MySQL 매뉴얼을 참조하십시오.

3.1 멀티 데이터베이스 연결 사용

애플리케이션에서 config/database.php 설정 파일에 여러 연결을 정의한 경우, DB 파사드에서 제공하는 connection 메소드를 통해 각 연결에 접근할 수 있습니다. connection 메소드에 전달되는 연결 이름은 config/database.php 설정 파일에 나열된 연결 중 하나와 일치해야 하며, config 헬퍼를 사용하여 런타임에 설정할 수도 있습니다:

use Illuminate\Support\Facades\DB;

$users = DB::connection('sqlite')->select(/* ... */);

연결 인스턴스의 getPdo 메소드를 사용하여 연결의 원시 PDO 인스턴스에 접근할 수 있습니다:

$pdo = DB::connection()->getPdo();

3.2 쿼리 이벤트 리스닝

애플리케이션에서 실행되는 각 SQL 쿼리에 대해 호출되는 클로저를 지정하려면 DB 파사드의 listen 메소드를 사용할 수 있습니다. 이 메소드는 쿼리 로깅이나 디버깅에 유용할 수 있습니다. 쿼리 리스너 클로저를 서비스 제공자boot 메소드에 등록할 수 있습니다:

<?php

namespace App\Providers;

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 애플리케이션 서비스를 등록합니다.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 애플리케이션 서비스를 부트스트랩합니다.
     */
    public function boot(): void
    {
        DB::listen(function (QueryExecuted $query) {
            // $query->sql;
            // $query->bindings;
            // $query->time;
        });
    }
}

boot 메소드 내부에서 DB::listen 메소드를 사용하여 쿼리 리스너 클로저를 등록합니다. 이렇게 하면 각 SQL 쿼리가 실행될 때마다 해당 클로저가 호출됩니다. 클로저 내부에서 $query->sql, $query->bindings, $query->time을 사용하여 쿼리 관련 정보를 가져올 수 있습니다.

3.3 누락 쿼리 시간 모니터링

현대 웹 애플리케이션의 일반적인 성능 병목 현상 중 하나는 데이터베이스를 쿼리하는 데 소요되는 시간입니다. 다행히도, Laravel은 단일 요청 중 데이터베이스 쿼리에 너무 많은 시간이 소요될 때 선택한 클로저 또는 콜백을 호출할 수 있습니다. 시작하려면, whenQueryingForLongerThan 메소드에 쿼리 시간 임계값(밀리초 단위)과 클로저를 제공하면 됩니다. 이 메소드는 서비스 제공자의 boot 메소드에서 호출할 수 있습니다:

<?php

namespace App\Providers;

use Illuminate\Database\Connection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Events.QueryExecuted;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 모든 애플리케이션 서비스를 등록합니다.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 모든 애플리케이션 서비스를 부트스트랩합니다.
     */
    public function boot(): void
    {
        DB::whenQueryingForLongerThan(500, function (Connection $connection, QueryExecuted $event) {
            // 개발 팀에 알림...
        });
    }
}

4 데이터베이스 트랜잭션

DB 파사드에서 제공하는 transaction 메소드를 사용하여 데이터베이스 트랜잭션 내에서 일련의 작업을 실행할 수 있습니다. 트랜잭션 클로저 내에서 예외가 발생하면 트랜잭션은 자동으로 롤백되고 예외가 다시 던져집니다. 클로저가 성공적으로 실행되면 트랜잭션은 자동으로 커밋됩니다. transaction 메소드를 사용하는 동안 수동으로 롤백하거나 커밋하는 것에 대해 걱정할 필요가 없습니다:

use Illuminate\Support\Facades\DB;
 
DB::transaction(function () {
    DB::update('update users set votes = 1');
 
    DB::delete('delete from posts');
});
데드락 처리

transaction 메소드는 데드락이 발생했을 때 트랜잭션을 재시도할 횟수를 정의하는 선택적 두 번째 인수를 허용합니다. 이 시도가 모두 소진되면 예외가 발생합니다:

use Illuminate\Support\Facades.DB;
 
DB::transaction(function () {
    DB::update('update users set votes = 1');
 
    DB::delete('delete from posts');
}, 5);
수동으로 트랜잭션 사용하기

트랜잭션을 수동으로 시작하고 롤백과 커밋을 완전히 제어하려면, DB 파사드에서 제공하는 beginTransaction 메소드를 사용할 수 있습니다:

use Illuminate\Support\Facades\DB;
 
DB::beginTransaction();

트랜잭션을 롤백하려면 rollBack 메소드를 사용할 수 있습니다:

DB::rollBack();

마지막으로, 트랜잭션을 커밋하려면 commit 메소드를 사용할 수 있습니다:

DB::commit();

Note

DB 파사드의 transaction 메소드는 쿼리 빌더Eloquent ORM 모두에 대해 트랜잭션을 제어합니다.

5 데이터베이스 CLI 연결

데이터베이스의 CLI에 연결하기 위해 db Artisan 명령어를 사용할 수 있습니다:

php artisan db

필요한 경우, 기본 연결이 아닌 다른 데이터베이스 연결에 연결하기 위해 데이터베이스 연결 이름을 지정할 수 있습니다:

php artisan db mysql

6 데이터베이스 검사

7 데이터베이스 모니터링

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}