Laravel ํ์ ์ก: ๋น๋๊ธฐ ์ํคํ ์ฒ์ ๋ฉด์ ๋๋น 2026
Laravel ํ ์์คํ ์ ๋ด๋ถ ๋์, ์ก ๋ฐฐ์น ์ฒ๋ฆฌ, ์ฒด์ด๋, ์ฌ์๋ ์ ๋ต์ ์์ธํ ๋ถ์ํฉ๋๋ค. 2026๋ ๊ธฐ์ ๋ฉด์ ์์ ์ถ์ ๋๋ ํ ์ํคํ ์ฒ ํต์ฌ ๊ฐ๋ ์ ์ฒด๊ณ์ ์ผ๋ก ์ ๋ฆฌํฉ๋๋ค.

Laravel ํ๋ ์ด๋ฉ์ผ ๋ฐ์ก, ํ์ผ ์ ๋ก๋ ์ฒ๋ฆฌ, ๋ณด๊ณ ์ ์์ฑ ๋ฑ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ปค์ ์์ํ๊ธฐ ์ํ ํตํฉ API๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ฌ์ฉ์๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฒ ํ๋ ๋์ , ์ ํ๋ฆฌ์ผ์ด์ ์ ์ก์ ํ์ ํธ์ํ๊ณ ์ฆ์ ๋ค์ ์ฒ๋ฆฌ๋ก ๋์ด๊ฐ๋๋ค. ์ด ๋ฉ์ปค๋์ฆ์ ํ์ฅ ๊ฐ๋ฅํ Laravel ์ ํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ ๊ธฐ๋ฐ์ ๋๋ค.
Laravel์ ๋๋ผ์ด๋ฒ์ ๋
๋ฆฝ์ ์ธ ๋จ์ผ API๋ฅผ ํตํด ์ฌ๋ฌ ํ ๋ฐฑ์๋(Redis, Amazon SQS, ๋ฐ์ดํฐ๋ฒ ์ด์ค, Beanstalkd)๋ฅผ ์ง์ํฉ๋๋ค. ์ก์ ShouldQueue ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ง๋ ฌํ ๊ฐ๋ฅํ PHP ํด๋์ค์
๋๋ค. ์์ปค๊ฐ ํ์์ ์ก์ ๊ฐ์ ธ์ ์ญ์ง๋ ฌํํ ํ handle() ๋ฉ์๋๋ฅผ ์คํํฉ๋๋ค. ์คํจํ ์ก์ ์ ์ฉ failed_jobs ํ
์ด๋ธ์ ์ ์ฅ๋์ด ์ฌ์๋ ๋๋ ์กฐ์ฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
Laravel ์ก ๋์คํจ์น์ ๋ด๋ถ ๋์ ์๋ฆฌ
์ก ํด๋์ค์์ dispatch()๊ฐ ํธ์ถ๋๋ฉด, Laravel์ ์ก ์ธ์คํด์ค(๊ณต๊ฐ ํ๋กํผํฐ ํฌํจ)๋ฅผ ์ง๋ ฌํํ๊ณ ์ค์ ๋ ํ ์ฐ๊ฒฐ์ ํ์ด๋ก๋๋ฅผ ํธ์ํฉ๋๋ค. ์ง๋ ฌํ๋ ํ์ด๋ก๋์๋ ์ ๊ทํ๋ ํด๋์ค๋ช
, ์ง๋ ฌํ๋ ํ๋กํผํฐ, ๋์ ํ ์ด๋ฆ, ํ์ฉ๋ ์๋ ํ์ ๋ฐ ํ์์์ ๋ฑ์ ๋ฉํ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ฉ๋๋ค.
ํ ์์ปค ํ๋ก์ธ์ค(php artisan queue:work)๋ ํ ๋ฐฑ์๋์์ ์๋ก์ด ์ก์ ํด๋งํ๋ ์ฅ์๊ฐ ์คํ ๋ฐ๋ชฌ์ผ๋ก ๋์ํฉ๋๋ค. ํ์ด๋ก๋๋ฅผ ์์ ํ๋ฉด ์์ปค๋ ์ก์ ์ญ์ง๋ ฌํํ๊ณ , ์๋น์ค ์ปจํ
์ด๋๋ฅผ ํตํด ์์กด์ฑ์ ํด๊ฒฐํ ํ handle()์ ํธ์ถํฉ๋๋ค.
namespace App\Jobs;
use App\Models\Order;
use App\Services\PdfGenerator;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $backoff = 60;
public int $timeout = 120;
public function __construct(
public readonly Order $order
) {}
public function handle(PdfGenerator $pdf): void
{
// Generate PDF invoice for the order
$invoice = $pdf->generate($this->order);
// Store the generated file
$this->order->update([
'invoice_path' => $invoice->path(),
'invoiced_at' => now(),
]);
}
public function failed(\Throwable $e): void
{
// Notify the ops team when invoice generation fails
logger()->error('Invoice generation failed', [
'order_id' => $this->order->id,
'error' => $e->getMessage(),
]);
}
}SerializesModels ํธ๋ ์ดํธ๋ Eloquent ๋ชจ๋ธ ์ ์ฒด๊ฐ ์๋ ๋ชจ๋ธ์ ๊ธฐ๋ณธ ํค์ ํด๋์ค๋ช
๋ง ์ ์ฅํฉ๋๋ค. ์์ปค๊ฐ ์ก์ ์ฒ๋ฆฌํ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ต์ ๋ชจ๋ธ์ ๊ฐ์ ธ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ค๋๋ ๋ฐ์ดํฐ ์ฌ์ฉ์ ๋ฐฉ์งํ๊ณ ํ์ด๋ก๋ ํฌ๊ธฐ๋ฅผ ์๊ฒ ์ ์งํฉ๋๋ค.
๋ณ๋ ฌ ์ํฌ๋ก๋๋ฅผ ์ํ ์ก ๋ฐฐ์น ์ฒ๋ฆฌ
์ก ๋ฐฐ์น ์ฒ๋ฆฌ๋ ์ฌ๋ฌ ์ก์ ๋จ์ผ ๋ฐฐ์น๋ก ๊ทธ๋ฃนํํ๊ณ , ์ ์ฒด ์งํ ์ํฉ์ ์ถ์ ํ๋ฉฐ, ๋ชจ๋ ์ก์ด ์๋ฃ๋๋ฉด ์ฝ๋ฐฑ์ ์คํํฉ๋๋ค. ์ด ํจํด์ ๋ฐ์ดํฐ ์ํฌํธ, ๋๋ ์๋ฆผ, ๋ณด๊ณ ์ ์์ฑ ๋ฑ ์ต์ข ๋จ๊ณ ์คํ ์ ์ ์ฌ๋ฌ ๋ ๋ฆฝ์ ์ธ ์์ ๋จ์๊ฐ ์๋ฃ๋์ด์ผ ํ๋ ์ํฉ์ ์ ํฉํฉ๋๋ค.
use App\Jobs\ImportRow;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
public function import(Request $request)
{
$rows = $this->parseCSV($request->file('data'));
// Create a batch of import jobs, one per CSV row
$batch = Bus::batch(
collect($rows)->map(fn ($row) => new ImportRow($row))
)
->then(function (Batch $batch) {
// All jobs completed successfully
Notification::send(
auth()->user(),
new ImportComplete($batch->totalJobs)
);
})
->catch(function (Batch $batch, \Throwable $e) {
// First failure in the batch
logger()->warning('Batch import partial failure', [
'batch_id' => $batch->id,
'failed' => $batch->failedJobs,
]);
})
->finally(function (Batch $batch) {
// Runs after all jobs finish (success or failure)
Cache::forget("import_lock_{$batch->id}");
})
->allowFailures()
->dispatch();
return response()->json(['batch_id' => $batch->id]);
}Laravel 12์์๋ ๋ฐฐ์น ํ์ด๋ก๋์ ํ ๋๊ธฐ ์๊ฐ๊ณผ ์์ปค ์๋ณ ์ ๋ณด๋ฅผ ํฌํจํ๋ ๋ฉํ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค. allowFailures() ๋ฉ์๋๋ ๋จ์ผ ์ก ์คํจ๊ฐ ์ ์ฒด ๋ฐฐ์น๋ฅผ ์ทจ์ํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ๋ถ๋ถ์ ์ฑ๊ณต์ด ํ์ฉ๋๋ ๋๊ท๋ชจ ์ํฌํธ์์ ๋งค์ฐ ์ค์ํ ๊ธฐ๋ฅ์
๋๋ค.
์์ฐจ ์ํฌํ๋ก์ฐ๋ฅผ ์ํ ์ก ์ฒด์ด๋
๋ฐฐ์น ์ฒ๋ฆฌ๊ฐ ๋ณ๋ ฌ ์ํฌ๋ก๋๋ฅผ ๋ด๋นํ๋ ๋ฐ๋ฉด, ์ฒด์ด๋์ ์์ฐจ์ ์คํ์ ๋ณด์ฅํฉ๋๋ค. ์ฒด์ธ ๋ด์ ๊ฐ ์ก์ ์ด์ ์ก์ด ์ฑ๊ณตํ ํ์๋ง ์คํ๋ฉ๋๋ค. ์ด๋ค ์ก์ด๋ผ๋ ์คํจํ๋ฉด ๋๋จธ์ง ์ฒด์ธ์ ์ค๋จ๋๊ณ catch ์ฝ๋ฐฑ์ด ์คํ๋ฉ๋๋ค.
use App\Jobs\ValidatePayment;
use App\Jobs\ReserveInventory;
use App\Jobs\SendConfirmation;
use App\Jobs\GenerateShippingLabel;
use Illuminate\Support\Facades\Bus;
public function processOrder(Order $order): void
{
// Each job runs only after the previous one succeeds
Bus::chain([
new ValidatePayment($order),
new ReserveInventory($order),
new GenerateShippingLabel($order),
new SendConfirmation($order),
])
->onQueue('orders')
->catch(function (\Throwable $e) use ($order) {
// Roll back the order if any step fails
$order->update(['status' => 'failed']);
logger()->error('Order chain failed', [
'order_id' => $order->id,
'step' => $e->getMessage(),
]);
})
->dispatch();
}์ฒด์ด๋์ ๋จ๊ณ์ ์์๊ฐ ์ค์ํ ๋๋ฉ์ธ ์ํฌํ๋ก์ฐ์ ์ ํฉํฉ๋๋ค. ๊ฒฐ์ ๊ฒ์ฆ์ ์ฌ๊ณ ์์ฝ ์ ์ ์๋ฃ๋์ด์ผ ํ๋ฉฐ, ๋ฐฐ์ก ๋ผ๋ฒจ์ ํ์ธ๋ ์ฌ๊ณ ์ ์์กดํฉ๋๋ค.
Laravel ๋ฉด์ ์ค๋น๊ฐ ๋์ จ๋์?
์ธํฐ๋ํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ, flashcards, ๊ธฐ์ ํ ์คํธ๋ก ์ฐ์ตํ์ธ์.
ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ํ ํ ๋ฏธ๋ค์จ์ด
ํ ๋ฏธ๋ค์จ์ด๋ ์ก ์คํ์ ๋ ์ดํธ ์ ํ, ์ค๋ณต ์ ๊ฑฐ, ์ํท ๋ธ๋ ์ด์ปค ๋ฑ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ก์ง์ผ๋ก ๋ํํฉ๋๋ค. ์ด๋ฌํ ๊ด์ฌ์ฌ๋ฅผ ๋ชจ๋ ์ก์ ๋ด์ฅํ๋ ๋์ , ๋ฏธ๋ค์จ์ด๋ฅผ ํตํด ์ก์ด ๋น์ฆ๋์ค ๋ก์ง์ ์ง์คํ ์ ์๋๋ก ํฉ๋๋ค.
namespace App\Jobs\Middleware;
use Closure;
use Illuminate\Support\Facades\RateLimiter;
class RateLimitedJob
{
public function __construct(
private string $key,
private int $maxAttempts = 10,
private int $decaySeconds = 60
) {}
public function handle(object $job, Closure $next): void
{
// Release job back to queue if rate limit exceeded
if (RateLimiter::tooManyAttempts($this->key, $this->maxAttempts)) {
$job->release($this->decaySeconds);
return;
}
RateLimiter::hit($this->key, $this->decaySeconds);
$next($job);
}
}์ก ํด๋์ค์ middleware() ๋ฉ์๋๋ฅผ ์ ์ํ์ฌ ๋ฏธ๋ค์จ์ด๋ฅผ ์ ์ฉํฉ๋๋ค:
public function middleware(): array
{
return [
new RateLimitedJob(
key: 'external-api',
maxAttempts: 30,
decaySeconds: 60
),
// Prevent duplicate jobs from running concurrently
(new WithoutOverlapping($this->apiResource->id))
->releaseAfter(300)
->expireAfter(600),
];
}WithoutOverlapping ๋ฏธ๋ค์จ์ด๋ ์์์ ์ ๊ธ์ ์ฌ์ฉํ์ฌ ํน์ ํค๋ก ์๋ณ๋๋ ์ก์ ์ธ์คํด์ค๊ฐ ํ ๋ฒ์ ํ๋๋ง ์คํ๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ๋ ์ดํธ ์ ํ๊ณผ ๊ฒฐํฉํ๋ฉด ์ค๋ณต ์ฒ๋ฆฌ์ API ์ค๋กํ๋ง์ ๋ชจ๋ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
์คํจํ ์ก ์ฒ๋ฆฌ์ ์ฌ์๋ ์ ๋ต
ํ๋ก๋์
ํ ์์คํ
์๋ ๊ฒฌ๊ณ ํ ์ฅ์ ์ฒ๋ฆฌ๊ฐ ํ์์ ์
๋๋ค. Laravel์ ์คํจํ ์ก์ ์ ์ฒด ํ์ด๋ก๋, ์์ธ ํธ๋ ์ด์ค, ์ฅ์ ๋ฅผ ๋ฐ์์ํจ ํ/์ฐ๊ฒฐ ์ ๋ณด์ ํจ๊ป failed_jobs ํ
์ด๋ธ์ ์ ์ฅํฉ๋๋ค. ๊ฐ ์ก ํด๋์ค์ failed() ๋ฉ์๋๋ ๋ชจ๋ ์ฌ์๋๊ฐ ์์ง๋ ํ ์คํ๋ฉ๋๋ค.
์ก๋ณ ์ฌ์๋ ๋์ ์ค์ ์ผ๋ก ์ธ๋ฐํ ์ ์ด๊ฐ ๊ฐ๋ฅํฉ๋๋ค:
class SyncExternalData implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 5;
// Exponential backoff: 10s, 30s, 60s, 120s, 300s
public function backoff(): array
{
return [10, 30, 60, 120, 300];
}
// Job-specific timeout
public int $timeout = 180;
// Maximum exceptions before marking as failed
public int $maxExceptions = 3;
public function retryUntil(): \DateTime
{
// Keep retrying for up to 24 hours
return now()->addHours(24);
}
public function handle(): void
{
$response = Http::timeout(30)
->retry(2, 1000)
->get('https://api.vendor.com/data');
if ($response->failed()) {
// Release back to queue with delay for transient failures
$this->release(60);
return;
}
DataSync::process($response->json());
}
public function failed(\Throwable $e): void
{
Notification::route('slack', config('services.slack.ops_channel'))
->notify(new SyncFailed($e));
}
}๋ฉด์ ์์ $tries, $maxExceptions, retryUntil()์ ์ฐจ์ด์ ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. $tries๋ ์๋ ๋ฆด๋ฆฌ์ค๋ฅผ ํฌํจํ ๋ชจ๋ ์๋๋ฅผ ์นด์ดํธํฉ๋๋ค. $maxExceptions๋ ์ฒ๋ฆฌ๋์ง ์์ ์์ธ๋ง ์นด์ดํธํฉ๋๋ค. retryUntil()์ ์๋ ํ์์ ๋ฌด๊ดํ๊ฒ ์๊ฐ ๋ฒ์๋ฅผ ์ค์ ํฉ๋๋ค.
ํ ์์ปค ๊ด๋ฆฌ์ ๋ฐฐํฌ
ํ๋ก๋์ ํ๊ฒฝ์ ํ ์์ปค์๋ ํ๋ก์ธ์ค ๊ฐ๋ , ๋ฐฐํฌ ์ ๊ทธ๋ ์ด์คํ ์ฌ์์, ๋ฆฌ์์ค ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. Supervisor๋ ์์ปค๋ฅผ ์์ ์ ์ผ๋ก ์ ์งํ๋ ํ์ค ๋๊ตฌ์ ๋๋ค.
; /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopwaitsecs=3600
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/log/worker.log
stopasgroup=true
killasgroup=true๋ฐฐํฌ ์ ์ฃผ์ ๊ณ ๋ ค์ฌํญ:
- ๊ทธ๋ ์ด์คํ ์ฌ์์:
php artisan queue:restart๋ ์์ปค์๊ฒ ํ์ฌ ์ก์ ์๋ฃํ ํ ์ฌ์์ํ๋ผ๋ ์ ํธ๋ฅผ ๋ณด๋ ๋๋ค. ๋ฐฐํฌ ์ค ์ก ์์์ ๋ฐฉ์งํฉ๋๋ค. - ์ต๋ ์๊ฐ/์ก ์:
--max-time=3600๊ณผ--max-jobs=1000์ ์์ปค ํ๋ก์ธ์ค๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ฌํ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํฉ๋๋ค. - ์ฌ๋ฆฝ ๊ฐ๊ฒฉ:
--sleep=3์ ๋น ํ๋ฅผ ๋ค์ ํด๋งํ๊ธฐ๊น์ง ์์ปค๊ฐ ๋๊ธฐํ๋ ์๊ฐ์ ์ ์ดํฉ๋๋ค. ๊ฐ์ ์ค์ด๋ฉด ์๋ต์ฑ์ด ํฅ์๋์ง๋ง ๋ฐ์ดํฐ๋ฒ ์ด์ค/Redis ๋ถํ๋ ์ฆ๊ฐํฉ๋๋ค. - ๋ค์ค ํ:
--queue=critical,default,low๋ ์ฐ์ ์์์ ๋ฐ๋ผ ํ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์์ปค๋criticalํ๋ฅผ ์์ ํ ์์งํ ํdefault๋ก ๋์ด๊ฐ๋๋ค.
Laravel 12.37์์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ ์ฐ๊ฒฐ์ด ๋์
๋์ด Concurrently::defer()๋ฅผ ์ฌ์ฉํ ์ก ์ง์ฐ ์คํ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ด ๋๋ผ์ด๋ฒ๋ ์ก์ ์ง๋ ฌํํ์ฌ ๋ณ๋์ PHP ํ๋ก์ธ์ค์์ ์คํํฉ๋๋ค. ์์ ํ ํ ์ธํ๋ผ๊ฐ ํ์ํ์ง ์์ ๊ฒฝ๋ ์ก์ ์ ํฉํฉ๋๋ค.
์ ๋ํฌ ์ก๊ณผ ์ํธํ๋ ํ์ด๋ก๋
ํ๋ก๋์ ํ๊ฒฝ๊ณผ ๋ฉด์ ์์ ์์ฃผ ๋ฑ์ฅํ๋ ๋ ๊ฐ์ง ํจํด์ด ์์ต๋๋ค. ํน์ ํค์ ๋ํด ์ก์ด ํ ๋ฒ๋ง ์คํ๋๋๋ก ๋ณด์ฅํ๋ ํจํด๊ณผ ์ก ํ์ด๋ก๋์ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ๋ ํจํด์ ๋๋ค.
use Illuminate\Contracts\Queue\ShouldBeUnique;
class RebuildSearchIndex implements ShouldQueue, ShouldBeUnique
{
// Lock duration in seconds
public int $uniqueFor = 3600;
public function __construct(
public readonly string $indexName
) {}
// Unique key scopes the lock to this specific index
public function uniqueId(): string
{
return $this->indexName;
}
public function handle(): void
{
SearchIndex::rebuild($this->indexName);
}
}๋ฏผ๊ฐํ ๋ฐ์ดํฐ(์ฌ์ฉ์ ์๊ฒฉ ์ฆ๋ช
, ๊ฒฐ์ ํ ํฐ)๋ฅผ ํฌํจํ๋ ์ก์๋ ShouldBeEncrypted ์ธํฐํ์ด์ค๊ฐ ์ง๋ ฌํ๋ ์ ์ฒด ํ์ด๋ก๋๋ฅผ ์ ์ฅ ์ ์ํธํํฉ๋๋ค:
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
class ProcessPayment implements ShouldQueue, ShouldBeEncrypted
{
public function __construct(
private string $paymentToken,
private float $amount
) {}
public function handle(PaymentGateway $gateway): void
{
$gateway->charge($this->paymentToken, $this->amount);
}
}ํ์ด๋ก๋๋ Redis๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๊ธฐ ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ํค๋ก ์ํธํ๋ฉ๋๋ค. ์์ปค๋ ์ญ์ง๋ ฌํ ์ ์ ์๋์ผ๋ก ๋ณตํธํํฉ๋๋ค.
Laravel ํ ๊ด๋ จ ๋ฉด์ ๋น์ถ ์ง๋ฌธ
๊ธฐ์ ๋ฉด์ ์์๋ ํ๋ฉด์ ์ธ API ์ง์์ ๋์ด์ ํ ์ํคํ ์ฒ ์ดํด๋๋ฅผ ํ๊ฐํฉ๋๋ค.
ํ์ ๋ฃ์ ์ก์ด ์ญ์ ๋ Eloquent ๋ชจ๋ธ์ ์ฐธ์กฐํ๋ฉด ์ด๋ป๊ฒ ๋๋๊ฐ?
SerializesModels๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์์ปค๋ ์ก ์ฒ๋ฆฌ ์ ID๋ก ๋ชจ๋ธ์ ์กฐํํฉ๋๋ค. ๋ชจ๋ธ์ด ์กด์ฌํ์ง ์์ผ๋ฉด Laravel์ ModelNotFoundException์ ๋ฐ์์ํต๋๋ค. ์ด๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋ ค๋ฉด $deleteWhenMissingModels ํ๋กํผํฐ๋ฅผ true๋ก ์ค์ ํฉ๋๋ค. ์ก์ ์คํจ ๋์ ํ์์ ์กฐ์ฉํ ์ญ์ ๋ฉ๋๋ค.
ShouldBeUnique์ WithoutOverlapping ๋ฏธ๋ค์จ์ด์ ์ฐจ์ด์ ์?
ShouldBeUnique๋ ๋์ผํ ์ ๋ํฌ ํค๋ฅผ ๊ฐ์ง ์ก์ด ์ด๋ฏธ ํ์ ์กด์ฌํ ๋ ์ก์ ๋์คํจ์น๋ฅผ ๋ฐฉ์งํฉ๋๋ค. WithoutOverlapping์ ๋์คํจ์น๋ ํ์ฉํ๋ ๋์ ์คํ์ ๋ฐฉ์งํฉ๋๋ค. ๋์ผํ ํค๋ฅผ ๊ฐ์ง ์ก์ด ์ด๋ฏธ ์คํ ์ค์ด๋ฉด ์ ์ธ์คํด์ค๋ ํ๋ก ๋๋๋ ค์ง๋๋ค. ์๋ก ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉฐ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
retryUntil()์ด $tries๋ณด๋ค ์ ํธ๋๋ ์ํฉ์?
๋ณต๊ตฌ ์๊ฐ์ ์์ธกํ ์ ์๋ ์ธ๋ถ ์๋น์ค์ ์ํธ์์ฉํ๋ ์ก์๋ retryUntil()์ ์ฌ์ฉํฉ๋๋ค. ๊ณ ์ ๋ ์ฌ์๋ ํ์($tries = 3)๋ ์งง์ ์ฅ์ ์ค์ ์๋๋ฅผ ์์งํ ์ ์์ต๋๋ค. retryUntil()์ ์๊ฐ ๋ฒ์(์: 24์๊ฐ)๋ฅผ ์ค์ ํ๊ณ ์๋น์ค๊ฐ ๋ณต๊ตฌ๋๊ฑฐ๋ ์๊ฐ์ด ๋ง๋ฃ๋ ๋๊น์ง ๋ฐฑ์คํ๋ฅผ ์ ์ฉํ๋ฉฐ ์ฌ์๋๋ฅผ ๊ณ์ํฉ๋๋ค.
๋ค์ค ํ์์ ํ ์ฐ์ ์์๋ ์ด๋ป๊ฒ ์๋ํ๋๊ฐ?
queue:work --queue=critical,default,low๋ก ์ฐ์ ์์ ์์คํ
์ ๊ตฌ์ฑํฉ๋๋ค. ์์ปค๋ critical ํ๋ฅผ ์์ ํ ์์งํ ํ default๋ฅผ ํ์ธํ๊ณ , default ํ์ low๋ฅผ ํ์ธํฉ๋๋ค. ํผํฌ ๋ถํ ์ ๋ฎ์ ์ฐ์ ์์ ์ก์ ๊ธฐ์ ์ํ์ ๋น ์ง ์ ์์ต๋๋ค. ์๊ฒฉํ SLA๊ฐ ํ์ํ ๊ฒฝ์ฐ ํ๋ณ ์ ์ฉ ์์ปค๋ฅผ ๋ฐฐ์นํ๋ ๊ฒ์ด ๋ ๋์ ๋ณด์ฅ์ ์ ๊ณตํฉ๋๋ค.
์ฐ์ต์ ์์ํ์ธ์!
๋ฉด์ ์๋ฎฌ๋ ์ดํฐ์ ๊ธฐ์ ํ ์คํธ๋ก ์ง์์ ํ ์คํธํ์ธ์.
๊ฒฐ๋ก
- Laravel ํ๋ Redis, SQS, ๋ฐ์ดํฐ๋ฒ ์ด์ค, Laravel 12.37์ ์๋ก์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฐ๊ฒฐ์ ์ง์ํ๋ ๋๋ผ์ด๋ฒ ๋ ๋ฆฝ์ API๋ก ํ ๋ฐฑ์๋๋ฅผ ์ถ์ํํฉ๋๋ค
- ์ก ๋ฐฐ์น ์ฒ๋ฆฌ๋ ์งํฉ์ ์งํ ์ํฉ ์ถ์ ์ผ๋ก ๋ณ๋ ฌ ์ํฌ๋ก๋๋ฅผ ์ฒ๋ฆฌํ๊ณ , ์ฒด์ด๋์ ๋๋ฉ์ธ ์ํฌํ๋ก์ฐ์ ์์ฐจ์ ์คํ์ ๋ณด์ฅํฉ๋๋ค
- ํ ๋ฏธ๋ค์จ์ด(๋ ์ดํธ ์ ํ,
WithoutOverlapping)๋ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ก์ ๋น์ฆ๋์ค ๋ก์ง์์ ๋ถ๋ฆฌํฉ๋๋ค - ์คํจํ ์ก ์ฒ๋ฆฌ๋
$tries,$maxExceptions,retryUntil(), ์ง์ ๋ฐฑ์คํ๋ฅผ ๊ฒฐํฉํ ๊ฒฌ๊ณ ํ ์ฌ์๋ ์ ๋ต์ ๊ตฌํํฉ๋๋ค ShouldBeUnique๋ ์ค๋ณต ๋์คํจ์น๋ฅผ ๋ฐฉ์งํ๊ณ ,ShouldBeEncrypted๋ ์ ์ฅ ์ ๋ฏผ๊ฐํ ํ์ด๋ก๋๋ฅผ ๋ณดํธํฉ๋๋ค- ํ๋ก๋์
์์ปค์๋ Supervisor, ๋ฐฐํฌ ์ ๊ทธ๋ ์ด์คํ ์ฌ์์,
--max-time๊ณผ--max-jobs๋ฅผ ํตํ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค - ๋ฉด์ ๋๋น์์๋ ๋์คํจ์น ์์ ์ ์ ์ผ์ฑ๊ณผ ์คํ ์์ ์ ์ ๊ธ ๊ตฌ๋ถ, ๋ชจ๋ธ ์ง๋ ฌํ ๋์, ํ ์ฐ์ ์์ ๊ธฐ์ ๋ฌธ์ ๋ฅผ ๋ค๋ฃจ์ด์ผ ํฉ๋๋ค
Laravel ๋ฉด์ ์ง๋ฌธ ์ค์ ์ฐ์ต์ ์ํด, SharpSkill ๋ฌธ์ ์ํ์์ ํ, ๋ฏธ๋ค์จ์ด, Eloquent ํจํด์ ๋ํ ์์ธ ํด์ค์ ์ ๊ณตํฉ๋๋ค.
์ฐ์ต์ ์์ํ์ธ์!
๋ฉด์ ์๋ฎฌ๋ ์ดํฐ์ ๊ธฐ์ ํ ์คํธ๋ก ์ง์์ ํ ์คํธํ์ธ์.
ํ๊ทธ
๊ณต์
๊ด๋ จ ๊ธฐ์ฌ

Laravel๊ณผ PHP ๋ฉด์ ์ง๋ฌธ: 2026๋ ํต์ฌ 25์
Laravel๊ณผ PHP ๋ฉด์ ์์ ๊ฐ์ฅ ์์ฃผ ์ถ์ ๋๋ 25๊ฐ์ง ์ง๋ฌธ์ ์์ธํ ๋ค๋ฃน๋๋ค. Eloquent ORM, ๋ฏธ๋ค์จ์ด, ํ, ํ ์คํธ, ์ํคํ ์ฒ ํจํด์ ๋ํ ์์ธํ ๋ต๋ณ๊ณผ ์ฝ๋ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.

Laravel Middleware ์๋ฒฝ ๊ฐ์ด๋: ์ธ์ฆ, ์๋ ์ ํ, ์ปค์คํ ๋ฏธ๋ค์จ์ด ๊ตฌ์ถ
Laravel ๋ฏธ๋ค์จ์ด์ ํ์ดํ๋ผ์ธ ๊ตฌ์กฐ๋ถํฐ ์ธ์ฆ, ์๋ ์ ํ(Rate Limiting), ์ปค์คํ ๋ฏธ๋ค์จ์ด ์์ฑ, ํ๋ก๋์ ํจํด๊น์ง ์ค๋ฌด ์ฝ๋ ์์ ์ ํจ๊ป ์ฒด๊ณ์ ์ผ๋ก ์ ๋ฆฌํฉ๋๋ค.

Eloquent ORM: Laravel๋ฅผ ์ํ ํจํด๊ณผ ์ต์ ํ
๊ณ ๊ธ ํจํด๊ณผ ์ต์ ํ ๊ธฐ๋ฒ์ผ๋ก Eloquent ORM์ ๋ง์คํฐํฉ๋๋ค. Laravel ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ eager loading, query scope, accessor, mutator ๋ฐ ์ฑ๋ฅ.