콘텐츠로 이동

03. JavaScript: 웹의 근육

"HTML이 뼈대, CSS가 화장이라면, JS는 움직이는 근육입니다."

여러분, 파이썬은 컴퓨터 내부의 CPU한테 일을 많이 시킵니다. '이거 계산해', '이거 분석해' 하면서요.

반면에 자바스크립트는 브라우저(크롬)한테 명령을 내리는 언어입니다. 그래서 자바스크립트 명령어의 80%는 '저기 있는 버튼 색깔 바꿔', '이미지 숨겨', '경고창 띄워' 같은 화면 조작 명령입니다.

즉, 자바스크립트는 '정적인 화면을 뜯어고치는 리모컨'이라고 생각하면 됩니다.

1. Why: 브라우저의 유일한 언어

여러분이 파이썬 고수라도 브라우저 내부를 파이썬으로 조종할 수는 없습니다. (크롬은 파이썬을 모릅니다.) JavaScript(JS)는 브라우저가 이해하는 유일한 프로그래밍 언어이자, 정적인 웹페이지에 생명을 불어넣는 도구입니다.

2. Python vs JavaScript: 번역기 돌리기

파이썬과 문법이 조금 다르지만, 논리(Logic)는 똑같습니다. 가장 큰 차이점은 파이썬의 들여쓰기(Indentation) 대신 중괄호 { }를 사용하여 구역을 나눈다는 점입니다.

개념 Python 🐍 JavaScript ☕️ 차이점
변수 선언 name = "Kim" let name = "Kim"; let으로 시작, ;로 끝남
상수 선언 (없음/관습) const PI = 3.14; 절대 변하지 않는 값
함수 정의 def hello(): function hello() { } 중괄호 { }가 핵심!
출력 print("Hi") console.log("Hi"); 개발자 도구 콘솔에 찍힘
조건문 if x == 1: if (x === 1) { } 등호 3개(===) 사용 권장

AI Native Tip

JS 문법을 달달 외우지 마세요. AI에게 "버튼을 누르면 배경색이 바뀌는 로직을 자바스크립트로 짜줘"라고 하고 싶은 일(Logic)을 설명하세요. 여러분의 한국어 명령이 곧 코드가 됩니다.

3. DOM: HTML을 객체로 만들기

JS가 HTML을 조작하려면, HTML 태그를 JS가 이해할 수 있는 객체(Object)로 변환해야 합니다. 이를 DOM (Document Object Model)이라고 합니다. 파이썬의 BeautifulSoup을 써보셨다면 이해가 빠를 것입니다.

최신 자바스크립트에서는 CSS 선택자를 그대로 쓸 수 있는 querySelector를 주로 사용합니다.

// 1. HTML에서 id가 'title'인 녀석을 잡아온다 (Select)
// CSS처럼 #을 붙여서 ID를 찾습니다.
const title = document.querySelector("#title");

// 2. 내용을 바꾼다 (Manipulate)
title.innerText = "반갑습니다!";
title.style.color = "blue";

4. Event: 낚시찌 던지기 (Event-Driven)

파이썬 스크립트는 실행(Run)하면 위에서 아래로 쭉 실행되고 끝납니다. 하지만 웹사이트는 다릅니다. 사용자가 "클릭할 때까지" 혹은 "스크롤할 때까지" 잠복해서 기다려야 합니다.

이것을 이벤트 리스너(Event Listener)라고 합니다.

sequenceDiagram
    participant User as 👤 사용자
    participant JS as 🟡 JavaScript
    participant Screen as 🖥️ 화면

    Note right of JS: 1. 함정 설치 (addEventListener)
    User->>JS: 2. 버튼 클릭! (Event 발생)
    JS->>Screen: 3. "로그인 성공" 알림창 띄움 (Function 실행)
// CSS처럼 .을 붙여서 클래스를 찾거나, 태그 이름으로 찾을 수 있습니다.
const btn = document.querySelector("#login-btn");

// "click"이라는 물고기가 물 때까지 기다림
btn.addEventListener("click", () => {
    alert("클릭되었습니다!");
});

5. Fetch: 데이터 배달시키기 (비동기 통신)

이 부분이 자바스크립트의 핵심이자 가장 어려운 난관입니다. 날씨 정보나 주식 데이터 같은 외부 데이터를 가져오려면 서버에 요청을 보내야 합니다. 이때 사용하는 함수가 fetch (가져오다)입니다.

하지만 여기서 JS만의 독특한 성격인 '비동기(Asynchronous)'가 등장합니다.

☕️ 비유: 자판기 vs 스타벅스

1. 동기(Synchronous) = 자판기 파이썬은 기본적으로 자판기와 같습니다. 동전을 넣고 음료수가 덜컹 하고 나올 때까지 자판기 앞에서 꼼짝 못 하고 기다려야 합니다. 앞사람이 음료를 꺼내기 전까진 뒷사람은 아무것도 못 합니다.

즉, 데이터가 올 때까지 프로그램 전체가 멈춥니다.

2. 비동기(Asynchronous) = 스타벅스 자바스크립트는 스타벅스입니다. 점원(JS)은 주문을 받고 진동벨을 준 뒤, 커피가 나오기를 기다리지 않고 바로 다음 손님을 받습니다. 여러분이 자리에 앉아서 유튜브를 보고 있으면(다른 코드 실행), 언젠가 징- 하고 진동벨이 울립니다(데이터 도착).

⏳ 왜 'await(기다려)'가 필요한가요?

문제는 성격 급한 자바스크립트 때문에 발생합니다. JS는 fetch(주문)를 하자마자, 데이터가 도착했는지 확인도 안 하고 바로 다음 줄인 console.log(마시기)를 실행해버립니다.

커피가 안 나왔는데 마시려고 하면 어떻게 될까요? 빈 컵(Undefined)만 들이키게 됩니다. 그래서 우리는 JS에게 "야, 딴짓하지 말고 일단 데이터 올 때까지 여기서 딱 기다려!" 라고 명령해야 합니다. 그 주문이 바로 await입니다.

💻 코드로 이해하기

AI에게 코드를 맡길 때도 이 구조를 알면 훨씬 편합니다.

// async: "이 함수 안에는 기다려야 할 작업(await)이 있어요"라고 미리 알리는 표시
async function getKoreaWeather() {

    console.log("1. 기상청에 날씨 데이터를 주문합니다...");

    // fetch: 주문 넣기
    // await: "진동벨 울릴 때(데이터 올 때)까지 밑으로 내려가지 마!" 라고 붙잡는 역할
    const response = await fetch("https://api.weather.com/seoul");

    // (여기서 몇 초간 대기함...)

    console.log("2. 데이터 도착! 포장을 뜯습니다(JSON 변환).");
    const data = await response.json(); // 포장 뜯는 것도 시간이 걸리니 기다림(await)

    console.log("3. 이제 화면에 보여줍니다:", data); 
}

🚫 가장 많이 하는 실수

초보자들이 가장 많이 하는 실수는 await를 빼먹는 것입니다.

  • await 있음: 데이터가 올 때까지 기다렸다가 data 변수에 담습니다. (성공)
  • await 없음: 주문하자마자 변수에 담으려 합니다. 데이터는 아직 오지도 않았는데 말이죠. 결과는 Promise { <pending> } (주문서) 이라고만 출력됩니다. 내용물이 아니라 영수증만 손에 쥐게 되는 꼴입니다.

🧠 Visible Thinking Activity: 콘솔에서 시간 지배하기

JS의 비동기 성질을 직접 체험해봅시다.

  1. 브라우저에서 F12를 눌러 Console 탭을 엽니다.
  2. 아래 코드를 복사해서 붙여넣고 엔터를 치세요. ( allow pasting 입력 필요할 수 있음)
console.log("1. 주문하신");
setTimeout(() => {
    console.log("2. 커피 나왔습니다! (3초 뒤)");
}, 3000);
console.log("3. 자리에 앉으세요.");
  • 예상 결과: 1 -> 2 -> 3 순서로 나올 것 같나요?
  • 실제 결과: 1 -> 3 -> (3초 뒤) -> 2
  • 의미: JS는 커피가 나올 때까지(3초) 손님을 카운터 앞에 세워두지 않습니다. 일단 자리에 앉히고(3번 실행), 커피가 다 되면 부릅니다(2번 실행). 이것이 웹의 속도 비결입니다.

🕹️ 실습 1: 3분 만에 내 사이트 움직이게 하기 (Interaction)

이제 마지막 단계입니다. 멈춰있는 내 사이트에 전용 두뇌(script.js)를 연결해 봅시다.

Step 1. 외부 JS 파일 만들기

  1. 작업 중인 폴더에 script.js라는 이름의 새 파일을 만듭니다.
  2. 아래 코드를 복사해서 넣고 저장(Ctrl + S)하세요. (이때 <script> 태그는 적지 않고 코드만 넣습니다.)
/* script.js */
// 페이지의 '첫 번째' 버튼을 찾아 클릭 이벤트를 연결합니다.
const myButton = document.querySelector("button");

if (myButton) { 
    myButton.addEventListener("click", () => {
        alert("환영합니다! 외부 JS 파일이 성공적으로 연결되었습니다.");
    });
}

Step 2. HTML과 JS 연결하기 (Src)

이제 HTML에게 "네 뇌는 script.js 파일에 들어 있어"라고 알려줘야 합니다. index.html 파일의 </body> 태그 바로 위에 아래 한 줄을 추가하세요.

<body>
    <script src="script.js"></script>
</body>

Step 3. 확인 및 수정

브라우저를 새로고침한 뒤 버튼을 클릭해 보세요. 알림창이 뜬다면 성공입니다!

  • 주의: src="script.js"에서 파일 이름과 경로가 정확한지 꼭 확인하세요.

🕹️ 실습 2: 실시간 날씨 데이터 가져오기 (API Fetch)

단순히 글자만 바꾸는 게 아니라, 진짜 실시간 데이터를 인터넷 너머에서 배달시켜 봅시다.

Step 1. HTML에 날씨 정보를 표시할 자리 만들기

먼저 index.html에서 날씨가 나타날 빈 공간을 하나 만들어줍니다.

<div class="container">
    <h1 id="title">오늘의 날씨</h1>
    <p id="weather-info">버튼을 눌러 날씨를 확인하세요!</p>
    <button id="weather-btn">날씨 불러오기 🌤️</button>
</div>

<script src="script.js"></script>

Step 2. script.js에 비동기 함수 작성하기

기존 내용을 지우고 아래의 fetch 로직을 넣습니다. (연습용 오픈 API를 사용합니다.)

/* script.js */
const weatherBtn = document.querySelector("#weather-btn");
const weatherInfo = document.querySelector("#weather-info");

// 1. 주문을 수행할 함수 (async)
async function getWeather() {
    weatherInfo.innerText = "데이터 배달 중... 🚚";

    try {
        // 2. 실제 데이터 요청 (await)
        // 위도 37.5, 경도 126.9(서울)의 날씨를 가져옵니다.
        const response = await fetch("https://api.open-meteo.com/v1/forecast?latitude=37.5&longitude=126.9&current_weather=true");

        // 3. 포장 뜯기 (await)
        const data = await response.json();

        // 4. 화면에 뿌리기
        const temp = data.current_weather.temperature;
        weatherInfo.innerText = `현재 서울의 온도는 ${temp}도입니다!`;

    } catch (error) {
        weatherInfo.innerText = "날씨를 가져오지 못했어요. 😢";
    }
}

// 5. 버튼을 클릭하면 함수 실행
weatherBtn.addEventListener("click", getWeather);

🧠 이 실습의 핵심 포인트

  1. 데이터는 '비어있는 컵'이다: 처음에 HTML에는 아무 데이터가 없습니다. 사용자가 버튼을 눌러야 비로소 인터넷에서 데이터를 채워 넣습니다.
  2. await가 없으면? 만약 await를 빼면, 데이터가 도착하기도 전에 화면에 온도를 그리려고 해서 undefined나 에러가 뜹니다. "커피가 나오기 전엔 컵을 들지 마라!"라고 설명해 주세요.
  3. 실제 통신의 체감: 로컬 컴퓨터가 아니라 외부 서버(open-meteo.com)와 대화하고 있다는 사실이 학생들에게는 큰 성취감을 줍니다.

💡 AI Native Tip: 에러 처리 부탁하기

학생들이 실습하다 보면 인터넷 연결 문제 등으로 에러가 날 수 있습니다. 이때 AI에게 이렇게 물어보게 유도해 보세요.

Prompt

지금 날씨 API를 연동했는데, 데이터를 불러오는 동안 '로딩 중...' 애니메이션을 보여주고 싶어. 그리고 만약 인터넷이 끊겼을 때 보여줄 예쁜 에러 메시지 창도 script.js에 추가해줘.

이렇게 하면 단순히 코드를 따라 치는 것을 넘어, '사용자 경험(UX)'까지 생각하는 개발자로 한 걸음 더 나아갈 수 있습니다.


💡 왜 JavaScript를 파일로 분리하나요?

  1. HTML의 간결함: HTML은 웹사이트의 '뼈대'에만 집중하고, 복잡한 '동작' 로직은 전용 파일에서 관리할 수 있습니다.
  2. 캐싱(Caching)을 통한 속도 향상: 브라우저는 한 번 불러온 .js 파일을 저장(캐시)해둡니다. 사용자가 다른 페이지로 이동해도 같은 파일을 다시 다운로드하지 않아도 되므로 사이트가 더 빨라집니다.
  3. 코드의 재사용: 로그인 로직이나 메뉴 애니메이션 같은 공통 기능을 하나의 .js 파일에 만들어두고 여러 HTML 페이지에서 돌려 쓸 수 있습니다.

🚀 마무리: 이제 AI에게 '전체 마법'을 맡겨보세요

이제 파일 구조(index.html, style.css, script.js)가 완벽하게 잡혔습니다. AI에게 프롬프트를 보낼 때 이렇게 말해보세요.

AI Native Prompt

지금 내 프로젝트는 index.html, style.css, script.js 세 개로 나뉘어 있어. 1. style.css에는 다크 모드 디자인을 추가해주고, 2. script.js에는 사용자의 OS 설정에 따라 자동으로 다크 모드를 전환하거나 버튼으로 껐다 켰다 하는 기능을 넣어줘. 각 파일에 들어갈 코드를 따로 정리해줘.


💡 (Bonus) TMI: 왜 이름이 자바스크립트인가요?

자바스크립트(JavaScript)라는 이름이 붙은 이유는 한마디로 요약하자면 "당시 가장 잘나가던 언어의 명성에 올라타기 위한 마케팅 전략" 때문입니다.

1. 원래 이름은 '모카(Mocha)'였다?

1995년, 넷스케이프(Netscape)라는 회사의 브랜던 아이크(Brendan Eich)가 웹 브라우저에서 동작하는 동적인 언어를 단 10일 만에 만들었습니다. 처음에는 모카(Mocha)였다가, 얼마 후 라이브스크립트(LiveScript)라는 이름으로 바뀌었습니다.

2. 왜 하필 '자바(Java)'인가?

당시 프로그래밍 세계에서 가장 핫했던 언어는 자바(Java)였습니다. 넷스케이프는 자신들이 만든 이 새로운 언어가 자바만큼 인기를 끌기를 바랐습니다. 그래서 자바스크립트(JavaScript)로 이름을 바꾸게 됩니다. (마치 코카콜라가 잘 팔리니 '코카-주스'라고 이름을 지은 것과 같습니다.)

Q. 자바와 자바스크립트는 가족인가요?

A. 아니요, 완전히 남남입니다. 프로그래밍 세계에서는 이런 농담이 있습니다. "자바와 자바스크립트의 관계는 '인도'와 '인도네시아', 혹은 '바다코끼리'와 '코끼리'의 관계와 같다."

3. 진짜 이름은 'ECMAScript'

이후 표준 전쟁이 벌어지자, 공식 명칭은 ECMAScript(ES)로 정해졌습니다. 우리가 흔히 듣는 ES6, ES2020 같은 용어들이 바로 자바스크립트의 '공식 버전 이름'입니다.