메인 콘텐츠로 건너뛰기

해시란

해시(Hashing)란 비밀번호 같은 평문 데이터를 단방향 변환으로 고정 길이의 문자열로 변환하는 처리입니다. 같은 입력에서는 항상 같은 해시가 생성되지만, 해시에서 원래 평문을 복원할 수는 없습니다. Laravel의 Hash 파사드는 안전한 비밀번호 저장을 위해 bcryptArgon2 해시 알고리즘을 지원합니다.

알고리즘 비교

알고리즘특징권장 용도
bcrypt워크 팩터(rounds)로 계산 비용을 조정할 수 있다. 기본값일반적인 웹 애플리케이션
argon2i메모리·시간·스레드 수를 조정할 수 있다. 사이드 채널 공격에 강함높은 보안이 요구되는 상황
argon2idargon2i와 argon2d의 하이브리드. PHC 권장신규 프로젝트에서 Argon2를 사용하는 경우
bcrypt의 “워크 팩터”는 해시 생성에 걸리는 시간을 제어합니다. 해시가 느릴수록 브루트포스 공격에 대한 내성이 높아집니다. 하드웨어가 빨라짐에 따라 워크 팩터를 올리면 보안을 유지할 수 있습니다.

해시화와 검증의 플로우


설정

기본적으로 Laravel은 bcrypt 드라이버를 사용합니다. HASH_DRIVER 환경 변수로 변경할 수 있습니다.
# .env
HASH_DRIVER=bcrypt  # bcrypt / argon / argon2id
해시 설정을 커스터마이징하는 경우, config:publish로 설정 파일을 게시합니다.
php artisan config:publish hashing
게시 후 config/hashing.php에서 기본 워크 팩터 등을 변경할 수 있습니다.

기본 사용법

비밀번호 해시화하기

Hash::make()에 비밀번호의 평문을 전달하면 해시 값이 반환됩니다. 이 해시 값을 데이터베이스에 저장합니다.
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class PasswordController extends Controller
{
    public function update(Request $request): RedirectResponse
    {
        $request->validate([
            'password' => ['required', 'min:8', 'confirmed'],
        ]);

        $request->user()->fill([
            'password' => Hash::make($request->password),
        ])->save();

        return redirect('/profile');
    }
}
해시 값은 데이터베이스에 저장하지만, 평문 비밀번호는 절대 저장하지 마세요.

bcrypt의 워크 팩터 조정

rounds 옵션으로 해시 생성의 계산 비용을 조정할 수 있습니다. 값이 클수록 안전하지만 처리 시간도 늘어납니다. 기본값(12)은 대부분의 애플리케이션에서 적절합니다.
$hashed = Hash::make('plain-text-password', [
    'rounds' => 14,
]);

Argon2의 워크 팩터 조정

Argon2를 사용하는 경우, memory·time·threads 옵션으로 계산 비용을 조정할 수 있습니다.
$hashed = Hash::make('plain-text-password', [
    'memory'  => 65536, // KiB 단위
    'time'    => 4,
    'threads' => 2,
]);
옵션설명기본값
memory사용하는 메모리 양(KiB)65536
time반복 횟수4
threads사용하는 스레드 수1
Argon2 옵션의 자세한 내용은 PHP 공식 문서를 참조해 주세요.

비밀번호 검증

Hash::check()를 사용하면 평문 비밀번호가 저장된 해시와 일치하는지 확인할 수 있습니다. 로그인 처리에서 사용하는 전형적인 예입니다.
use Illuminate\Support\Facades\Hash;

if (Hash::check($request->password, $user->password)) {
    // 비밀번호가 일치했다
} else {
    // 비밀번호가 일치하지 않는다
}
Auth::attempt()를 사용하는 경우에는 이 처리가 자동으로 이루어지므로 직접 호출할 필요는 없습니다. Hash::check()가 유용한 경우는 현재 비밀번호 확인을 수동으로 수행할 때입니다.
// 비밀번호 변경 폼에서 현재 비밀번호를 확인하는 예
if (! Hash::check($request->current_password, $request->user()->password)) {
    return back()->withErrors(['current_password' => '현재 비밀번호가 올바르지 않습니다.']);
}

재해시 판정

Hash::needsRehash()를 사용하면, 해시 생성 시의 워크 팩터가 현재 설정과 다른지 확인할 수 있습니다. 워크 팩터를 변경했을 때, 기존 해시를 새 설정으로 갱신하기 위해 사용합니다.
use Illuminate\Support\Facades\Hash;

if (Hash::needsRehash($user->password)) {
    $user->update([
        'password' => Hash::make($plainTextPassword),
    ]);
}
로그인 성공 시에 재해시를 수행하는 예시입니다.
// 로그인 처리 안에서 재해시를 수행한다
if (Auth::attempt($credentials)) {
    if (Hash::needsRehash(Auth::user()->password)) {
        Auth::user()->update([
            'password' => Hash::make($credentials['password']),
        ]);
    }

    return redirect()->intended('/dashboard');
}
하드웨어의 성능 향상에 맞춰 워크 팩터를 정기적으로 재검토해 보안을 유지합시다. needsRehash()를 활용하면 사용자의 로그인 시점이라는 자연스러운 타이밍에 비밀번호를 갱신할 수 있습니다.

해시 알고리즘 검증

기본적으로 Hash::check()는 해시가 현재 설정된 알고리즘으로 생성된 것인지를 검증합니다. 알고리즘이 다른 경우에는 RuntimeException이 던져집니다. 이를 통해 해시 알고리즘 변조에 의한 공격을 방지할 수 있습니다. 알고리즘을 이전하는 중 등, 여러 알고리즘을 동시에 지원해야 하는 경우에는 HASH_VERIFYfalse로 설정해 이 검증을 무효화할 수 있습니다.
# .env
HASH_VERIFY=false
HASH_VERIFY=false로 하면 알고리즘 검증이 무효화됩니다. 이행 기간 동안에만 사용하고, 이행 완료 후에는 true(기본값)로 되돌려 주세요.

정리

원하는 것방법
비밀번호를 해시화한다Hash::make($password)
해시를 검증한다Hash::check($plain, $hash)
재해시가 필요한지 확인한다Hash::needsRehash($hash)
해시 드라이버를 변경한다HASH_DRIVER 환경 변수
알고리즘 검증을 무효화한다HASH_VERIFY=false

다음 단계

인증 입문

Hash::check()를 사용한 로그인 처리 구현 등 인증의 전체 그림을 배웁니다.
마지막 수정일 2026년 7월 13일