세션이란
HTTP는 스테이트리스한 프로토콜입니다. 즉, 요청 사이에 사용자의 정보를 유지하는 구조가 HTTP 자체에는 없습니다.
Laravel의 세션 기능은 여러 요청에 걸쳐 사용자의 데이터를 유지하는 수단을 제공합니다.
로그인 상태, 카트 내 상품, 폼 입력 중 데이터 등 요청 사이에 유지하고 싶은 정보를 세션에 저장합니다.
세션 드라이버 설정
세션 설정은 config/session.php에 작성되어 있습니다.
SESSION_DRIVER 환경 변수(.env 파일)로 드라이버를 전환할 수 있습니다.
Laravel이 기본으로 지원하는 드라이버는 다음과 같습니다.
드라이버 개요 filestorage/framework/sessions에 파일로 저장(기본값)cookie암호화된 쿠키로 브라우저에 저장 database데이터베이스 테이블에 저장 redisRedis에 저장(고속) arrayPHP 배열에 저장(테스트용. 요청 사이에 유지되지 않음)
Laravel의 기본 프로젝트에서는 database 드라이버가 설정되어 있습니다. database 드라이버를 사용하는 경우 sessions 테이블이 필요하지만, 기본 마이그레이션에 포함되어 있으므로 그대로 사용할 수 있습니다.
세션 접근 방법
세션에 접근하려면 Request 인스턴스의 메서드를 사용하는 방법과 글로벌 헬퍼 session()을 사용하는 방법 두 가지가 있습니다.
Request 인스턴스를 사용하는 방법
컨트롤러의 메서드에 Request를 타입 힌트로 받고, $request->session()으로 세션에 접근합니다.
<? php
namespace App\Http\Controllers ;
use Illuminate\Http\ Request ;
use Illuminate\View\ View ;
class DashboardController extends Controller
{
public function index ( Request $request ) : View
{
$username = $request -> session () -> get ( 'username' );
return view ( 'dashboard' , [ 'username' => $username ]);
}
}
글로벌 헬퍼 session()을 사용하는 방법
session() 헬퍼 함수는 컨트롤러나 뷰 등 어디서든 호출할 수 있습니다.
// 값을 가져온다
$value = session ( 'key' );
// 기본값과 함께 가져온다
$value = session ( 'key' , '기본값' );
// 값을 저장한다
session ([ 'key' => 'value' ]);
어느 방법이든 테스트 시에 assertSessionHas 메서드로 검증할 수 있습니다. 컨트롤러 안에서는 $request->session()을 사용하면 의존 관계가 명시되어 알기 쉬워집니다.
세션 조작
데이터 가져오기
// 키를 지정해서 가져오기
$value = $request -> session () -> get ( 'key' );
// 기본값을 지정한다
$value = $request -> session () -> get ( 'key' , 'default' );
// 기본값을 클로저로 지정한다
$value = $request -> session () -> get ( 'key' , function () {
return 'default' ;
});
// 모든 세션 데이터를 가져온다
$data = $request -> session () -> all ();
데이터 존재 체크
// 값이 존재하고 null이 아닐 경우에 true
if ( $request -> session () -> has ( 'user_id' )) {
// ...
}
// null이라도 존재하면 true
if ( $request -> session () -> exists ( 'user_id' )) {
// ...
}
// 존재하지 않는 경우에 true
if ( $request -> session () -> missing ( 'user_id' )) {
// ...
}
has와 exists의 차이에 주의해 주세요.
메서드 null인 경우hasfalse를 반환existstrue를 반환
데이터 저장
// Request 인스턴스 경유
$request -> session () -> put ( 'user_name' , '김철수' );
// 글로벌 헬퍼 경유
session ([ 'user_name' => '김철수' ]);
// 배열에 추가
$request -> session () -> push ( 'cart.items' , [ 'id' => 1 , 'name' => '상품A' ]);
데이터 삭제
// 특정 키를 삭제한다
$request -> session () -> forget ( 'user_name' );
// 여러 키를 함께 삭제한다
$request -> session () -> forget ([ 'user_name' , 'cart' ]);
// 모든 세션 데이터를 삭제한다
$request -> session () -> flush ();
플래시 데이터
플래시 데이터는 다음 요청에서만 유효한 세션 데이터입니다.
폼 전송 완료 메시지나 오류 메시지 등 한 번만 표시하고 싶은 정보에 사용합니다.
flash()로 데이터 저장
$request -> session () -> flash ( 'status' , '게시물을 저장했습니다.' );
이 데이터는 다음 요청에서 참조할 수 있지만, 그 후에는 자동으로 삭제됩니다.
플래시 데이터 연장
// 모든 플래시 데이터를 한 번 더 요청 연장한다
$request -> session () -> reflash ();
// 특정 키만 연장한다
$request -> session () -> keep ([ 'status' , 'message' ]);
Blade에서 플래시 메시지 표시
{{-- resources/views/layouts/app.blade.php --}}
@if ( session ( 'success' ))
< div class = "alert alert-success" >
{{ session ( 'success' ) }}
</ div >
@endif
@if ( session ( 'error' ))
< div class = "alert alert-danger" >
{{ session ( 'error' ) }}
</ div >
@endif
플래시 메시지 표시는 레이아웃 파일(layouts/app.blade.php 등)에 작성해 두면 모든 페이지에서 일관되게 표시됩니다.
실용 예시: 폼 전송 후의 메시지 표시
폼을 전송한 후 성공 메시지를 세션에 저장해 리다이렉트하고, 다음 페이지에서 표시하는 것은 웹 앱의 정석 패턴입니다.
라우트 정의
use App\Http\Controllers\ PostController ;
Route :: get ( '/posts' , [ PostController :: class , 'index' ]) -> name ( 'posts.index' );
Route :: get ( '/posts/create' , [ PostController :: class , 'create' ]) -> name ( 'posts.create' );
Route :: post ( '/posts' , [ PostController :: class , 'store' ]) -> name ( 'posts.store' );
컨트롤러 구현
폼 전송을 받는 store 메서드에서 저장 후 성공 메시지를 붙여 리다이렉트합니다. <? php
namespace App\Http\Controllers ;
use App\Models\ Post ;
use Illuminate\Http\ RedirectResponse ;
use Illuminate\Http\ Request ;
use Illuminate\View\ View ;
class PostController extends Controller
{
public function index () : View
{
$posts = Post :: latest () -> get ();
return view ( 'posts.index' , [ 'posts' => $posts ]);
}
public function create () : View
{
return view ( 'posts.create' );
}
public function store ( Request $request ) : RedirectResponse
{
$validated = $request -> validate ([
'title' => 'required|string|max:255' ,
'body' => 'required|string' ,
]);
Post :: create ( $validated );
return redirect ()
-> route ( 'posts.index' )
-> with ( 'success' , '게시물을 생성했습니다.' );
}
}
redirect()->with('success', '...')는 리다이렉트 대상으로 플래시 데이터를 전달하는 단축 구문입니다.
레이아웃에서 메시지 표시
resources/views/layouts/app.blade.php에 플래시 메시지의 표시 부분을 추가합니다.<! DOCTYPE html >
< html >
< head >
< title > My App </ title >
</ head >
< body >
{{-- 플래시 메시지 --}}
@if ( session ( 'success' ))
< div class = "alert alert-success" >
{{ session ( 'success' ) }}
</ div >
@endif
@if ( session ( 'error' ))
< div class = "alert alert-danger" >
{{ session ( 'error' ) }}
</ div >
@endif
@yield ( 'content' )
</ body >
</ html >
목록 페이지의 뷰를 생성
{{-- resources/views/posts/index.blade.php --}}
@extends ( 'layouts.app' )
@section ( 'content' )
< h1 > 게시물 목록 </ h1 >
@foreach ( $posts as $post )
< div >
< h2 > {{ $post -> title }} </ h2 >
< p > {{ $post -> body }} </ p >
</ div >
@endforeach
@endsection
게시물이 저장되어 리다이렉트되면 이 목록 페이지 상단에 “게시물을 생성했습니다.”라는 메시지가 한 번만 표시됩니다.
유효성 검증 오류와 조합한 패턴
유효성 검증 실패 시에는 back()->withErrors()와 조합해 사용합니다.
Laravel은 유효성 검증 실패 시 자동으로 오류를 플래시 데이터로 유지하므로 Blade에서 $errors 변수를 사용할 수 있습니다.
public function store ( Request $request ) : RedirectResponse
{
$validated = $request -> validate ([
'title' => 'required|string|max:255' ,
'body' => 'required|string' ,
]);
Post :: create ( $validated );
// 성공 시: 플래시 메시지와 함께 리다이렉트
return redirect ()
-> route ( 'posts.index' )
-> with ( 'success' , '게시물을 생성했습니다.' );
// 유효성 검증 실패 시에는 Laravel이 자동으로 back()->withErrors()->withInput()을 실행한다
}
{{-- 폼 페이지 --}}
@if ( $errors -> any ())
< div class = "alert alert-danger" >
< ul >
@foreach ( $errors -> all () as $error )
< li > {{ $error }} </ li >
@endforeach
</ ul >
</ div >
@endif
< form method = "POST" action = " {{ route ('posts.store') }} " >
@csrf
< div >
< label for = "title" > 제목 </ label >
< input
id = "title"
type = "text"
name = "title"
value = " {{ old ('title') }} "
/>
@error ( 'title' )
< span > {{ $message }} </ span >
@enderror
</ div >
< div >
< label for = "body" > 본문 </ label >
< textarea id = "body" name = "body" > {{ old ( 'body' ) }} </ textarea >
@error ( 'body' )
< span > {{ $message }} </ span >
@enderror
</ div >
< button type = "submit" > 게시 </ button >
</ form >
flush()는 세션의 모든 데이터를 삭제합니다. 로그인 상태 등도 잃게 되므로 사용자의 데이터만 삭제하고 싶은 경우에는 forget()으로 특정 키를 지정해 주세요.
다음 단계
유효성 검증 폼의 입력 데이터를 유효성 검증으로 검사하는 방법을 확인합니다.