로깅이란
Laravel의 로깅은 채널 이라는 개념을 축으로 설계되어 있습니다.
채널이란 로그의 쓰기 대상과 방법을 정의한 설정 단위로, 파일, Slack, syslog 등 다양한 출력 대상을 조합할 수 있습니다.
내부적으로 Monolog 라이브러리를 사용하고 있어 풍부한 핸들러와 포매터를 활용할 수 있습니다.
기본적으로 stack 채널이 사용됩니다. stack은 여러 채널을 통합해서 다루는 부모 채널입니다.
로깅 설정은 config/logging.php에 집중되어 있습니다. 환경 변수 LOG_CHANNEL로 기본 채널을 전환합니다.
// config/logging.php
'default' => env ( 'LOG_CHANNEL' , 'stack' ),
이용 가능한 채널 드라이버
드라이버 설명 single하나의 파일에 모든 로그를 기록 daily날짜별로 파일을 나누어 기록(로테이션 포함) slackSlack의 Incoming Webhook로 메시지 전송 stack여러 채널을 통합하는 부모 채널 syslog시스템 syslog에 기록 errorlogPHP 오류 로그에 기록 monologMonolog의 핸들러를 직접 지정 custom팩토리 클래스로 채널을 완전히 커스터마이징
로그 레벨
Laravel은 RFC 5424 에 정의된 8단계 로그 레벨을 지원합니다.
심각도가 높은 순으로 나열되어 있습니다.
레벨 용도 예 emergency시스템 전체가 사용 불가. 즉시 대응 필요 alert즉시 사람이 대응해야 하는 상태(DB 접속 끊김 등) critical앱의 주요 기능이 멈춘 중대한 장애 error런타임 오류. 대응이 필요하지만 즉시는 아닌 경우도 많다 warning잠재적 문제. 지원 중단 API 사용, 예기치 않은 데이터 등 notice정상 동작이지만 주목할 만한 정보 info사용자 로그인이나 주문 확정 등 일반적인 조작 로그 debug개발 중의 상세 디버깅 정보
채널의 level 설정은 최저 로그 레벨 을 의미합니다.
예를 들어 level이 error라면 error 이상(critical, alert, emergency)만 기록됩니다.
기본 사용법
Log 파사드
Illuminate\Support\Facades\Log 파사드를 사용해 각 레벨의 메시지를 기록합니다.
use Illuminate\Support\Facades\ Log ;
Log :: emergency ( '시스템이 정지했습니다.' );
Log :: alert ( '데이터베이스 접속이 끊어졌습니다.' );
Log :: critical ( '결제 서비스가 응답하지 않습니다.' );
Log :: error ( '사용자 데이터 갱신에 실패했습니다.' );
Log :: warning ( '지원 중단된 메서드가 호출되었습니다.' );
Log :: notice ( '설정 파일이 재로드되었습니다.' );
Log :: info ( '사용자가 로그인했습니다.' );
Log :: debug ( '쿼리 실행 시간: 42ms' );
컨트롤러에서의 사용 예시입니다.
<? php
namespace App\Http\Controllers ;
use App\Models\ User ;
use Illuminate\Support\Facades\ Log ;
use Illuminate\View\ View ;
class UserController extends Controller
{
public function show ( string $id ) : View
{
Log :: info ( '사용자 프로필을 표시합니다.' , [ 'user_id' => $id ]);
return view ( 'user.profile' , [
'user' => User :: findOrFail ( $id ),
]);
}
}
log() 헬퍼 함수
log() 헬퍼를 사용하면 Log 파사드를 import하지 않고 작성할 수 있습니다.
log ( '헬퍼로부터의 로그입니다.' );
// 레벨과 컨텍스트도 지정할 수 있습니다
log ( '사용자를 생성했습니다.' , 'info' , [ 'user_id' => $user -> id ]);
컨텍스트 정보 추가
메시지와 함께 컨텍스트(배열)를 전달하면 관련 정보를 함께 기록할 수 있습니다.
Log :: info ( '로그인 실패.' , [
'user_id' => $user -> id ,
'ip' => $request -> ip (),
'reason' => '비밀번호 불일치' ,
]);
withContext() — 채널 전체에 공통 컨텍스트 부여
특정 채널에 대해 이후 모든 로그 엔트리에 공통 정보를 부여하고 싶은 경우에는 withContext()를 사용합니다.
요청 ID처럼 모든 로그에 포함하고 싶은 정보에 적합합니다.
Log :: withContext ([ 'request-id' => ( string ) Str :: uuid ()]);
// 이후 모든 로그에 request-id가 자동으로 포함된다
Log :: info ( '처리를 시작합니다.' );
Log :: error ( '오류가 발생했습니다.' );
shareContext() — 모든 채널에 공통 컨텍스트 부여
withContext()는 대상 채널에만 효과가 한정되지만, shareContext()는 모든 채널에 공통 컨텍스트를 부여합니다.
Log :: shareContext ([ 'app-version' => config ( 'app.version' )]);
채널 설정
stack 채널 — 여러 채널에 동시 기록
stack 채널을 사용하면 한 번의 로그 호출로 여러 채널에 기록할 수 있습니다.
// config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack' ,
'channels' => [ 'daily' , 'slack' ],
],
'daily' => [
'driver' => 'daily' ,
'path' => storage_path ( 'logs/laravel.log' ),
'level' => env ( 'LOG_LEVEL' , 'debug' ),
'days' => 14 ,
],
'slack' => [
'driver' => 'slack' ,
'url' => env ( 'LOG_SLACK_WEBHOOK_URL' ),
'username' => env ( 'LOG_SLACK_USERNAME' , 'Laravel Log' ),
'emoji' => env ( 'LOG_SLACK_EMOJI' , ':boom:' ),
'level' => 'critical' ,
],
],
이 설정에서는 debug 이상의 모든 로그가 daily(파일)에 기록되고, critical 이상만 slack에도 전송됩니다.
프로덕션 환경에서는 slack 채널의 레벨을 error나 critical로 설정하는 것을 권장합니다.
경미한 로그까지 Slack으로 보내면 알림이 대량이 되어 중요한 알람이 파묻힙니다.
daily 채널 — 로그 로테이션
daily 채널은 날짜별로 파일을 나누고 오래된 파일을 자동 삭제합니다.
'daily' => [
'driver' => 'daily' ,
'path' => storage_path ( 'logs/laravel.log' ),
'level' => env ( 'LOG_LEVEL' , 'debug' ),
'days' => env ( 'LOG_DAILY_DAYS' , 14 ), // 14일분 유지
],
days를 작게 하면 오래된 로그가 빨리 삭제됩니다.
프로덕션 환경의 장애 조사에 대비해 충분한 보존 기간을 확보해 주세요.
Slack으로의 오류 알림
Slack의 Incoming Webhook URL 을 획득하고, .env에 설정합니다.
LOG_SLACK_WEBHOOK_URL =https://hooks.slack.com/services/xxx/yyy/zzz
// config/logging.php
'slack' => [
'driver' => 'slack' ,
'url' => env ( 'LOG_SLACK_WEBHOOK_URL' ),
'username' => 'Laravel Error Bot' ,
'emoji' => ':fire:' ,
'level' => 'error' ,
],
stack 채널에 slack을 포함시키고 LOG_CHANNEL=stack을 설정하면 오류 발생 시 자동으로 알림이 갑니다.
특정 채널에 로그 기록
Log::channel()로 대상 채널을 명시적으로 지정할 수 있습니다.
// slack 채널에만 기록
Log :: channel ( 'slack' ) -> error ( '결제 서비스가 응답하지 않습니다.' );
// 여러 채널에 동시 기록
Log :: stack ([ 'daily' , 'slack' ]) -> critical ( '데이터베이스 접속에 실패했습니다.' );
온디맨드 채널
Log::build()를 사용하면 설정 파일에 정의하지 않고 즉석에서 커스텀 채널을 만들 수 있습니다.
테스트나 일시적인 출력 대상으로의 기록에 편리합니다.
use Illuminate\Support\Facades\ Log ;
$channel = Log :: build ([
'driver' => 'single' ,
'path' => storage_path ( 'logs/import-' . now () -> format ( 'Ymd' ) . '.log' ),
]);
Log :: stack ([ $channel ]) -> info ( 'CSV 임포트를 시작합니다.' );
실전 유스케이스
미들웨어에서 요청 ID 부여하기
모든 로그에 공통 요청 ID를 부여하면 로그에서 특정 요청의 흐름을 추적하기 쉬워집니다.
미들웨어를 생성한다
php artisan make:middleware AssignRequestId
handle() 메서드를 구현한다
<? php
namespace App\Http\Middleware ;
use Closure ;
use Illuminate\Http\ Request ;
use Illuminate\Support\Facades\ Log ;
use Illuminate\Support\ Str ;
use Symfony\Component\HttpFoundation\ Response ;
class AssignRequestId
{
public function handle ( Request $request , Closure $next ) : Response
{
$requestId = ( string ) Str :: uuid ();
Log :: withContext ([ 'request-id' => $requestId ]);
$response = $next ( $request );
$response -> headers -> set ( 'X-Request-Id' , $requestId );
return $response ;
}
}
미들웨어를 등록한다
bootstrap/app.php에서 글로벌 미들웨어로 등록합니다.-> withMiddleware ( function ( Middleware $middleware ) {
$middleware -> append ( \App\Http\Middleware\ AssignRequestId :: class );
})
이 설정 후 모든 로그에 request-id가 자동으로 부여됩니다.
[2026-03-01 12:00:00] local.INFO: 사용자가 로그인했습니다. {"request-id":"550e8400-...","user_id":1}
[2026-03-01 12:00:00] local.INFO: 대시보드를 표시합니다. {"request-id":"550e8400-..."}
지원 중단 경고의 로그 기록
PHP나 Laravel의 지원 중단 기능을 사용했을 때의 경고를 로그에 남길 수 있습니다.
// config/logging.php
'deprecations' => [
'channel' => env ( 'LOG_DEPRECATIONS_CHANNEL' , 'null' ),
'trace' => env ( 'LOG_DEPRECATIONS_TRACE' , false ),
],
.env에서 채널을 지정합니다.
LOG_DEPRECATIONS_CHANNEL =daily
Laravel Pail — 실시간 로그 감시
Laravel Pail 은 터미널에서 애플리케이션의 로그를 실시간으로 확인할 수 있는 개발 도구입니다.
Pail의 실행에는 PHP의 PCNTL 확장이 필요합니다.
composer require --dev laravel/pail
기본 사용법
# 로그를 흘려보며 확인한다
php artisan pail
# 상세 표시(생략 없음)
php artisan pail -v
# 스택 트레이스도 표시
php artisan pail -vv
로그 필터링
# 키워드로 좁히기
php artisan pail --filter= "QueryException"
# 메시지만으로 좁히기
php artisan pail --message= "로그인"
# 로그 레벨로 좁히기
php artisan pail --level=error
# 특정 사용자의 로그만 표시
php artisan pail --user=1
레벨 사용 타이밍 emergency시스템 전체가 정지할 정도의 치명적인 장애 alert즉시 사람이 개입해야 하는 상태 critical주요 기능이 동작하지 않는 중대한 장애 error예기치 않은 런타임 오류. 대응이 필요 warning지원 중단된 사용이나 예기치 않은 데이터 등 주의해야 할 상태 notice정상이지만 기록해 두고 싶은 중요한 조작 info사용자 조작이나 비즈니스 이벤트 기록 debug개발 중의 상세 디버깅 정보(프로덕션에서는 불필요)
개발 환경 : single이나 daily로 파일에 기록
프로덕션 환경 : stack으로 daily(파일 저장)와 slack(오류 알림)을 조합
특정 처리의 로그 : Log::build()로 온디맨드 채널을 생성해 독립된 파일에 기록
실시간 감시 : php artisan pail로 터미널에서 확인
debug 로그에는 기밀 정보가 포함되는 경우가 있습니다. 프로덕션 환경에서는 LOG_LEVEL=error 이상을 권장합니다.
로그 파일은 정기적으로 로테이션해서 디스크를 압박하지 않도록 해 주세요(daily 채널의 days 설정).
Slack 같은 외부 서비스로의 알림은 레이트 리밋에 주의해 주세요. 중대한 오류만 알리도록 레벨을 설정해 주세요.