제5.3장: Laravel 뷰에 JavaScript 임베딩
학습 시간: 50분
1. 웹에서 JavaScript를 다루는 두 가지 접근 방식
지금까지 우리는 서버 측 렌더링(SSR)으로 작업했습니다. 서버(Laravel)가 완성된 HTML을 생성(Blade를 통해)하여 브라우저로 전송하는 방식입니다. 이는 SEO와 빠른 초기 로딩에 매우 좋습니다.
이제 클라이언트 측 상호작용을 추가할 것입니다. 브라우저는 페이지를 로드한 후 JavaScript 코드를 실행하여 다음을 수행합니다:
- 페이지를 새로고침하지 않고 API에 요청을 보냅니다.
- 페이지의 특정 부분을 동적으로 업데이트합니다(예: 목록에 새 행성 추가).
- 알림 및 모달 창을 표시합니다.
💡 우주 비유:
SSR은 우주 비행 관제 센터(서버)에서 인쇄된 전체 성계 지도를 받는 것이라고 상상해 보십시오. 인쇄 시점의 모든 개체를 볼 수 있습니다.
클라이언트 측 JS는 위성(API)과 실시간으로 통신하며, 우주 비행 관제 센터에서 새로운 종이 지도를 요청할 필요 없이 지도상의 객체 위치를 업데이트하는 개인 태블릿(브라우저)입니다.
2. JS 코드를 저장하고 연결하는 방법
이미 확인했듯이, 모든 공개 자산(CSS, JS, 이미지)은 public
폴더에 있어야 합니다.
올바른 구조:
- 원본 파일: 모든 주요 JS 코드는
public/js/
에 있어야 합니다. 예를 들어,public/js/planets.js
와 같이요. - Blade에서 연결:
asset()
헬퍼를 사용하여 올바른 URL을 생성하십시오.
layouts/app.blade.php
레이아웃에서 연결 예시:
<!DOCTYPE html>
<html>
<head>
{{-- ... --}}
</head>
<body>
{{-- ... 헤더 및 메인 ... --}}
<footer>
<p>© {{ date('Y') }} Space Command.</p>
</footer>
{{-- 스크립트는 페이지 렌더링 속도를 높이기 위해 body 태그 끝에 연결하는 것이 좋습니다 --}}
<script src="{{ asset('js/planets.js') }}"></script>
@stack('scripts') {{-- 특정 페이지의 스크립트 "슬롯" 생성 --}}
</body>
</html>
@stack('scripts')
는 강력한 Blade 지시문입니다. 이는 하위 뷰가 자신만의 JS 코드를 이 위치에 "푸시"할 수 있도록 허용합니다. 이는 특정 페이지에는 고유한 스크립트가 필요하고 다른 페이지에는 필요하지 않을 때 유용합니다.
3. 예시: 확인이 필요한 "삭제" 버튼
행성 목록 페이지(planets/index.blade.php
)에 JavaScript와 Fetch API를 통해 작동하는 각 행성에 대한 "삭제" 버튼을 추가해 봅시다.
1단계: resources/views/planets/index.blade.php
에 버튼 추가
data-속성을 사용하여 행성 카드에 버튼을 추가합니다:
{{-- ... @forelse 루프 내부 ... --}}
<div class="planet-card" id="planet-card-{{ $planet->id }}">
<h3>{{ $planet->name }}</h3>
<p>태양계: {{ $planet->solar_system }}</p>
<p>직경: {{ number_format($planet->size_km, 0, '.', ' ') }} km</p>
<a href="/planets/{{ $planet->id }}">더 알아보기 →</a>
<button class="delete-btn" data-id="{{ $planet->id }}" data-url="/api/planets/{{ $planet->id }}">
폐기
</button>
</div>
<!-- ... 닫히는 body 태그 앞 ... -->
<script src="{{ asset('js/planets.js') }}" defer></script>
id="planet-card-{{ $planet->id }}"
— 전체 카드에 대한 고유 ID로, DOM에서 이 카드를 제거할 수 있도록 합니다.data-id
및data-url
— PHP (Blade)에서 JavaScript로 데이터를 전달하는 편리한 방법입니다.
2단계: JavaScript 로직 작성
public/js/planets.js
파일을 생성하고 다음 코드를 추가합니다:
document.addEventListener('DOMContentLoaded', () => {
// 모든 "삭제" 버튼 찾기
const deleteButtons = document.querySelectorAll('.delete-btn');
deleteButtons.forEach(button => {
button.addEventListener('click', async (event) => {
const planetId = event.target.dataset.id;
const apiUrl = event.target.dataset.url;
if (!confirm(`ID ${planetId}의 행성을 폐기하시겠습니까? 이 작업은 되돌릴 수 없습니다.`)) {
return; // 사용자가 "취소"를 눌렀습니다
}
try {
// API에 DELETE 요청 보내기
const response = await fetch(apiUrl, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
// 나중에 여기에 CSRF 토큰을 추가할 것입니다
}
});
if (response.status === 204) { // 204 No Content - 성공적인 삭제
// 페이지에서 행성 카드 제거
const cardToRemove = document.getElementById(`planet-card-${planetId}`);
if (cardToRemove) {
cardToRemove.remove();
}
alert('행성이 성공적으로 폐기되었습니다.');
} else {
// API가 오류를 반환한 경우
const errorData = await response.json();
alert(`오류: ${errorData.message || '행성을 삭제할 수 없었습니다.'}`);
}
} catch (error) {
console.error('요청 전송 중 오류 발생:', error);
alert('네트워크 오류가 발생했습니다. 다시 시도해 주세요.');
}
});
});
});
이제 /planets
페이지를 새로고침하면 "폐기" 버튼이 나타나고, 이 버튼을 클릭하면 JavaScript 코드가 실행됩니다!
4. Blade에서 JavaScript로 데이터 전달하기
때로는 단순히 문자열이 아니라 전체 배열 또는 객체를 JS로 전달해야 할 때도 있습니다.
잘못된 방법 (취약):
올바른 방법 (JSON을 통해):
@json
지시어를 사용하십시오. 이 지시어는 PHP 배열/객체를 유효한 JSON 객체로 안전하게 변환합니다.
planets/index.blade.php
예시:
@extends('layouts.app')
{{-- ... --}}
@section('content')
{{-- ... --}}
@endsection
@push('scripts') {{-- 우리 스크립트를 레이아웃의 @stack('scripts') 슬롯에 "푸시"합니다 --}}
<script>
// Laravel은 $planets 컬렉션을 JSON 배열로 안전하게 변환합니다
const planetsData = @json($planets);
// 이제 JS에서 이 배열을 사용할 수 있습니다
console.log('Blade에서 전달된 행성 데이터:', planetsData);
alert(`${planetsData.length}개의 행성이 로드되었습니다!`);
</script>
@endpush
@push('scripts')
는layouts/app.blade.php
의@stack('scripts')
내부에 내용을 배치합니다. 이를 통해 스크립트가 실제로 필요한 페이지에만 추가할 수 있습니다.
확인을 위한 퀴즈
🚀 챕터 요약:
당신은 클라이언트 로직을 추가하여 정적인 Blade 페이지에 생명을 불어넣는 방법을 배웠습니다. 핵심 기술:
- Laravel 프로젝트에서 JS 파일을 올바르게 구성하고 연결하는 방법.
- HTML에서 JS로 데이터를 전송하기 위해
data-*
속성을 사용하는 방법. - 페이지를 새로 고치지 않고 Fetch를 사용하여 API와 동적으로 상호 작용하는 방법.
@json
지시어를 사용하여 PHP 변수를 JavaScript로 안전하게 전송하는 방법.@push
및@stack
을 사용하여 스크립트를 구성하는 방법.
당신의 "제어판"이 이제 상호작용 가능해졌습니다. 하지만 지금 우리의 변경 요청들(POST, PUT, DELETE)은 취약합니다. 다음 챕터에서 우리는 가장 중요한 보안 메커니즘인 CSRF 토큰을 추가할 것입니다. ```