HOWTO · HTML

JavaScript 파일을 HTML 파일에 연결

이 튜토리얼에서는 JavaScript 파일을 HTML 파일에 링크하는 방법을 소개합니다.

이 페이지의 내용

JavaScript를 HTML에 연결하려면 페이지에 <script> 요소를 추가합니다. src 속성으로 별도의 .js 파일을 불러오거나, 여는 태그와 닫는 태그 사이에 짧은 스크립트를 작성할 수 있습니다. DOM이 필요한 일반적인 페이지 스크립트는 <head>에 두고 defer를 사용하세요. 실행 순서가 중요하지 않은 독립적인 스크립트에는 async를 사용하면 됩니다.

src로 외부 JavaScript 파일 연결하기

JavaScript 파일을 만들고 HTML 문서에서 해당 파일을 참조합니다. 예를 들어 index.html과 app.js가 같은 디렉터리에 있으면, 다음 페이지가 app.js를 불러옵니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>External script example</title>
  <script src="./app.js" defer></script>
</head>
<body>
  <h1 id="message">Waiting for JavaScript</h1>
</body>
</html>

./app.js는 컴퓨터에서 JavaScript 파일이 있는 위치나 서버의 작업 디렉터리가 아니라, HTML 문서의 URL을 기준으로 해석되는 URL 경로입니다. 페이지와 같은 위치의 js 하위 디렉터리에 파일이 있다면 ./js/app.js를 사용하세요. 대소문자와 철자를 정확히 맞춰야 합니다. 대소문자를 구분하지 않는 개발 환경에서는 작동하던 경로가 대소문자를 구분하는 서버에서 실패할 수 있습니다. /js/app.js처럼 맨 앞에 슬래시가 있으면 사이트 URL의 루트부터 경로가 시작됩니다.

defer 속성을 사용하면 브라우저가 HTML을 파싱하는 동안 파일을 다운로드하고, 파싱이 끝난 뒤 스크립트를 실행합니다. 따라서 스크립트가 제목 요소를 찾을 때 해당 요소가 이미 준비되어 있습니다. 여러 페이지에서 같은 파일을 사용하거나 HTML과 JavaScript를 별도로 관리하려면 파일을 분리해 두세요.

이 예제를 실행해 보세요.

console.log("JavaScript loaded");

이 짧은 JavaScript 예제는 브라우저 콘솔에 메시지를 표시하는 독립적인 실행 예입니다. 변경하지 않은 예제의 콘솔 출력은 JavaScript loaded입니다. 페이지 예제에서는 app.js가 document.querySelector("#message")를 사용해 요소를 찾고, 요소가 있으면 textContent를 "JavaScript is connected"로 설정할 수 있습니다. 이 조건부 DOM 업데이트는 페이지에서 사용할 수 있도록 바꿔 쓴 예일 뿐, 실제로 실행해 얻은 결과를 주장하는 것은 아닙니다.

HTML 페이지에 JavaScript 직접 추가하기

한 페이지에서만 사용하는 짧은 동작이라면 <script> 요소 안에 JavaScript를 직접 작성할 수 있습니다. 필요한 마크업 뒤에 요소를 두세요. 대개 </body> 바로 앞이 적절합니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

<body>
  <h1 id="message">Waiting for JavaScript</h1>
  <script>
    const message = document.querySelector("#message");
    if (message) {
      message.textContent = "Inline JavaScript is connected";
    }
  </script>
</body>

브라우저가 제목을 파싱한 다음 스크립트에 도달하므로, 요소를 찾을 수 있습니다. 인라인 코드는 특정 페이지에서만 필요한 작은 동작에 편리합니다. 코드가 커지면 외부 파일이 재사용, 캐시, 유지 관리에 더 유리합니다. 일반적인 페이지 업데이트에는 document.write를 사용하지 마세요. 파싱이 끝난 뒤 호출하면 문서 전체를 바꿀 수 있습니다. 요소를 안전하게 변경하려면 textContent 같은 DOM 메서드를 사용하세요.

외부 스크립트의 실행 시점 선택하기

<head>에 둔 일반 외부 스크립트는 다운로드되고 실행되는 동안 HTML 파싱을 일시 중단합니다. 스크립트가 곧바로 본문 요소를 조회하면 해당 요소는 아직 파싱되지 않았을 수 있습니다. <body> 끝부분에 둔 스크립트는 앞선 마크업이 파싱된 뒤 실행되므로 작은 페이지에 적합할 수 있지만, 파일을 불러오고 실행하는 동안 브라우저가 파싱을 멈추는 점은 같습니다.

일반적으로 DOM에 의존하는 파일에는 <head>의 <script src="./app.js" defer></script>가 명확한 기본 선택입니다. 지연된 외부 스크립트는 HTML 파싱과 동시에 다운로드된 뒤, 파싱이 끝나면 문서에 나타난 순서대로 실행됩니다. 한 지연 스크립트가 다른 파일에 의존한다면 의존 대상 파일을 먼저 적으세요. defer는 외부 스크립트에 적용됩니다. 인라인 스크립트에 추가해도 해당 코드의 실행이 지연되지는 않습니다.

독립적인 파일, 예를 들어 단독 분석 스크립트에는 <script src="./analytics.js" async></script>를 사용하세요. 파일은 HTML 파싱과 동시에 다운로드되고 준비되는 즉시 실행되므로, 파싱이 끝나기 전에 실행될 수도 있습니다. 비동기 스크립트의 실행 순서는 보장되지 않고 페이지 요소가 준비되기 전에 실행될 수 있습니다. 따라서 서로 의존하거나 파싱된 DOM에 의존하는 스크립트에는 이 방식을 사용하지 마세요. async와 defer는 모두 외부 스크립트용입니다. 최신 브라우저에서 둘 다 지정하면 async 동작이 우선합니다.

스크립트 경로와 페이지 동작 확인하기

아무 일도 일어나지 않으면 먼저 src 값이 정확한지, HTML 페이지가 어디에서 제공되는지 확인하세요. 브라우저 개발자 도구의 Network 패널에서 스크립트 요청을 살펴보세요. 파일을 찾을 수 없다는 응답은 대개 경로, 파일 이름 또는 대소문자가 잘못되었음을 뜻합니다. Console 패널에는 JavaScript 구문 오류와 실행 중 오류가 표시됩니다. 수정한 뒤 페이지를 다시 로드해 최신 요청과 메시지를 확인하세요.

요청은 성공했는데 페이지가 바뀌지 않는다면 스크립트가 올바른 요소 ID를 조회하는지, 필요한 마크업이 생긴 뒤 실행되는지 확인하세요. <head>에 있는 DOM 의존 외부 스크립트에는 defer를 추가하거나, 짧은 인라인 스크립트를 요소 아래로 옮기세요. 여러 스크립트가 서로 상호작용한다면 async 대신 의존 순서에 맞춘 지연 스크립트를 사용하세요. 파일 다운로드가 성공했다는 사실은 브라우저가 파일을 찾았다는 뜻일 뿐, 스크립트가 오류 없이 끝까지 실행되었다는 뜻은 아닙니다.

자주 묻는 질문

JavaScript 파일 링크는 어디에 두어야 하나요? 페이지 DOM을 사용하는 일반적인 외부 스크립트라면 <head>에 두고 defer를 사용하세요. 본문 끝에 둔 스크립트도 앞서 나온 마크업에 접근할 수 있지만, 일반적인 head 스크립트는 본문이 파싱되기 전에 실행됩니다.

defer는 어떤 역할을 하나요? HTML 파싱을 중단하지 않고 외부 스크립트를 다운로드한 다음, 파싱이 끝난 뒤 지연 스크립트가 적힌 순서대로 실행합니다.

한 페이지에서 JavaScript 파일 여러 개를 연결할 수 있나요? 네. 파일마다 <script src="..." defer></script> 요소를 하나씩 추가하세요. 지연 스크립트는 문서 순서대로 실행되므로 공통 의존 파일을 이를 사용하는 파일보다 먼저 적으세요.

async와 defer는 어떻게 다른가요? 둘 다 병렬 다운로드를 허용합니다. defer는 파싱이 끝날 때까지 기다리고 문서 순서를 지킵니다. async는 각 파일이 준비되는 즉시 실행되며 순서를 지키지 않습니다.

type="text/javascript"를 지정해야 하나요? 아니요. HTML5에서는 JavaScript가 script 요소의 기본 형식이므로 일반적인 JavaScript에는 type이 필요하지 않습니다.