JavaScript 기초와 AI
AI와 함께 웹사이트에 인터랙티비티를 추가해요 — DOM 조작, 이벤트 핸들링, 폼 검증, 바닐라 JavaScript로 동적 콘텐츠 업데이트.
프리미엄 강좌 콘텐츠
이 레슨은 프리미엄 강좌의 일부예요. Pro로 업그레이드하면 모든 프리미엄 강좌와 콘텐츠를 이용할 수 있어요.
- 모든 프리미엄 강좌 이용
- 1000개 이상의 AI 스킬 템플릿 포함
- 매주 새로운 콘텐츠 추가
🔄 복습: 지난 레슨에서 CSS로 페이지를 스타일링했어요 — 반응형 레이아웃, 디자인 토큰, 다크 모드. 이제 JavaScript로 인터랙티비티를 추가해볼게요.
DOM 조작
DOM(Document Object Model)은 JavaScript가 HTML과 상호작용하는 방식이에요. 일반적인 DOM 작업에서 AI와 협력하는 방법을 알아봐요.
요소 선택과 수정
Write vanilla JavaScript to:
1. Select the element with id="hero-title" and change its text
2. Select all elements with class="card" and add a "featured" class to the first one
3. Create a new paragraph element, set its text content, and append it to the element with id="content"
Requirements:
- Use document.querySelector and document.querySelectorAll (not getElementById)
- Use textContent for safe text updates
- No external libraries
- Add comments explaining each step
동적 콘텐츠 생성
Write vanilla JavaScript to dynamically create a list of items from an array:
Data:
const items = [
{ title: "Item 1", description: "Description 1", category: "A" },
{ title: "Item 2", description: "Description 2", category: "B" },
// ... more items
];
Requirements:
- Create an unordered list element
- For each item, create an li containing the title in a strong tag and description in a paragraph
- Append the complete list to the element with id="item-list"
- Use document.createElement and textContent for safe DOM updates
- Use a document fragment for performance (batch DOM insertions)
Vanilla JavaScript only, no dependencies.
✅ 확인 질문: 여러 요소를 만들 때 document fragment를 사용하는 이유는?
페이지에 요소를 추가할 때마다 브라우저가 레이아웃을 다시 계산해요. 50개 항목을 하나씩 추가하면 50번의 재계산이 일어나요. document fragment는 보이지 않는 컨테이너예요 — 그 안에 모든 것을 빌드한 다음 한 번에 추가해요. 50번 대신 1번의 재계산이에요. AI가 하나씩 추가하는 접근법을 생성하는 경우가 있는데, 리스트가 커지면 성능 차이가 눈에 띄어요.
이벤트 핸들링
클릭 이벤트와 위임(Delegation)
Write vanilla JavaScript for an interactive FAQ accordion:
HTML structure:
- Multiple FAQ items, each with a question (button) and answer (div)
- Clicking a question toggles its answer visibility
- Only one answer open at a time (accordion behavior)
Requirements:
- Use event delegation (single listener on the parent container, not one per button)
- Toggle aria-expanded on the button
- Toggle a "hidden" class on the answer div
- Add smooth height transition with CSS class toggling
- Keyboard accessible (Enter and Space trigger toggle)
Vanilla JavaScript, no dependencies. Include the HTML structure in the output.
폼 검증
Write client-side form validation in vanilla JavaScript:
Form fields:
- Name (required, minimum 2 characters)
- Email (required, valid email format)
- Phone (optional, but if filled must match a phone pattern)
- Message (required, minimum 10 characters, maximum 500)
Validation behavior:
- Validate on form submit
- Show error messages below each invalid field using textContent (never inject raw HTML)
- Use aria-invalid and aria-describedby for accessibility
- Prevent form submission if any field is invalid
- Clear error messages when user starts correcting a field (input event)
- Show success message when form is valid
Vanilla JavaScript, no dependencies.
한국 웹사이트에서 흔히 보는 전화번호 형식(010-1234-5678)이나 사업자등록번호 같은 한국 특화 검증 패턴도 AI에게 요청할 수 있어요. 프롬프트에 “한국 전화번호 패턴 (010-XXXX-XXXX)” 같은 맥락을 추가하면 돼요.
로컬 스토리지 활용
Write vanilla JavaScript for a simple favorites/bookmarks feature:
Behavior:
- Each card has a heart/star button
- Clicking the button toggles the item as a favorite
- Favorites are saved to localStorage
- On page load, previously favorited items are restored
- A "View Favorites" filter shows only favorited items
Requirements:
- Store an array of item IDs in localStorage (JSON.stringify/parse)
- Handle the case where localStorage is unavailable (try-catch)
- Update button visual state (filled/outline) based on favorite status
- Include aria-pressed attribute on toggle buttons
Vanilla JavaScript, no dependencies.
✅ 확인 질문: localStorage가 사용 불가할 경우를 체크하는 이유는?
localStorage가 보장되지 않기 때문이에요. 프라이빗/시크릿 모드에서 차단될 수 있어요. 스토리지가 가득 차면 일부 브라우저가 비활성화해요. 기업 방화벽이 제한할 수 있어요. localStorage.setItem()이 항상 작동한다고 가정하면, 한 번의 차단된 호출로 모든 것이 멈춰요. localStorage 작업 주변의 try-catch는 페이지가 여전히 동작하도록 보장해요 — 세션 간에 즐겨찾기를 기억하지 못할 뿐이에요.
AI가 생성한 JavaScript의 보안 검토
AI 출력에서 이런 일반적인 취약점을 항상 확인하세요:
Review this JavaScript for security issues:
[paste your JavaScript]
Check for:
1. Unsanitized user data inserted into the DOM (XSS risk)
2. Dynamic code execution patterns (code injection risk)
3. Unvalidated URL parameters used in page logic
4. Sensitive data stored in localStorage without encryption
5. Missing input sanitization on form data
6. Event handlers that could be triggered maliciously
7. API keys or secrets hardcoded in client-side code
For each issue found, explain the risk and provide a secure alternative.
연습: 페이지에 인터랙티비티 추가하기
- 이벤트 위임을 사용해 FAQ 아코디언을 페이지에 추가하세요
- 최소 4개 필드가 있는 클라이언트 사이드 폼 검증을 만드세요
- localStorage 영속성이 있는 즐겨찾기 기능을 구현하세요
- 모든 JavaScript에 보안 검토 프롬프트를 실행하세요
- 키보드 내비게이션을 테스트하세요 — 마우스 없이 모든 기능을 사용할 수 있나요?
핵심 정리
- 프롬프트에 항상 “바닐라 JavaScript, 의존성 없음"을 명시해서 범용적으로 호환되는 코드를 얻으세요
- 안전한 텍스트 업데이트에는
textContent를 사용하고, DOM에 삽입하기 전에 모든 HTML 콘텐츠를 살균하세요 - 이벤트 위임(부모에 하나의 리스너)이 각 요소에 개별 리스너보다 효율적이고 유지보수하기 쉬워요
- document fragment로 DOM 삽입을 일괄 처리하면 동적 콘텐츠의 성능이 향상돼요
- localStorage, API 호출, JSON 파싱을 try-catch 블록으로 감싸세요 — 외부 작업이 성공한다고 가정하지 마세요
- AI가 생성한 JavaScript에서 살균되지 않은 사용자 데이터와 하드코딩된 시크릿을 확인하는 보안 검토를 항상 실행하세요
다음 레슨: 인터랙티브 기능을 만들고 외부 API에 연결해요 — 데이터 페칭, 응답 처리, 동적 웹 애플리케이션 만들기.
이해도 체크
먼저 위의 퀴즈를 완료하세요
레슨 완료!