[오류 해결] 렌더링 순서 오류

원서연·2023년 12월 11일
0
post-thumbnail

👉 구현하려고 했던 내용

image

위와 같이, 로그인 정보 오류시 toast 메시지로 알림을 띄우려고 했습니다.

⚠️ 발생한 오류

브라우저 콘솔을 확인해본 결과, toastrWarning 이라는 함수를 인식하지 못함.

image

<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('아이디 또는 비밀번호를 확인해 주세요.');
        }
...

🔖 해결방법 1

그래서 페이지가 모두 로드된 후에 스크립트를 실행하도록 변경하여 해결.

<!-- login.html -->
        /* 로그인 오류에 대한 알림 처리 */
        // DOMContentLoaded : 페이지가 완전히 로드된 후에 스크립트 실행
        document.addEventListener("DOMContentLoaded", function() {
            const currentUrl = window.location.href;
            var queryString = currentUrl.split('?')[1];

            if (queryString && queryString.includes('error')) {
                toastWarning('아이디 또는 비밀번호를 확인해 주세요.');
            }
        });

🔖 해결방법 2 (최종 해결 방법)

일반적으로는 스크립트는 </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에 선언해두기로 결정하였습니다.

profile
웹 백엔드 프로그래밍 Today I Learned

0개의 댓글