> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 이미지 가공

> Laravel의 Image 파사드를 사용하여 이미지의 리사이즈·크롭·변환·저장을 하는 방법을 설명합니다.

## 시작하기

Laravel은 `Image` 파사드를 통해 유창한 이미지 가공 API를 제공합니다. 리사이즈·크롭·인코드·저장 등의 조작을 프레임워크 전반에 걸쳐 일관된 표현 방식으로 작성할 수 있습니다.

내부적으로는 [Intervention Image](https://image.intervention.io/)를 이용하며, PHP의 GD 확장과 Imagick 확장을 모두 지원합니다.

```php theme={null}
use Illuminate\Support\Facades\Image;

$path = Image::fromStorage('avatars/photo.jpg', 'public')
    ->cover(400, 400)
    ->toWebp()
    ->quality(80)
    ->storePublicly('avatars', 'public');
```

<Warning>
  이미지 처리는 CPU와 메모리를 대량으로 소비할 수 있습니다. 대규모 이미지 처리는 HTTP 요청 중에 하지 말고 [큐 잡](/ko/queues)으로 처리하는 것을 검토하세요.
</Warning>

<Info>
  이 기능은 **Laravel v13.20.0 이상**에서 이용할 수 있습니다. 이전 버전을 사용하는 경우 `composer update`로 프레임워크를 최신판으로 업데이트하세요.
</Info>

## 설치

이미지 가공 기능을 사용하기 전에 Composer로 Intervention Image 패키지를 설치합니다.

```shell theme={null}
composer require intervention/image:^4.0
```

또한 사용하는 드라이버에 따라 PHP의 GD 확장 또는 Imagick 확장이 설치되어 있는지 확인하세요.

### 설정

설정 파일은 `config/image.php`에 배치됩니다. 설정 파일이 존재하지 않는 경우 Artisan 명령으로 배포합니다.

```shell theme={null}
php artisan config:publish image
```

기본 드라이버는 설정 파일 또는 환경 변수 `IMAGE_DRIVER`로 지정할 수 있습니다. 지원되는 드라이버는 `gd`와 `imagick`입니다.

```ini theme={null}
IMAGE_DRIVER=imagick
```

## 이미지 로드

`Image` 파사드는 다양한 소스에서 이미지 인스턴스를 생성하는 메서드를 제공합니다. 이미지 내용은 지연 로드되므로, 처리 또는 바이트열의 요구가 있을 때까지 실제로는 로드되지 않습니다.

### 업로드 파일

요청에서 업로드된 이미지를 취득하려면 `image` 메서드를 사용합니다. 파일이 존재하지 않는 경우 `null`을 반환합니다.

```php theme={null}
use Illuminate\Http\Request;

Route::post('/avatar', function (Request $request) {
    $request->validate(['avatar' => ['required', 'image']]);

    $path = $request->image('avatar')
        ->cover(400, 400)
        ->toWebp()
        ->storePublicly('avatars', 'public');

    // ...
});
```

`UploadedFile` 인스턴스에서 생성할 경우 `fromUpload` 메서드를 사용합니다.

```php theme={null}
use Illuminate\Support\Facades\Image;

$image = Image::fromUpload($request->file('avatar'));
```

업로드 파일에서 생성한 이미지 인스턴스는 `file` 메서드로 원본 파일을 취득할 수 있습니다.

```php theme={null}
$file = $image->file();
```

### 스토리지 파일

[파일시스템 디스크](/ko/filesystem)에 저장된 파일에서 이미지 인스턴스를 생성하려면 `fromStorage` 메서드를 사용합니다. 첫 번째 인수는 파일 경로, 두 번째 인수는 디스크명입니다.

```php theme={null}
use Illuminate\Support\Facades\Image;

$image = Image::fromStorage('avatars/photo.jpg', disk: 'public');
```

Storage 파사드의 `image` 메서드에서도 생성할 수 있습니다.

```php theme={null}
use Illuminate\Support\Facades\Storage;

$image = Storage::disk('public')->image('avatars/photo.jpg');
```

### 그 외 소스

바이트열·로컬 경로·URL·Base64에서도 이미지 인스턴스를 생성할 수 있습니다.

```php theme={null}
use Illuminate\Support\Facades\Image;

$image = Image::fromBytes($contents);
$image = Image::fromBase64($base64);
$image = Image::fromPath(storage_path('app/avatars/photo.jpg'));
$image = Image::fromUrl('https://example.com/photo.jpg');
```

## 이미지 가공

이미지 인스턴스는 불변입니다. 각 메서드는 변환을 처리 파이프라인에 추가한 새 인스턴스를 반환하므로 메서드 체인으로 작성할 수 있습니다. 변환은 파이프라인에 추가된 순으로 처리되며, 인코딩은 마지막에 한 번만 수행됩니다.

```php theme={null}
$image = $request->image('avatar')
    ->orient()
    ->cover(400, 400)
    ->sharpen(10);
```

### 리사이즈

| 메서드                 | 설명                                          |
| ------------------- | ------------------------------------------- |
| `resize(800, 600)`  | 지정 크기로 리사이즈. 너비 또는 높이만 지정 가능                |
| `scale(800, 600)`   | 비율을 유지하면서 지정 크기 내에 들어가도록 축소. 확대는 하지 않음      |
| `cover(400, 400)`   | 지정 크기를 완전히 덮도록 리사이즈 + 크롭                    |
| `contain(400, 400)` | 비율을 유지하면서 지정 크기 내에 들어가도록 리사이즈. 여백은 배경색으로 채움 |
| `crop(300, 200)`    | 지정 크기로 크롭. `x`·`y` 좌표도 지정 가능                |

```php theme={null}
$image = $image->resize(800, 600);
$image = $image->resize(width: 800);       // 너비만
$image = $image->scale(800, 600);
$image = $image->cover(400, 400);
$image = $image->contain(400, 400, '#ffffff');
$image = $image->crop(300, 200, x: 50, y: 25);
```

### 그 외 변환

```php theme={null}
$image = $image->orient();            // EXIF의 방향 정보에 따라 회전
$image = $image->rotate(90);          // 시계 방향으로 90° 회전
$image = $image->rotate(90, '#ffffff'); // 배경색을 지정하여 회전
$image = $image->blur(5);             // 블러 (0~100)
$image = $image->grayscale();         // 그레이스케일
$image = $image->sharpen(10);         // 샤픈 (0~100)
$image = $image->flipVertically();    // 상하 반전
$image = $image->flipHorizontally();  // 좌우 반전
```

### 조건부 변환

이미지 인스턴스는 `Conditionable` 트레이트를 지원하며, `when` / `unless`로 조건부 변환이 가능합니다.

```php theme={null}
$image = $request->image('avatar')
    ->when($request->boolean('crop'), fn ($image) => $image->cover(400, 400))
    ->unless($request->boolean('preserve_format'), fn ($image) => $image->toWebp());
```

## 인코딩

기본적으로는 원본 포맷으로 인코딩됩니다. 포맷을 변환하려면 다음 메서드를 사용합니다.

```php theme={null}
$image = $image->toWebp();
$image = $image->toJpg();
$image = $image->toJpeg();
```

`quality` 메서드로 출력 품질(1\~100)을 설정할 수 있습니다.

```php theme={null}
$image = $image->toWebp()->quality(80);
```

`optimize` 메서드는 포맷 변환과 품질 설정의 단축키입니다. 기본값은 WebP·품질 70입니다.

```php theme={null}
$image = $image->optimize();
$image = $image->optimize(format: 'jpg', quality: 85);
```

바이트열·Base64·Data URI로도 취득할 수 있습니다.

```php theme={null}
$bytes   = $image->toBytes();
$base64  = $image->toBase64();
$dataUri = $image->toDataUri();
$bytes   = (string) $image; // 문자열 캐스트
```

## 저장

`store` 메서드로 이미지를 파일시스템 디스크에 저장합니다. Laravel은 고유한 파일 이름을 자동 생성하고 저장 경로를 반환합니다.

```php theme={null}
$path = $request->image('avatar')
    ->cover(400, 400)
    ->store(path: 'avatars');

$path = $request->image('avatar')
    ->cover(400, 400)
    ->store(path: 'avatars', disk: 's3');
```

파일 이름을 지정할 경우 `storeAs`를 사용합니다.

```php theme={null}
$path = $request->image('avatar')
    ->cover(400, 400)
    ->storeAs(path: 'avatars', name: 'avatar.jpg', disk: 'public');
```

`public` 가시성으로 저장할 경우 `storePublicly` / `storePubliclyAs`를 사용합니다.

```php theme={null}
$path = $request->image('avatar')
    ->cover(400, 400)
    ->storePublicly(path: 'avatars', disk: 'public');

$path = $request->image('avatar')
    ->cover(400, 400)
    ->storePubliclyAs(path: 'avatars', name: 'avatar.webp', disk: 'public');
```

저장에 실패한 경우 `false`를 반환합니다.

## 이미지 정보 취득

`mimeType`·`extension`·`dimensions`·`width`·`height` 메서드로 이미지의 정보를 취득할 수 있습니다. 이 메서드들은 처리 후의 이미지를 대상으로 합니다(예: `cover(400, 400)` 후 `width()`를 호출하면 `400`을 반환합니다).

```php theme={null}
$mimeType = $image->mimeType();
$extension = $image->extension();

[$width, $height] = $image->dimensions();
$width  = $image->width();
$height = $image->height();
```

## 커스텀 드라이버

Laravel의 이미지 매니저는 `Illuminate\Support\Manager`를 상속하고 있으며, `extend` 메서드로 커스텀 드라이버를 등록할 수 있습니다.

커스텀 드라이버는 `Illuminate\Contracts\Image\Driver` 인터페이스를 구현하고, `process` 메서드로 원본 이미지 바이트열과 파이프라인을 받아 처리된 이미지 바이트열을 반환합니다.

```php theme={null}
<?php

namespace App\Images;

use Illuminate\Contracts\Image\Driver;
use Illuminate\Image\ImagePipeline;

class VipsDriver implements Driver
{
    public function process(string $contents, ImagePipeline $pipeline): string
    {
        // 파이프라인의 변환과 출력 옵션을 적용...
        return $contents;
    }

    public function transformUsing(string $transformation, callable $callback): static
    {
        // 핸들러를 저장하여 처리 중에 적용할 수 있도록 함...
        return $this;
    }
}
```

등록은 서비스 프로바이더의 `boot` 메서드에서 수행합니다.

```php theme={null}
use App\Images\VipsDriver;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Image;

public function boot(): void
{
    Image::extend('vips', function (Application $app) {
        return new VipsDriver;
    });
}
```

특정 이미지에 대해 드라이버를 지정하려면 `using` 메서드를 사용합니다.

```php theme={null}
$image = $request->image('avatar')
    ->using('vips')
    ->cover(400, 400);
```

## 커스텀 변환

`Illuminate\Contracts\Image\Transformation` 인터페이스를 구현한 클래스로 커스텀 변환을 정의할 수 있습니다.

```php theme={null}
<?php

namespace App\Images\Transformations;

use Illuminate\Contracts\Image\Transformation;

class Pixelate implements Transformation
{
    public function __construct(
        public readonly int $size,
    ) {}
}
```

핸들러 등록은 서비스 프로바이더의 `boot` 메서드에서 수행합니다.

```php theme={null}
use App\Images\Transformations\Pixelate;
use Illuminate\Support\Facades\Image;
use Intervention\Image\Interfaces\ImageInterface;

Image::transformUsing('gd', Pixelate::class, function (ImageInterface $image, Pixelate $transformation) {
    return $image->pixelate($transformation->size);
});
```

등록 후에는 `transform` 메서드로 적용합니다.

```php theme={null}
use App\Images\Transformations\Pixelate;

$image = $request->image('avatar')
    ->transform(new Pixelate(12))
    ->store('avatars');
```


## Related topics

- [Laravel AI SDK](/ko/ai-sdk.md)
- [검증(Verify)](/ko/packages/laravel-bluesky/verify.md)
- [Laravel AI SDK용 Amazon Bedrock 드라이버](/ko/packages/laravel-amazon-bedrock.md)
- [Laravel Sail](/ko/sail.md)
- [알림 채널 - LINE SDK for Laravel](/ko/packages/laravel-line-sdk/notification.md)
