[JS] html의 <script> 태그

jiny·2025년 1월 29일

기술 면접

목록 보기
45/78

🗣️ html에서 자바스크립트 코드를 로딩하는 <script> 태그는 보통 <body> 태그의 최하단에 위치하는데요. 그 이유가 무엇일까요?

  • 의도: 브라우저의 로딩 방식과 DOM 트리 구축 등 렌더링 과정에 대한 지식이 있는지 확인하는 질문

  • 팁: moduledefer 속성에 대해서도 언급하면 좋다.

  • 나의 답안

    그 이유는 페이지 로딩 속도사용자 경험 때문입니다.

    브라우저는 HTML을 위에서부터 차례로 파싱하면서 화면을 그리는데,
    <script> 태그를 만나면 자바스크립트를 다운로드하고 실행할 때까지 HTML 파싱이 일시 중단됩니다.
    즉, 스크립트가 상단에 있으면 렌더링이 지연되어 사용자에게 화면이 늦게 보이는 문제가 생깁니다.

    그래서 <body> 하단에 스크립트를 두면 HTML 구조와 콘텐츠가 먼저 로드된 뒤,
    그 이후에 자바스크립트가 실행되기 때문에 초기 렌더링 속도가 빨라지고 사용자에게 더 빠른 반응을 보여줄 수 있습니다.

  • 주어진 답안 (모범 답안)

    첫 번째 이유는 페이지의 로딩 속도 최적화 때문입니다.
    브라우저는 html을 읽어내려가다 <script> 태그를 만나게 되면 해당 자바스크립트 코드를 읽고 실행하기 시작합니다.
    만약 <script> 태그가 상단에 있다면 DOM 트리 구축 시기가 늦어져 페이지의 로딩이 느려질 수 있습니다.

    두 번째 이유는 DOM 접근 시에 오류가 생길 수 있기 때문입니다.
    앞서 자바스크립트가 먼저 읽히고 실행될 수도 있다고 말씀드렸죠?
    그런데 만약 자바스크립트 코드에 document.querySelector처럼 html 태그를 가져오는 코드가 있다면 어떻게 될까요?
    아직 DOM 트리가 구축되지 않았으므로 원하는 태그를 가져오지 못하고 undefined를 반환하게 됩니다.
    이러한 이유로 <script> 태그를 <body>의 최하단에 넣곤 합니다.

    물론 다른 방법도 있는데요, 바로 <script> 태그에 defermodule을 작성하는 것입니다.
    그러면 자동으로 <script> 태그를 지연 로딩할 수 있습니다.


📝 개념 정리

<script> 태그는 HTML 문서에서 JavaScript 코드를 포함하거나 외부 스크립트 파일을 불러올 때 사용하는 태그이다.

🌟 <script> 태그의 기본 구조

  1. 내부 스크립트 사용
    HTML 문서 안에 직접 JavaScript 코드를 작성할 수 있다.
    <!DOCTYPE html>
    <html lang="ko">
      <head>
        <title>스크립트 테스트</title>
      </head>
      <body>
        <h1>안녕하세요!</h1>
        <script>
          alert("페이지가 로드되었습니다.");
        </script>
      </body>
    </html>
    • <script> 태그는 기본적으로 HTML 코드 어디에서든 사용할 수 있지만, 가능하면 <body>의 맨 아래defer 속성을 사용하는 것이 좋다.
  1. 외부 스크립트 파일 사용
    외부 JavaScript 파일을 불러올 수도 있다.
    <script src="script.js"></script>
    • 이 방식은 HTML과 JavaScript를 분리할 수 있어서 유지보수하기 좋다.

🌟 <script> 태그의 주요 속성들

  1. src: 외부 스크립트 파일 경로
    <script src="app.js"></script>
    • src 속성을 사용하면 해당 파일의 코드를 실행한다.
    • src가 있으면 <script> 태그 내부에는 코드를 작성하면 안 된다.
  1. async: 비동기 실행
    <script src="script1.js" async></script>
    <script src="script2.js" async></script>
    • HTML 파싱스크립트 다운로드동시에 진행한다.
    • 다운로드 완료 즉시 실행한다. (HTML 파싱 중단)
    • 여러 개의 <script> 태그가 있을 때, 실행 순서가 보장되지 않는다.
    • 언제 사용하면 좋을까?
      💡페이지에 영향을 주지 않는 스크립트 (예: 광고, 분석 도구)
      💡서로 의존성이 없는 스크립트 (서로 실행 순서가 중요하지 않을 때)
  1. defer: HTML 파싱 완료 후 실행
    <script src="script1.js" defer></script>
    <script src="script2.js" defer></script>
    • HTML 파싱스크립트 다운로드동시에 진행한다.
    • HTML이 완전히 로드된 후 실행한다. (DOMContentLoaded 이벤트 발생 직전)
    • <script defer>작성된 순서대로 실행된다.
    • 언제 사용하면 좋을까?
      💡DOM을 조작하는 스크립트 (HTML 요소가 다 로딩된 후 실행해야 할 때)
      💡스크립트 실행 순서가 중요한 경우 (async보다 defer가 안정적)
  1. type: MIME 타입 지정
    MIME(Multipurpose Internet Mail Extensions) 타입은 파일의 형식(타입)을 나타내는 문자열이다.
    웹에서 서버와 클라이언트가 데이터를 주고받을 때 파일의 종류를 명확하게 구분하는 역할을 한다.
    즉, 브라우저나 서버가 이 파일이 어떤 형식인지 알 수 있도록 하는 정보이다.

    <script type="module" src="script.js"></script>
    • type="module"ES 모듈(JavaScript 모듈) 사용
    • 기본값은 type="text/javascript" (생략 가능)
    • 모듈 사용 예제
      <script type="module">
        import { hello } from "./module.js";
        hello();
      </script>

🌟 <script> 태그의 위치

일반적으로 script 태그는 두 가지 위치에서 사용된다.

  1. <head> 안에 배치
    <head>
      <script src="script.js"></script>
    </head>
    • 문제점
      • 스크립트가 실행될 때까지 HTML 파싱이 멈춘다.
      • 특히 외부 파일(src)이 크다면 페이지 로딩이 느려질 수 있다.
    • 해결 방법: defer 또는 async 사용
      <head>
        <script src="script.js" defer></script>
      </head>
  1. <body>의 맨 아래에 배치 (권장)
    <body>
      <h1>안녕하세요!</h1>
      <script src="script.js"></script>
    </body>
    • 장점
      • HTML이 완전히 로드된 후 JavaScript가 실행된다.
      • 렌더링 차단을 방지해서 더 빠르게 페이지가 표시된다.

🌟 여러 개의 <script> 태그를 사용할 때 주의할 점

  • async를 사용하면 실행 순서가 보장되지 않는다.
  • defer를 사용하면 순서가 유지된다.
  • DOM 조작이 필요한 경우에는 defer 속성을 추가하거나 <script> 태그를 <body> 아래에 배치하는 것이 안전하다.

🌟 <script> 태그를 <body>의 최하단에 위치시키는 게 좋은 이유

<script> 태그를 <body> 태그의 맨 아래에 배치하는 이유는 웹페이지의 성능과 사용자 경험(UX)을 개선하기 위해서이다.

  1. <script> 태그는 기본적으로 HTML 렌더링을 차단(blocking)한다.
    기본적으로 <script> 태그를 만나면, 브라우저는 HTML 파싱을 멈추고 JS 파일 다운로드 → 실행 완료 후 다시 HTML을 파싱한다.

    • 예제: <head><script>를 배치한 경우
      <!DOCTYPE html>
      <html lang="ko">
        <head>
          <script src="script.js"></script> <!-- 여기서 실행 차단 발생 -->
        </head>
        <body>
          <h1>안녕하세요!</h1>
        </body>
      </html>
      • 문제점
        • script.js 파일을 다운로드하고 실행하는 동안, 페이지 렌더링(화면 표시)이 멈춰 있다.
        • 만약 script.js가 크다면 로딩 속도가 크게 느려진다.
        • 특히, 사용자가 보는 화면이 늦게 표시되면 느린 사이트처럼 느껴질 수 있다.
  1. <script><body> 맨 아래 배치하면 렌더링이 먼저 완료된다.
    <!DOCTYPE html>
    <html lang="ko">
      <head>
        <title>최적화된 페이지</title>
      </head>
      <body>
        <h1>안녕하세요!</h1>
        <script src="script.js"></script> <!-- HTML이 먼저 로드된 후 실행됨 -->
      </body>
    </html>
    • 장점
      • HTML이 먼저 완전히 로드되므로 사용자가 빠르게 콘텐츠를 볼 수 있다.
      • JavaScript가 실행되더라도 렌더링이 이미 끝났기 때문에 UI 깜빡임이 없다.
  1. 브라우저의 HTML 파싱(렌더링) 과정과의 관계

    • 웹페이지 로딩 과정
      1) 브라우저가 HTML 문서를 위에서 아래로 읽는다.
      2) <script>를 만나면 HTML 파싱을 중단한다.
      3) JavaScript 파일을 다운로드 후 실행한다.
      4) JavaScript 실행이 끝나야 다시 HTML 파싱을 시작한다.
      5) 모든 HTMl이 로드되면 화면 렌더링이 완료된다.

    즉, <script> 태그가 상단에 있으면 그 시점에서 페이지가 멈추는 문제가 발생한다.


🌟 결론

  • 내부 스크립트 vs. 외부 스크립트
    • 내부 스크립트: <script> alert("안녕!"); </script>
    • 외부 스크립트: <script src="script.js"></script> (권장 방법)
  • 속성 정리
    속성설명실행 시점순서 보장
    없음HTML 파싱 중 스크립트 실행즉시X
    asyncHTML 파싱과 병렬 다운로드, 완료 즉시 실행즉시X
    deferHTML 파싱 후 실행 (DOMContentLoaded 직전)HTML 이후O
  • 위치 정리
    • <head> 안에서 async 또는 defer 사용
    • 가장 좋은 방법: <body> 맨 아래 배치

0개의 댓글