관리 메뉴

java,javascript,android,php,sql,공부용,메모용

라라벨 5 - 메인(홈) 화면, 회원가입, 로그인, 로그아웃, 메일보내기 본문

개발/php

라라벨 5 - 메인(홈) 화면, 회원가입, 로그인, 로그아웃, 메일보내기

yy_dd2 2025. 10. 10. 15:34
반응형

1단에서 메인화면, 회원가입, 로그인, 로그아웃, 메일보내기를 작성하고 사용하는 방법을 배웠다.

2-3년이 지났어도 꾸준히 발전하는 언어기 때문에 생각보다 많은게 바뀌어 있었다.

 

/home 라우트 기본 구조와 홈화면 연결
/register 회원가입 폼, DB저장, 등록완료화면
/login 로그인 폼, 인증 처리
/logout 로그아웃 구현 및 미들웨어 설명
회원가입 시 메일 보내기 회원가입 후 인증 메일 발송 기능

 

 

/home

기본 페이지 및 Home 라우트 만들기 (/home)
① — 기본 라우트와 Home 페이지 연결하기

 

더보기

1. 라우트(Route) 기본 구성
/ : welcome.blade.php 표시
/home : home.blade.php 표시

// routes/web.php
Route::get('/', function () {
    return view('welcome');
});

Route::get('/home', function () {
    return view('home');
});

 

2.뷰 파일 생성
resources/views/home.blade.php

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>첫 화면</title>
</head>
<body>
    <p>안녕하세요
@if (Auth::check())
    {{  \Auth::user()->name }}님</p>
    <p><a href="/logout">로그아웃</a></p>
@else 
    게스트님</p>
    <p><a href="/login">로그인</a></br><a href="/register">회원등록</a></p>
@endif    
</body>
</heml>

 

3.개념 정리 포인트

라우트(Route)는 URL 요청을 어떤 컨트롤러나 뷰와 연결할지 결정한다.
Route::get()은 GET 요청을 받을 때 사용된다.
return view('home') → resources/views/home.blade.php를 보여줌.

 

 

 

 

/register

② — 회원가입(Register) 기능 구현

 

더보기

1. 라우터 설정

// routes/web.php
Route::get('/register', [App\Http\Controllers\RegisterController::class, 'create'])
    ->middleware('guest')
    ->name('register');
Route::post('/register', [App\Http\Controllers\RegisterController::class, 'store'])
    ->middleware('guest');

 

2. 회원가입 폼 뷰 작성

/resources/views/regist/register.blade.php

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <title>사용자 등록폼</title>
</head>
<body>
<form name="registerform" action="/register" method="post" id="registform">
    {{  csrf_field() }} <!-- CSRF 토큰을 넣기 위한 코드 -->
    <!-- form 태그안에는 <input type="hidden" name="_token" value="랜덤한_긴문자열">
        이라는 값이 있는데 CSRF(Cross-Site Request Forgery, 사이트 간 요청 위조) 공격을 막기 위한 토큰을 자동으로 생성해서 넣어준다
        라라벨은 POST, PUT, DELETE 요청을 받을 때 CSRF 토큰 검사를 무조건 수행
        폼에 이 토큰이 없으면 → "419 Page Expired" 에러가 남
        @ 와 csrf붙여서도 사용함 @ csrf

    -->  
    <dl>
        <dt>이름 : </dt>
        <dd><input type="text" name="name" size="30" />
        <span>{{ $errors->first('name') }}</span></dd>
    </dl>
    <dl>
        <dt>메일주소 : </dt>
        <dd><input type="text" name="email" size="30" />
        <span>{{ $errors->first('email') }}</span></dd>
    </dl>
    <dl>
        <dt>비밀번호 : </dt>
        <dd><input type="password" name="password" size="30" />
        <span>{{ $errors->first('password') }}</span></dd>
    </dl>
    <dl>
        <dt>비밀번호(확인) : </dt>
        <dd><input type="password" name="password_confirmation" size="30" />
        <span>{{ $errors->first('password_confirmation') }}</span></dd>
    </dl>
    <button type="submit" name="action" value="send">보내기</button>
</form>
</body>
</html>

 

3. 컨트롤러 작성

<?php

declare(strict_types=1);
// php7 이상에서 "엄격한 타입 모드 선언" (함수/메소드 파라미터, 리턴타입 체크 강화)

namespace App\Http\Controllers;
// 이 클래스의 네임스페이스(이름공간)의 정의 App\Http\Controllers 폴더 안에 있는 컨트롤러를 나타냄

use App\Models\User;                  // User 모델을 불러옴 DB Users 테이블과 연결
use Illuminate\Http\Request;          // Http 요청(Requset)객체를 사용하기 위해 불러움 사용자가 보낸 데이터 (폼, 입력값 등)을 다루는 클래스
use Illuminate\Support\Facades\Hash;  // 비밀번호 해시 암호화 하기 위해 불러옴

class RegisterController extends Controller
{
    public function create()    // 회원가입 화면을 보여주는 메소드
    {   
        return view('regist.register'); 
        // view단의 디렉토리 구분을 . 마침표로 한다 regist디렉토리  register 라는 파일의 view회면을 뜻한다.
        // 'regist.register'는 resources/views/regist/register.blade.php 파일을 의미
    }
    // store 메서드는 Request 클래스의 validate 메서드를 이용해 입력된 값을 확인한 뒤에 User::create 메서드를 사용해 데이터베이스에 등록합니다. 그런 뒤에 regist.complete 뷰로 이동한다.
    /* 
        store 메서드는
        사용자가 입력한 값이 제대로 되었는지 먼저 검사합니다. (예: 이메일 형식이 맞는지, 비밀번호 길이가 충분한지 등)
        값이 올바르면 새로운 사용자를 데이터베이스에 저장합니다.
        저장이 끝나면 "회원가입이 완료되었습니다"라는 화면(regist.complete 뷰)을 보여줍니다.
    */
    public function store(Request $request) // 회원가입 데이터를 저장하는 메소드
    {
        // 입력값 유효성 검사
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8',
        ]);
        //  새로운 사용자(User) 생성
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);


        //  회원가입 완료 화면으로 이동
        // compact('user')는 ['user' => $user]와 같은 의미로 뷰 화면에 전달됨
        return view('regist.complete', compact('user'));
    }
}

?>

 

4. 등록완료 화면

/resources/views/regist/complete.blade.php

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <title>등록 완료</title>
</head>
<body>
    {{  $user->name }}님을 등록했습니다.
    등록된 이메일은 {{ $user->email }}입니다.
</body>
</html>

 

 

 

/login

③ — 로그인(Login) 기능 구현

 

더보기

1. 라우터 설정

Route::get('/login', [App\Http\Controllers\LoginController::class, 'index'])
    ->middleware('guest')
    ->name('login');
Route::post('/login', [App\Http\Controllers\LoginController::class, 'authenticate'])
    ->middleware('guest');

 

2. 로그인 폼 작성

/resources/views/auth/login.blade.php

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <title>로그인폼</title>
</head>
<body>
@isset($errors)
    <p style="color: red">{{ $errors->first('message') }}</p>
@endisset
<form name="loginform" action="/login"  method="POST">
    {{ csrf_field() }}
    <dl>
        <dt>메일주소:</dt><dd><input type="text" name="email" size="30" value="{{ old('email') }}"></dd>
        <dt>비밀번호:</dt><dd><input type="password" name="password" size="30"></dd>
    </dl>
    <button type="submit"   name="action"   value="send">로그인</button>
</form>
</body>
</html>

 

3. 컨트롤러 작성

<?php

namespace App\Http\Controllers; // 이 클래스의 네임스페이스(이름공간)의 정의

use App\Providers\RouteServiceProvider;        // 로그인 후 리디렉션 경로를 지정하기 위해 RouteServiceProvider 사용
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;        // 사용자 인증 관련 기능을 제공하는 Auth Facades를 불러옴

class LoginController extends Controller
{
    //
    public function index()
    {
        // 로그인 화면을 보여주는 메서드
        // resources/views/auth/login.blade.php 파일
        return view('auth.login');
    }
    public function authenticate(Request $request)
    {
        // 로그인 요청처리 메서드, Request객체를 통해서 폼 데이터를 가져옴
        $credentials = $request->only('email', 'password');
        // 요청에서 email과 password만 추출해서 $credentials에 저장

        if(Auth::attempt($credentials)){
            //Auth::attempt는 주어진 email과 password가 데이터베이스와 일치한지 확인
            $request->session()->regenerate();
            // 세션 id를 새로 생성해 고정공격(session Fixtion)을 방지
            return redirect()->intended(RouteServiceProvider::HOME);
            // 로그인 이전에 사용자가 접근하려던 페이지로 이동합니다
            // 지정된 경로가 없다면 (RouteServiceProvider::HOME) /home으로 이동합니다.
        }
        return back()->withErrors([
            'message' => '메일주소 또는 비밀번호가 올바르지 않습니다.',
        ]);
        // 로그인 실패시 이전페이지로 돌아가면서 에러메시지를 전달합니다.
    }

    //  로그아웃 기능 메서드
    public function logout(Request $request){
        Auth::logout();
        // 현재 로그인된 사용자의 인증 정보를 삭제 (로그아웃 처리)

        $request->session()->invalidate();
        // 기존 세션 데이터를 무효화 하기

        $request->session()->regenerateToken();
        // 새로운 세션 토큰 (CSRF Token)을 재생성해 보안 위협 방지

        return redirect(RouteServiceProvider::HOME);
        // 로그아웃 후 홈 화면으로 리다이랙트
    }


}

 

 

 

/logout

④ — 로그아웃(Logout) 기능 구현

1. 라우트 설정

Route::get('/logout', [App\Http\Controllers\LoginController::class, 'logout'])
    ->middleware('auth')
    ->name('logout');

 

2. 컨트롤러 작성
로그인 컨트롤러에 같이 작성되어있음

 

 

회원 가입시 메일보내기 

⑤ — 회원가입 시 이메일 인증 메일 보내기

더보기

1. 메일 설정

파일 : .env

MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=mailpit
##MAIL_HOST=mailhog     Laravel 10+ 이후, Sail은 기본적으로 Mailhog 대신 Mailpit을 사용합니다.
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

 

2. 리스터 클래스 만들기

회원가입이 완료될 때 자동으로 이메일을 발송하기 위해
라라벨의 이벤트 리스너 구조를 사용합니다.

터미널에서 아래 명령어를 실행합니다.

sail artisan event:generate


이 명령어는

/app/Providers/EventServiceProvider.php 안의 listen 배열을 참고해서

필요한 리스너 파일을 자동으로 생성해줍니다.

**먼저 EventServiceProvider에 리스너를 등록해야 합니다.

/app/Providers/EventServiceProvider.php

 

<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        Registered::class   =>  [
            //SendEmailVerificationNotification::class, //삭제
            \App\Listeners\RegisteredListener::class,
            // 이렇게 작성하고 터미널에서 sail artisan event:generate 라고 쓰면
            // 리스너 클래스가 생성되었다고함 Events and listeners generated successfully. 
        ]
    ];
    public function boot(): void
    {
    
    };
}
<?php
/*
실제로 Laravel 12 버전에서는 “미니멀 스켈레톤(minimal skeleton)” 설치 방식이 도입되면서, 기본적으로 제공되던 많은 파일들이 생략된 버전이 있을 수 있다는 토론이 있습니다. 
GitHub

즉, Laravel 12에서 기본 설치판이라고 해도 AppServiceProvider.php 하나만 있고 나머지 AuthServiceProvider, EventServiceProvider, RouteServiceProvider 등이 없는 구조가 있을 수 있다는 보고가 있습니다.
https://github.com/gothinkster/laravel-realworld-example-app/tree/master/app/Providers
*/

namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array<class-string, array<int, class-string>>
     */
    protected $listen = [
        // \App\Events\SomeEvent::class => [
        //     \App\Listeners\SomeListener::class,
        // ],
        Registered::class   =>  [
         //\Illuminate\Auth\Events\Registered::class  => [
            //SendEmailVerificationNotification::class, //삭제
            \App\Listeners\RegisteredListener::class,
            // 이렇게 작성하고 터미널에서 sail artisan event:generate 라고 쓰면
            // 리스너 클래스가 생성되었다고함 Events and listeners generated successfully. 
        ]
    ];

    /**
     * Register any events for your application.
     */
    public function boot(): void
    {
        //
    }

    //
}

 

포인트

Registered 이벤트는 라라벨의 회원가입 완료 시 자동으로 발생하는 기본 이벤트입니다.
RegisteredListener는 우리가 작성할 리스너 클래스입니다.

 

이 상태에서 명령어 실행 👇

sail artisan event:generate

성공 시 /app/Listeners/RegisteredListener.php 파일이 자동 생성됩니다.

 

3. 리스너 클래스 구현

/app/Listeners/RegisteredListener.php

<?php

namespace App\Listeners;

use App\Models\User;
use Illuminate\Mail\Mailer;
use Illuminate\Auth\Events\Registered;

class RegisteredListener
{
    /**
     * Handle the event.
     */
    Private $mailer;
    Private $eloquent;

    public function __construct(Mailer $mailer, User $eloquent)
    {
        $this->mailer   =   $mailer;
        $this->eloquent =   $eloquent;
    }
    public function handle(Registered $event)
    {
        // 회원가입 이벤트 처리 로직
        // 예: 로그 출력, 이메일 발송 등
        // info('User registered: ' . $event->user->email);
        $user   =   $this->eloquent->findOrFail($event->user->getAuthIdentifier());
        $this->mailer->raw('회원등록을 완료했습니다.',function ($message) use ($user){
            $message->subject('회원 등록 메일')->to($user->email);
        });
    }
}

Registered는 라라벨이 기본 제공하는 회원가입 완료 이벤트입니다.

RegisteredListener::class 는 방금 작성한 리스너 파일을 연결해줍니다.

이 상태로 저장 후 아래 명령어 실행 👇
sail artisan event:generate
이미 파일이 존재한다면 “리스너가 이미 존재합니다” 메시지가 뜨고, 문제없고 다음으로 넘어감

 

4. 컨트롤러 작성 "회원가입 이벤트 발생시키기"

리스너는 “이벤트가 발생해야” 실행됩니다.
회원가입이 완료되는 시점(즉, User가 생성된 직후)에 Registered 이벤트를 발생시켜야 합니다.

✅ 가 추가된 내용

/app/Http/Controllers/RegisterController.php

<?php

declare(strict_types=1);
// php7 이상에서 "엄격한 타입 모드 선언" (함수/메소드 파라미터, 리턴타입 체크 강화)

namespace App\Http\Controllers;
// 이 클래스의 네임스페이스(이름공간)의 정의 App\Http\Controllers 폴더 안에 있는 컨트롤러를 나타냄

use App\Models\User;                  // User 모델을 불러옴 DB Users 테이블과 연결
use Illuminate\Auth\Events\Registered;// ✅ + 이메일 보내기 관련 추가하면서 자동으로 추가됨
use Illuminate\Http\Request;          // Http 요청(Requset)객체를 사용하기 위해 불러움 사용자가 보낸 데이터 (폼, 입력값 등)을 다루는 클래스
use Illuminate\Support\Facades\Hash;  // 비밀번호 해시 암호화 하기 위해 불러옴

class RegisterController extends Controller
{
    public function create()    // 회원가입 화면을 보여주는 메소드
    {   
        return view('regist.register'); 
        // view단의 디렉토리 구분을 . 마침표로 한다 regist디렉토리  register 라는 파일의 view회면을 뜻한다.
        // 'regist.register'는 resources/views/regist/register.blade.php 파일을 의미
    }
    // store 메서드는 Request 클래스의 validate 메서드를 이용해 입력된 값을 확인한 뒤에 User::create 메서드를 사용해 데이터베이스에 등록합니다. 그런 뒤에 regist.complete 뷰로 이동한다.
    /* 
        store 메서드는
        사용자가 입력한 값이 제대로 되었는지 먼저 검사합니다. (예: 이메일 형식이 맞는지, 비밀번호 길이가 충분한지 등)
        값이 올바르면 새로운 사용자를 데이터베이스에 저장합니다.
        저장이 끝나면 "회원가입이 완료되었습니다"라는 화면(regist.complete 뷰)을 보여줍니다.
    */
    public function store(Request $request) // 회원가입 데이터를 저장하는 메소드
    {
        // 입력값 유효성 검사
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8',
        ]);
        //  새로운 사용자(User) 생성
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);
		// ✅ 여기서 이벤트 발생
        // + 이메일 보내기 관련 추가
        event(new Registered($user));

        //  회원가입 완료 화면으로 이동
        // compact('user')는 ['user' => $user]와 같은 의미로 뷰 화면에 전달됨
        return view('regist.complete', compact('user'));
    }
}

?>

 



 

5. 로그로 발송 메일 확인하기 / 메일핏으로 메일 발송 확인 하기


.env에서 MAIL_MAILER=log로 설정 후

MAIL_MAILER=log

storage/logs/laravel.log에서 메일 내용이 기록되는지 확인합니다.
정상 작동하면 나중에 MAIL_MAILER=smtp로 변경하여 실제 메일 발송 가능.

 

메일핏은 http://localhost:8025   :8025로 접속해서 확인이 가능하다.

 

 

추가로 메일보내기에 이렇게 화면을 분리하면 꾸미기 편리할 듯 함

app/Mail/WelcomeMail.php (참고용)

<?php

namespace App\Mail;

use Illuminate\Mail\Mailable;

class WelcomeMail extends Mailable
{
    public $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

    public function build()
    {
        return $this->subject('회원가입을 축하드립니다 🎉')
                    ->view('emails.welcome');
    }
}



📁 resources/views/emails/welcome.blade.php

<h2>🎉 회원가입을 환영합니다!</h2>
<p>{{ $user->name }}님, 가입을 진심으로 축하드립니다.</p>
<p>지금 바로 로그인하여 서비스를 이용해보세요!</p>

 

반응형
Comments