위와 같이, 로그인 정보 오류시 toast 메시지로 알림을 띄우려고 했습니다.
브라우저 콘솔을 확인해본 결과, toastrWarning 이라는 함수를 인식하지 못함.
<th:block layout:fragment="content"></th:block>
이 부분이 실행될 때에는
JQuery 라이브러리도, toastr 라이브러리도 로드되지 않은 상태라서
login.html에서 바로 사용할 수 없는 상황.
<!-- layout.html -->
<!doctype html>
<html lang="ko" data-theme="light" xmlns:layout="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>MEDIUM</title>
<link rel="stylesheet" type="text/css" href="/global.css">
<link href="https://jhs512.github.io/toastr/toastr.css" rel="stylesheet">
<meta name="_csrf" th:content="${_csrf.token}"/>
</head>
<body>
<nav th:replace="~{global/navbar :: navbarFragment}"></nav>
<th:block layout:fragment="content"></th:block>
<!-- 테일윈드, 데이지UI -->
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/daisyui@4.4.19/dist/full.min.css" rel="stylesheet" type="text/css"/>
<!-- 제이쿼리 불러오기 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- toastr 불러오기 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>
<script src="/global.js"></script>
<script>
/* 일반적인 msg 알림 처리 */
const queryParams = getQueryParams();
if (queryParams.msg) {
toastNotice(queryParams.msg);
}
/* historyBack에 대한 msg 알림 처리 */
$(window).bind("pageshow", function (event) {
const historyBackMsg = localStorage.getItem('historyBackMsg');
if (historyBackMsg) {
toastWarning(historyBackMsg);
localStorage.removeItem('historyBackMsg');
}
});
</script>
</body>
</html>
<!-- login.html -->
...
/* 로그인 오류에 대한 알림 처리 */
const currentUrl = window.location.href;
var queryString = currentUrl.split('?')[1];
if (queryString && queryString.includes('error')) {
toastWarning('아이디 또는 비밀번호를 확인해 주세요.');
}
...
그래서 페이지가 모두 로드된 후에 스크립트를 실행하도록 변경하여 해결.
<!-- login.html -->
/* 로그인 오류에 대한 알림 처리 */
// DOMContentLoaded : 페이지가 완전히 로드된 후에 스크립트 실행
document.addEventListener("DOMContentLoaded", function() {
const currentUrl = window.location.href;
var queryString = currentUrl.split('?')[1];
if (queryString && queryString.includes('error')) {
toastWarning('아이디 또는 비밀번호를 확인해 주세요.');
}
});
일반적으로는 스크립트는 </body>
태그 위에 놓는 것이 좋은 이유가, 스크립트에서 dom 객체를 사용하는 경우를 고려해서 body의 내용이 렌더링 된 후에 스크립트가 돌아가게 하기 위함인데,
라이브러리 처럼 오히려 body에서 가져다 사용하는 스크립트 들은 head 에 있는 것이 올바른 것이라는 것을 알게 되었습니다.
그래서 다시 소스코드 구조와 원인을 되돌아본 결과, JQuery 라이브러리와 toastr 라이브러리 즉, body에서 사용을 하게되는 코드들은 head에 올려놓는 것이 더 근본적인 해결책이라고 생각했습니다.
<!-- login.html -->
/* 로그인 오류에 대한 알림 처리 */
const currentUrl = window.location.href;
var queryString = currentUrl.split('?')[1];
if (queryString && queryString.includes('error')) {
toastWarning('아이디 또는 비밀번호를 확인해 주세요.');
}
<!-- layout.html -->
<!doctype html>
<html lang="ko" data-theme="light" xmlns:layout="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>MEDIUM</title>
<!-- 제이쿼리 불러오기 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- toastr 불러오기 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>
<link href="https://jhs512.github.io/toastr/toastr.css" rel="stylesheet">
<script src="/global.js"></script>
<link rel="stylesheet" type="text/css" href="/global.css">
<meta name="_csrf" th:content="${_csrf.token}"/>
</head>
JQuery, toastr 라이브러리 이외에도 body에서 사용하기 위해 로드시키는 스크립트는 head에 선언해두기로 결정하였습니다.