스크립트 및 이벤트 처리
컴포넌트 템플릿의 <script>
태그를 사용하여 브라우저로 JavaScript를 전송하고 Astro 컴포넌트에 기능을 추가할 수 있습니다.
스크립트는 React, Svelte, Vue와 같은 UI 프레임워크 없이 이벤트를 처리하거나 콘텐츠를 동적으로 업데이트하는 등 사이트에 상호 작용을 추가할 수 있습니다. 따라서 프레임워크 JavaScript의 오버헤드를 피할 수 있으며 모든 기능을 갖춘 웹사이트나 애플리케이션을 만들기 위해 다른 프레임워크를 학습할 필요가 없습니다.
클라이언트 측 스크립트
섹션 제목: “클라이언트 측 스크립트”스크립트를 사용하여 이벤트 리스너를 추가하고, 분석 데이터를 전송하고, 애니메이션을 재생하는 등 JavaScript가 웹에서 수행할 수 있는 모든 작업을 수행할 수 있습니다.
Astro는 번들링, TypeScript 등을 통해 HTML 표준 <script>
태그를 개선합니다. 자세한 내용은 Astro가 스크립트를 처리하는 방법을 참조하세요.
<button data-confetti-button>Celebrate!</button>
<script> // npm 패키지에서 가져옵니다. import confetti from 'canvas-confetti';
// 페이지에서 컴포넌트 DOM을 찾습니다. const buttons = document.querySelectorAll('[data-confetti-button]');
// 버튼을 클릭하면 confetti를 실행하는 이벤트 리스너를 추가합니다. buttons.forEach((button) => { button.addEventListener('click', () => confetti()); });</script>
스크립트 처리하기
섹션 제목: “스크립트 처리하기”기본적으로 <script>
태그는 Astro에서 처리됩니다.
기본적으로 Astro는 src
외에 다른 속성이 없는 <script>
태그를 다음과 같은 방식으로 처리합니다.
- TypeScript 지원: 모든 스크립트는 기본적으로 TypeScript입니다.
- 번들 가져오기: 함께 번들링된 로컬 파일 또는 npm 모듈을 가져옵니다.
- 타입 모듈: 처리된 스크립트는 자동으로
type="module"
이 됩니다. - 중복 제거:
<script>
가 포함된 컴포넌트가 한 페이지에서 여러 번 사용되면 스크립트는 오직 한 번만 포함됩니다. - 자동 인라인 처리: 스크립트가 충분히 작은 경우, Astro는 요청 횟수를 줄이기 위해 스크립트를 HTML에 직접 인라인 처리합니다.
<script> // 처리, 번들링 및 타입스크립트가 지원됩니다! // 로컬 스크립트를 가져올 수 있으며, npm 패키지에서 가져올 수도 있습니다.</script>
처리되지 않은 스크립트
섹션 제목: “처리되지 않은 스크립트”<script>
태그에 src
이외의 속성이 있는 경우 Astro는 이를 처리하지 않습니다.
is:inline
지시어를 추가하여 스크립트 처리를 의도적으로 거부할 수 있습니다.
<script is:inline> // 작성된 그대로 HTML로 렌더링됩니다! // 변환되지 않음: TypeScript 처리 및 Astro의 가져오기 경로 해석이 적용되지 않습니다. // 컴포넌트에서 사용하는 경우, 이 코드는 각 인스턴스마다 복제됩니다.</script>
페이지에 JavaScript 파일 포함
섹션 제목: “페이지에 JavaScript 파일 포함”스크립트를 별도의 .js
/.ts
파일로 작성하거나 다른 서버의 외부 스크립트를 참조해야 할 수도 있습니다. <script>
태그의 src
속성에서 이를 참조하여 수행할 수 있습니다.
로컬 스크립트 가져오기
섹션 제목: “로컬 스크립트 가져오기”사용 시기: 스크립트가 src/
디렉터리에 있을 때
Astro는 스크립트 처리 규칙에 따라 이러한 스크립트를 처리합니다.
<!-- `src/scripts/local.js`에 있는 스크립트의 상대 경로 --><script src="../scripts/local.js"></script>
<!-- 로컬 TypeScript 파일에도 작동합니다. --><script src="./script-with-types.ts"></script>
외부 스크립트 로드
섹션 제목: “외부 스크립트 로드”사용 시기: JavaScript 파일이 public/
또는 CDN에 있는 경우.
프로젝트의 src/
폴더 외부에 있는 스크립트를 로드하려면 is:inline
지시어를 포함하세요. 이 접근 방식은 위에서 설명한 대로 스크립트를 가져올 때 Astro에서 제공하는 JavaScript 처리, 번들링 및 최적화를 건너뜁니다.
<!-- `public/my-script.js`에 있는 스크립트의 절대 경로 --><script is:inline src="/my-script.js"></script>
<!-- 원격 서버의 스크립트에 대한 전체 URL --><script is:inline src="https://my-analytics.com/script.js"></script>
일반적인 스크립트 패턴
섹션 제목: “일반적인 스크립트 패턴”onclick
및 기타 이벤트 처리
섹션 제목: “onclick 및 기타 이벤트 처리”일부 UI 프레임워크는 이벤트 처리를 위해 onClick={...}
(React/Preact) 또는 @click="..."
(Vue)과 같은 사용자 정의 구문을 사용합니다. Astro는 표준 HTML을 더 밀접하게 따르며 이벤트에 사용자 정의 구문을 사용하지 않습니다.
대신 <script>
태그에서 addEventListener
를 사용하여 사용자 상호작용을 처리할 수 있습니다.
<button class="alert">Click me!</button>
<script> // 페이지에서 `alert` 클래스가 포함된 모든 버튼을 찾습니다. const buttons = document.querySelectorAll('button.alert');
// 각 버튼의 클릭을 처리합니다. buttons.forEach((button) => { button.addEventListener('click', () => { alert('Button was clicked!'); }); });</script>
한 페이지에 여러 <AlertButton />
컴포넌트가 있는 경우 Astro는 스크립트를 여러 번 실행하지 않습니다. 스크립트는 번들로 제공되며 페이지당 한 번만 포함됩니다. querySelectorAll
을 사용하면 이 스크립트가 페이지에 있는 alert
클래스를 가진 모든 버튼에 이벤트 리스너를 연결합니다.
사용자 정의 요소가 있는 웹 컴포넌트
섹션 제목: “사용자 정의 요소가 있는 웹 컴포넌트”웹 컴포넌트 표준을 사용하여 사용자 정의 동작으로 자신만의 HTML 요소를 만들 수 있습니다. .astro
컴포넌트에 사용자 정의 요소를 정의하면 UI 프레임워크 라이브러리 없이도 대화형 컴포넌트를 구축할 수 있습니다.
다음 예시에서는 하트 버튼을 클릭한 횟수를 추적하고 <span>
의 값을 최신 횟수로 업데이트하는 새 <astro-heart>
HTML 요소를 정의합니다.
<!-- 사용자 정의 요소 "astro-heart"에 컴포넌트 요소를 래핑합니다. --><astro-heart> <button aria-label="Heart">💜</button> × <span>0</span></astro-heart>
<script> // 새로운 유형의 HTML 요소에 대한 동작을 정의합니다. class AstroHeart extends HTMLElement { connectedCallback() { let count = 0;
const heartButton = this.querySelector('button'); const countSpan = this.querySelector('span');
// 버튼을 클릭할 때마다 개수를 업데이트합니다. heartButton.addEventListener('click', () => { count++; countSpan.textContent = count.toString(); }); } }
// <astro-heart> 요소에 AstroHeart 클래스를 사용하도록 브라우저에 지시합니다. customElements.define('astro-heart', AstroHeart);</script>
여기에서 사용자 정의 요소를 사용하면 두 가지 이점이 있습니다.
-
document.querySelector()
를 사용하여 전체 페이지를 검색하는 대신 현재 사용자 정의 요소 인스턴스에서만 검색하는this.querySelector()
를 사용할 수 있습니다. 이렇게 하면 한 번에 하나의 컴포넌트 인스턴스의 하위 항목으로만 작업하는 것이 더 쉬워집니다. -
<script>
는 한 번만 실행되지만 브라우저는 페이지에서<astro-heart>
를 찾을 때마다 사용자 정의 요소의connectedCallback()
메서드를 실행합니다. 즉, 한 페이지에서 이 컴포넌트를 여러 번 사용하려는 경우에도 한 번에 하나의 컴포넌트에 대한 코드를 안전하게 작성할 수 있습니다.
프런트매터 변수를 스크립트에 전달
섹션 제목: “프런트매터 변수를 스크립트에 전달”Astro 컴포넌트의 프런트매터 (---
펜스 내부)에 있는 코드는 서버에서 실행되며, 브라우저에서는 사용할 수 없습니다.
서버 측 변수를 클라이언트 측 스크립트에 전달하려면 변수를 HTML 요소의 data-*
속성에 저장하세요. 그러면 스크립트에서 dataset
속성을 사용하여 이 값에 액세스할 수 있습니다.
이 예시 컴포넌트에서 message
prop은 data-message
속성에 저장되므로 사용자 정의 요소는 this.dataset.message
를 읽고 브라우저에서 prop 값을 가져올 수 있습니다.
---const { message = 'Welcome, world!' } = Astro.props;---
<!-- message prop을 data 속성으로 저장합니다. --><astro-greet data-message={message}> <button>Say hi!</button></astro-greet>
<script> class AstroGreet extends HTMLElement { connectedCallback() { // data 속성에서 메시지를 읽습니다. const message = this.dataset.message; const button = this.querySelector('button'); button.addEventListener('click', () => { alert(message); }); } }
customElements.define('astro-greet', AstroGreet);</script>
이제 컴포넌트를 여러 번 사용할 수 있으며 각 컴포넌트마다 다른 메시지가 표시됩니다.
---import AstroGreet from '../components/AstroGreet.astro';---
<!-- 기본 메시지인 "Welcome, world!"를 사용하세요. --><AstroGreet />
<!-- props로 전달된 사용자 정의 메시지를 사용하세요. --><AstroGreet message="Lovely day to build components!" /><AstroGreet message="Glad you made it! 👋" />
이것은 실제로 React와 같은 UI 프레임워크를 사용하여 작성된 컴포넌트에 props를 전달할 때 Astro가 뒤에서 수행하는 작업입니다! client:*
지시어가 있는 컴포넌트의 경우 Astro는 HTML 출력에 서버 측 props를 저장하는 props
속성이 있는 <astro-island>
사용자 정의 요소를 생성합니다.
스크립트와 UI 프레임워크 결합하기
섹션 제목: “스크립트와 UI 프레임워크 결합하기”UI 프레임워크에 의해 렌더링되는 요소들은 <script>
태그가 실행될 때 아직 사용 가능하지 않을 수 있습니다. 스크립트에서 UI 프레임워크 컴포넌트도 처리해야 하는 경우 사용자 정의 요소를 사용하는 것이 좋습니다.