Chromium 156.0.8078.48. 본문의 HTML·CSS·JavaScript를 실제 브라우저로 렌더링하고 현재 화면을 캡처했습니다. 모든 조작·레이아웃·접근성을 검증한 것은 아닙니다.
이 글의 순서 4개 단락
이름을 입력하고 버튼을 누르면 화면의 문장이 바뀌는 작은 페이지를 만들어 보겠습니다. 콘솔에 값을 출력하는 대신 HTML 요소를 선택하고, 클릭이 일어났을 때 그 요소의 내용을 바꾸는 실습입니다. 실습 환경은 Chromium입니다.
화면과 클릭 동작 만들기
핵심은 버튼을 선택한 뒤 addEventListener('click', 함수)로 클릭할 때 실행할 함수를 등록하는 것입니다. 입력값이 비어 있거나 공백뿐이면 이름을 요청하고, 이름이 있으면 인사 문장을 표시합니다.
먼저 화면을 구성하는 HTML입니다. 아래 JavaScript와 함께 사용합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>인사 버튼 실습</title>
</head>
<body>
<main>
<h1>인사 문장 만들기</h1>
<label for="name">이름</label>
<input id="name" type="text" placeholder="이름을 입력하세요">
<button id="greet" type="button">인사하기</button>
<p id="result" aria-live="polite">이름을 입력하고 버튼을 눌러 보세요.</p>
</main>
</body>
</html>

다음은 보조 JavaScript입니다. 직접 하나의 HTML 문서로 실습한다면 아래 코드를 <script>와 </script> 사이에 넣어 </body> 바로 앞에 배치하세요. 그러면 입력창, 버튼, 결과 문단이 만들어진 뒤 코드가 실행됩니다.
const nameInput = document.querySelector('#name');
const greetButton = document.querySelector('#greet');
const result = document.querySelector('#result');
greetButton.addEventListener('click', () => {
const name = nameInput.value.trim();
if (name === '') {
result.textContent = '이름을 입력해 주세요.';
return;
}
result.textContent = `안녕하세요, ${name}님!`;
});
입력과 예상 화면 결과는 다음과 같습니다.
| 입력과 동작 | 예상 결과 문장 |
|---|---|
| 처음 페이지를 열었을 때 | 이름을 입력하고 버튼을 눌러 보세요. |
지민을 입력하고 인사하기 클릭 | 안녕하세요, 지민님! |
| 입력을 지우고 인사하기 클릭 | 이름을 입력해 주세요. |
| 공백만 입력하고 인사하기 클릭 | 이름을 입력해 주세요. |
클릭하면 왜 문장이 바뀔까?
document.querySelector('#greet')는 ID가 greet인 첫 요소를 찾습니다. #은 ID 선택자입니다. 같은 방식으로 입력창과 결과 문단도 선택합니다. 선택한 버튼의 addEventListener에 이벤트 이름 click과 함수를 전달하면, 버튼을 클릭할 때 그 함수가 호출됩니다. 함수를 등록하는 시점에는 함수 본문이 실행되지 않습니다. MDN의 addEventListener 설명을 참고하세요.
함수 안에서는 클릭할 때마다 입력창의 현재 value를 읽습니다. trim()은 문자열 양끝의 공백을 제거하므로 지민 은 지민으로, 공백뿐인 입력은 빈 문자열로 처리됩니다. textContent에 새 문자열을 대입하면 결과 문단의 기존 내용이 바뀝니다. 입력한 HTML 태그도 화면에 텍스트로 표시됩니다.
버튼에 type="button"을 지정한 것은 이 버튼의 역할을 일반 버튼으로 명확히 하기 위해서입니다. 나중에 폼 안으로 옮겨도 제출 버튼으로 동작하지 않습니다.
요소를 찾지 못할 때 비교하기
querySelector는 유효한 선택자에 일치하는 요소가 없으면 null을 반환합니다. 문법 자체가 잘못된 선택자는 null 대신 예외를 발생시킵니다. 다음 두 경우는 결과가 같아 보여도 확인할 곳이 다릅니다. 각각 독립적으로 재현한 뒤 원래 코드로 되돌려 보세요.
선택자가 다른 경우
완성 예제의 버튼 선택 줄만 다음처럼 바꾸세요. HTML의 버튼 ID는 여전히 greet입니다.
const greetButton = document.querySelector('#greeting');
console.log(greetButton); // 예상: null
나머지 코드를 그대로 두고 새로고침하면 greetButton.addEventListener(...)에서 null의 속성을 읽을 수 없다는 TypeError가 발생할 것으로 예상됩니다. 클릭 함수가 등록되지 않으므로 버튼을 눌러도 처음 안내 문장이 유지됩니다. Chromium 개발자 도구의 Console에서 null과 오류를 확인하고, 선택자를 #greet로 고치세요. 오류 문구의 정확한 표현은 브라우저에 따라 다를 수 있습니다.
코드가 너무 일찍 실행되는 경우
다음은 별도의 최소 HTML입니다. script가 실행될 때 버튼은 아직 문서에 만들어지지 않았습니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>실행 시점 확인</title>
<script>
const button = document.querySelector('#greet');
console.log(button); // 예상: null
button.addEventListener('click', () => console.log('클릭'));
</script>
</head>
<body>
<button id="greet" type="button">인사하기</button>
</body>
</html>
예상되는 콘솔 결과는 null 다음의 TypeError입니다. 이후 버튼이 화면에 나타나더라도 실패한 이벤트 등록이 자동으로 다시 실행되지는 않습니다. 클릭해도 클릭은 출력되지 않습니다.
해결하려면 이 예제의 <script>...</script> 전체를 버튼 다음, </body> 바로 앞으로 옮겨 새로고침하세요. 이제 버튼 선택 결과는 해당 버튼 요소이고 클릭할 때마다 콘솔에 클릭이 출력될 것으로 예상됩니다. 이처럼 일반 인라인 스크립트의 위치를 요소 뒤로 옮기는 방법을 사용할 수 있습니다. 스크립트 요소와 실행 방식은 MDN script 문서를 참고하세요.
선택자가 맞는데도 null이 나온다면 철자뿐 아니라 코드가 실행되는 시점도 살펴보세요. greetButton.addEventListener('click', 인사하기())처럼 함수를 호출해 결과를 전달하는 실수도 피해야 합니다. 이벤트가 일어났을 때 실행할 함수 자체를 전달해야 합니다.
연습: 긴 이름에 안내하기
완성 예제에서 공백을 제거한 이름이 10자를 초과하면 인사 대신 이름은 10자 이하로 입력해 주세요.를 표시해 보세요. 빈 입력 처리는 그대로 유지합니다. 예를 들어 가나다라마바사아자차카를 입력하면 안내 문장이 나와야 합니다.
풀이에서는 빈 입력 검사 뒤, 인사 문장 대입 전에 다음 조건을 추가합니다.
if (name.length > 10) {
result.textContent = '이름은 10자 이하로 입력해 주세요.';
return;
}
return은 현재 클릭 함수의 실행을 끝내므로 뒤의 인사 문장이 안내 문장을 덮어쓰지 않습니다. 이 연습의 length는 JavaScript 문자열의 UTF-16 코드 단위 수를 세므로 일부 이모지처럼 눈에 보이는 글자 수와 다를 수 있습니다.
CHECK THE SOURCE
참고한 공식 문서
기능 설명은 위 문서를 참고했으며, 예제의 입력·결과와 한계는 본문에 따로 기록했습니다.