기본적으로 html 파일을 서버로부터 받고 link 되어있는 css, js, img 등의 외부 파일을 받는다고 알고 있는데, 그럼 html 파일 내부에서는 처리 순서가 어떻게 될까?

밑에 코드 : 같은 script구문 안에 있으면 호이스팅 기능이 있어 함수를 정의하기 전에 호출해도 문제가 없는데, 밑에처럼 script구문을 두 개로 나누어하면 왜 안될까?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Insert title here</title>

    <script>
      test();
    </script>

    <script>
      function test() {
        alert("함수 호출 성공");
      }
    </script>
    
  </head>
  <body></body>
</html>

밑에 코드 : html을 브라우저가 화면에 띄우기 전에 만약 바로 처리해야하는 js코드가 있다면 js를 먼저 처리하고 완성된 html 문서를 화면에 출력한다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Insert title here</title>
  </head>
  <body>
    <p>lsajdlkjalhgkjdalkbhjadflkbjladfjbladfjlbkjadflbjadlbjlkadjb</p>
    <script>
      do {
        var s = prompt("아무거나 입력하세요.");
        document.write(s);
      } while (s != "0");
    </script>
    <p>dkjfaslkfjaslkvjlskbvjlkabjlkj</p>
    
  </body>
</html>

***js로 html 요소를 선택할 때!! head태그 안에 script 블럭 넣으니깐 오류가 발생했다. 왜냐하면 body태그가 아직 실행되지 않았기 때문에 먼저 실행된 js 코드에서는 변수에 null값이 들어간다. 왜냐면 객체가 없으니깐!!

해결방법으로는 window.onload()로 감싸주거나, </body>바로 앞에 script블럭을 넣어주기!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      input[name="append"] {
        padding: 5px;
        width: 80%;
      }
      #mylist {
        list-style-type: none;
        padding: 0;
      }
      #mylist > li {
        line-height: 2em;
        margin: 5px 0;
        border: 1px solid #ccc;
        cursor: pointer;
        background: url("bullet.png") no-repeat;
        text-indent: 32px;
      }
    </style>

    <script>
      **var newList = document.querySelector('input[name="append"]');
//아직 body태그 실행 안됨. 즉 괄호안의 저런 객체는 없음**
	
      newList.onkeydown = function (event) {
        if (event.which == 13 && event.target.value.length > 2) {
          var newLi = document.createElement("li");
          var txt = event.target.value;
          newLi.appendChild(document.createTextNode(txt));
          document.getElementById("mylist").appendChild(newLi);
        }
      };
    </script>
  </head>
  <body>
    <input type="text" name="append" placeholder="내용 입력 후 엔터!" />
    <ul id="mylist">
      <li>1번째 목록</li>
    </ul>
  </body>
</html>

밑에는 이 과정을 좀 더 잘 설명해준 chatGPT 선생님이시다.

[](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%2730%27%20height=%2730%27/%3e)

[](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%2730%27%20height=%2730%27/%3e)

test.html:29 Uncaught TypeError: Cannot set properties of null (setting 'onkeydown')

This error occurs when you try to access a property or method of a null or undefined value. In this case, it seems that the newList variable is not pointing to an element in the HTML document. This could be because the element with the name append does not exist, or because the JavaScript code is being executed before the HTML document has finished loading.

To fix this error, you can try placing the JavaScript code at the end of the body tag, just before the closing </body> tag. This will ensure that the HTML elements have been loaded by the time the JavaScript code runs. Alternatively, you can use the window.onload event to make sure that the JavaScript code runs only after the HTML document has finished loading.