
1. Spread와 Rest
1. 개념
Spread와Rest는 둘 다...모양을 쓰지만 역할은 반대다.
겉모양은 같지만 실제로는 하나는 펼치고, 하나는 모은다고 이해해야 한다.
Spread는 배열이나 문자열처럼 여러 요소를 가진 값을 하나씩 펼쳐서 사용하는 문법이다.
예를 들면 배열 안의 값을 함수 인수로 넘기거나, 여러 배열을 합쳐 새 배열을 만들 때 자주 쓴다.
반대로Rest는 여러 값을 하나로 모아서 받는 문법이다.
배열 구조 분해에서는 앞의 몇 개를 따로 받고 나머지를 한 배열로 모을 때 쓰고, 함수에서는 몇 개가 들어올지 모르는 인수들을 한 번에 받을 때 쓴다.즉, 먼저 이 기준을 잡으면 된다.
Spread→ 묶여 있는 값을 펼쳐서 사용한다.Rest→ 여러 값을 하나로 모아서 받는다.
이 기준만 정확히 잡히면 뒤에서 함수의 가변 인수까지 자연스럽게 이어진다.
2. Spread 문법
핵심 특징
Spread는 배열 전체를 한 번에 넘기는 것이 아니라,
배열 안의 요소를 쉼표로 나열한 것처럼 펼쳐서 사용하게 해 준다.
예를 들어Math.min()은 숫자들을 각각 받아야 하는데,
배열을 그냥 넣으면 원하는 방식으로 동작하지 않는다.
이럴 때...배열을 쓰면 배열 안의 값이 하나씩 꺼내져 들어간다.
배열 합칠 때도 마찬가지다.
기존에는concat()같은 메서드로 합칠 수 있었지만,
Spread를 쓰면 배열 안에 직접 끼워 넣는 형태로 더 직관적으로 합칠 수 있다.
즉,Spread는 함수 호출에도 쓰이고, 배열 생성에도 쓰인다는 점을 같이 봐야 한다.
3. 코드 예제예제:
SpreadArrayTest1const prices = [29, 39, 9, 114]; console.log(Math.min(...prices)); // prices 배열을 펼쳐서 29, 39, 9, 114처럼 전달한다. // 출력결과 // 9 const arr1 = [3, 5, -10]; const arr2 = [6, 2, -7, 3, 5]; console.log(Math.max(3, ...arr1, 10, ...arr2, 11)); // 배열 두 개를 각각 펼쳐서 최대값을 구한다. // 출력결과 // 11 const fruits = ["apple", "mango", "pineapple"]; const allFruits = ["grapes", ...fruits, "strawberry"]; console.log(allFruits); // 기존 배열의 요소를 펼쳐서 새 배열 안에 자연스럽게 넣는다. // 출력결과 // ["grapes", "apple", "mango", "pineapple", "strawberry"]이 코드는
Spread가 어디에서 편한지 가장 기본적으로 보여 준다.
Math.min(...prices)에서는 배열을 숫자 목록처럼 펼쳐서 넘긴다.
즉,prices자체를 통째로 주는 것이 아니라, 그 안의 값들을 하나씩 꺼내서 주는 것이다.그리고 배열 합치기 예제에서는
...fruits가 배열 안에 바로 들어간다.
그래서"grapes"다음에fruits의 요소들이 차례대로 들어가고, 마지막에"strawberry"가 붙는다.이 예제의 핵심은
Spread를 사용하면 기존 배열의 요소를 펼쳐서 새 배열이나 함수 인수 목록 안에 자연스럽게 넣을 수 있다는 점이다.
예제:
SpreadArrayTest2const original = [1, 2, 3]; const copy = [...original]; console.log(copy); // original 배열의 요소를 펼쳐서 새 배열로 복사한다. // 출력결과 // [1, 2, 3]이 예제는
Spread가 배열 합치기뿐 아니라
기존 배열을 바탕으로 새 배열을 만들 때도 자주 쓰인다는 점을 보여 준다.
4. 문자열과 Set에도Spread를 쓸 수 있다배열에서만
Spread가 되는 것은 아니다.
문자열도 글자들이 순서대로 이어져 있기 때문에 펼칠 수 있고,Set도 반복 가능한 자료형이므로 펼칠 수 있다.즉, 이 부분은 결국 반복 가능한 값이면 펼칠 수 있다는 감각을 잡게 해 준다.
예제:
SpreadIterableTest1const text = "korea"; console.log(...text); // 문자열을 펼치면 글자가 하나씩 나온다. // 출력결과 // k o r e a console.log([...text]); // 문자열을 펼쳐서 배열로 만들 수 있다. // 출력결과 // ["k", "o", "r", "e", "a"] const animals = new Set(["tiger", "lion", "dog", "cat"]); animals.add("hippo"); const animalArray = [...animals]; console.log(animalArray); // Set 안의 값을 펼쳐서 배열로 바꾼다. // 출력결과 // ["tiger", "lion", "dog", "cat", "hippo"]여기서 중요한 것은
Spread가 단순히 배열 전용 문법이 아니라, 반복 가능한 값을 펼쳐서 꺼내 쓰는 문법이라는 점이다.그래서 이 구간은 뒤에서
for...of, 배열 구조 분해,Rest Parameter까지 연결되는 준비 단계라고 보면 된다.
5. Rest 문법이번에는 같은
...이지만 방향이 반대다.
Rest는 펼치는 것이 아니라
남는 값들을 하나로 모아서 받는 문법이다.배열 구조 분해에서 보면 이 차이가 가장 잘 보인다.
앞의 값은 하나씩 따로 받고, 나머지 값들은 배열 하나로 묶을 수 있다.
즉,Rest는 남는 요소들을 모아 두는 역할이라고 보면 된다.배열 구조 분해에서
Rest는 남는 값을 한 번에 모으는 역할이므로 마지막 위치에 와야 한다.예제:
RestArrayTest1const friends = ["둘리", "또치", "도우너", "고길동", "희동이"]; const [first, second, ...others] = friends; console.log(first); // 첫 번째 요소를 따로 받는다. // 출력결과 // 둘리 console.log(second); // 두 번째 요소를 따로 받는다. // 출력결과 // 또치 console.log(others); // 남은 요소들은 others 배열 하나로 묶인다. // 출력결과 // ["도우너", "고길동", "희동이"]이 코드는
Rest를 배열에서 이해할 때 가장 기본이 되는 형태다.즉,
- 앞에서 필요한 값은 하나씩 꺼내고
- 뒤에서 남는 값은 배열 하나로 모은다
라는 구조다.
그래서
Spread와Rest를 같이 볼 때는
같은...이지만 역할이 다르다는 점을 먼저 구분해야 한다.
6. 헷갈리기 쉬운 부분초보자가 가장 많이 헷갈리는 것은
Spread와Rest를 문법 모양만 보고 같은 기능이라고 생각하는 것이다.하지만 실제로는 반대다.
Math.min(...prices)→ 값을 펼쳐서 사용한다.const [a, ...rest] = arr→ 남는 값을 모아서 받는다.또 문자열을 펼친다고 해서 문자열이 배열인 것은 아니다.
다만 글자를 순서대로 꺼낼 수 있기 때문에Spread가 가능한 것이다.
2. 가변 인수 처리와 Rest Parameter
1. 개념함수를 만들 때는 보통 매개변수 개수를 정해 두지만,
실제로는 몇 개가 들어올지 미리 정하기 어려운 경우도 있다.예를 들어 숫자를 몇 개 받을지 모르는
sum()같은 함수는
sum(10),sum(10, 20),sum(10, 20, 30)처럼 다양한 형태로 호출될 수 있다.즉, 이 구간의 핵심은
함수는 인수 개수가 딱 맞아야만 호출되는 구조가 아니며, 들어온 인수를 어떻게 처리할지가 더 중요하다는 점이다.
2. arguments
arguments는 함수에 실제로 들어온 인수들을 모아 두는 내장 객체다.즉, 함수를 만들 때 매개변수를 몇 개 적었는지보다
실제로 몇 개가 들어왔는지 확인해야 할 때arguments를 본다고 이해하면 된다.예제:
exam18function out() { document.write("아규먼트 갯수 : " + arguments.length + "<br>"); // 실제로 전달된 인수 개수를 출력한다. for (let i = 0; i < arguments.length; i++) { console.log(arguments[i]); // 전달된 인수를 순서대로 확인한다. } console.log("-----------------------"); } out(); out(10); out(10, 20); out("a", "b", "c"); out(1, 2, 3, 4, 5, 6, 7, 8); // 출력결과 // 아규먼트 갯수 : 0 // 아규먼트 갯수 : 1 // 아규먼트 갯수 : 2 // 아규먼트 갯수 : 3 // 아규먼트 갯수 : 8이 예제는 함수 이름은 하나지만,
호출할 때 들어오는 인수 개수는 계속 달라질 수 있다는 점을 보여 준다.
그리고 그 차이를arguments.length로 바로 확인한다.여기서 먼저 잡아야 할 것은
arguments가 들어온 값을 통째로 확인하는 용도라는 점이다.
3. arguments로 합계 구하기
arguments를 쓰면 실제로 전달된 값 전체를 순회하면서 계산하는 것도 가능하다.예제:
exam18_1function sum() { let result = 0; for (let i = 0; i < arguments.length; i++) { result += arguments[i]; // 전달된 값을 하나씩 더해서 총합을 만든다. } return result; // 최종 합계를 호출한 곳으로 돌려준다. } console.log(sum()); console.log(sum(10)); console.log(sum(10, 20)); console.log(sum(10, 20, 30)); // 출력결과 // 0 // 10 // 30 // 60이 예제는
arguments가 단순히 개수만 보는 객체가 아니라,
가변 인수 처리의 기본 재료가 된다는 점을 보여 준다.다만 여기서 한 단계 더 생각해 보면,
arguments는 배열처럼 보이지만 완전한 배열처럼 쓰기에는 어색하다.
그래서 뒤에서Rest Parameter가 더 깔끔한 방식으로 등장한다.
4. Rest Parameter
Rest Parameter는 함수 매개변수 앞에...을 붙여서
들어오는 여러 인수를 진짜 배열로 받는 방식이다.이제는
arguments를 따로 꺼내 보지 않고, 처음부터 특정 이름의 배열에 모든 값이 들어온다고 보면 된다.즉,
- 예전 방식 →
arguments- 더 읽기 쉬운 방식 →
Rest Parameter라고 이해하면 된다.
Rest Parameter는 여러 남는 값을 한 번에 모으는 역할이므로, 매개변수 목록의 마지막에만 올 수 있다.예제:
exam18_3function sum(...nums) { let result = 0; for (let i = 0; i < nums.length; i++) { result += nums[i]; // nums 배열 안의 값을 하나씩 더한다. } return result; // 계산된 총합을 반환한다. } console.log(sum()); console.log(sum(10)); console.log(sum(10, 20)); console.log(sum(10, 20, 30)); // 출력결과 // 0 // 10 // 30 // 60이 코드는 방금 본
arguments버전과 결과는 같지만,
읽는 느낌이 훨씬 더 분명하다.
nums라는 이름만 봐도
“여러 숫자를 배열로 받아서 계산하는구나”가 바로 보이기 때문이다.그래서
Rest Parameter는
가변 인수 처리 의도를 코드에서 더 또렷하게 드러내는 방식이라고 이해하면 좋다.
5. 고정 인수와 가변 인수를 함께 받기
Rest Parameter가 더 편해지는 이유는
앞쪽에 고정 역할의 인수를 두고, 뒤쪽에만 가변 인수를 둘 수 있기 때문이다.즉, 앞의 값은 따로 받고, 실제로 개수가 달라질 수 있는 값들만 뒤에서 한 번에 모으는 구조를 만들 수 있다.
예제:
exam18_4function printSum(tag, color, ...nums) { let result = 0; for (let i = 0; i < nums.length; i++) { result += nums[i]; // nums에 모인 숫자들만 합계 계산에 사용한다. } console.log(tag, color, result); // 앞의 고정 인수와 뒤의 계산 결과를 함께 사용한다. } printSum("h3", "red"); printSum("h3", "green", 10); printSum("h3", "yellow", 10, 20); printSum("h3", "lime", 10, 20, 30); // 출력결과 // h3 red 0 // h3 green 10 // h3 yellow 30 // h3 lime 60이 예제의 핵심은
함수에 들어오는 값이 전부 같은 역할이 아니라는 점이다.
- 앞의
tag,color→ 출력 형식을 정하는 값- 뒤의
nums→ 개수가 달라도 되는 숫자들즉,
Rest Parameter는
필요한 값은 따로 받고, 나머지는 한 번에 모으는 구조를 만들 때 특히 편하다.
6. 값 검증과 예외 처리가변 인수라고 해서 아무 값이나 받아도 되는 것은 아니다.
숫자 합계를 구하는 함수라면 숫자가 아닌 값이 들어왔을 때는 예외를 처리해야 한다.즉, 이 구간은 단순 합계 함수가 아니라 입력 검증까지 포함한 가변 인수 처리를 보여 준다.
예제:
exam19function sum(...nums) { let result = 0; for (let i = 0; i < nums.length; i++) { const value = nums[i]; if (isNaN(value)) { throw new Error("지정값이 숫자가 아닙니다: " + value); // 숫자가 아니면 예외를 발생시켜 계산을 멈춘다. } result += value; // 숫자일 때만 합계에 더한다. } return result; } try { console.log(sum(1, 3, 5, 7, 9)); console.log(sum(1, 3, "가", 7, 9)); } catch (e) { console.log(e.message); } // 출력결과 // 25 // 지정값이 숫자가 아닙니다: 가이 예제는 “가변 인수 처리”가 단순히 개수만 유연한 것이 아니라,
들어온 값이 올바른지도 같이 확인해야 한다는 점까지 보여 준다.
7. 헷갈리기 쉬운 부분초보자가 많이 헷갈리는 지점은 세 가지다.
arguments와Rest Parameter를 같은 것으로 보기 쉽다.Rest Parameter를 아무 위치에나 둘 수 있다고 생각하기 쉽다.- 가변 인수 함수는 어떤 값이 와도 다 처리한다고 생각하기 쉽다.
하지만 실제로는
arguments는 내장 객체 쪽 감각에 가깝고Rest Parameter는 매개변수 선언 단계에서 받는 문법이며- 숫자 계산 함수라면 입력 검증이 꼭 필요할 수 있다
는 점을 같이 봐야 한다.
3. 고차 함수
1. 개념
고차 함수는 함수를 값처럼 다루는 함수다.즉, 이 구간에서 먼저 잡아야 할 핵심은 이것이다.
- 함수에 함수를 넘길 수 있다.
- 함수가 함수를 돌려줄 수도 있다.
숫자나 문자열을 변수에 담고 전달하듯이,
JavaScript에서는 함수도 변수에 담고 다른 함수에 넘기거나, 실행 결과로 돌려줄 수 있다.
그래서 함수는 단순히 “호출되는 코드”가 아니라 전달되고 저장되고 반환될 수 있는 값으로도 다뤄진다.
2. 함수를 인수로 받는 경우함수를 다른 함수에 넘기면,
받는 쪽에서는 그 함수를 필요할 때 실행할 수 있다.다른 함수에 인수로 전달되어 나중에 실행되는 함수는 보통
콜백 함수라고 부른다.인수 자리에 들어온 값이 함수인지 아닌지에 따라 동작을 달리하는 구조가 여기서 중요하다.
예제:
exam20function highOrderFunction(p) { if (typeof p === "function") { p("안녕하세요"); // p가 함수이면 문자열을 넘기면서 실행한다. } else { console.log(p); // 함수가 아니면 그냥 값처럼 출력한다. } } highOrderFunction(function (msg) { console.log("첫 번째 함수:", msg); // 전달된 함수를 실행하면서 msg를 받는다. }); highOrderFunction(function (msg) { document.write(msg); // 이번에는 화면에 출력하는 다른 함수를 전달한다. }); highOrderFunction("함수가 아닙니다"); // 출력결과 // 첫 번째 함수: 안녕하세요 // 화면에는 안녕하세요 출력 // 콘솔에는 함수가 아닙니다 출력이 예제의 핵심은
highOrderFunction이 직접 모든 일을 하는 것이 아니라,
넘겨받은 함수에 일을 맡길 수 있다는 점이다.그래서 같은 함수라도
- 어떤 함수를 넘기느냐에 따라
- 실제 실행 결과는 달라질 수 있다
는 감각을 잡는 것이 중요하다.
3. 함수를 반환하는 경우이번에는 방향이 반대다.
함수가 함수를 만들어서 돌려주는 구조다.즉, 함수 호출 결과가 숫자나 문자열이 아니라 또 다른 함수가 될 수 있다는 점을 봐야 한다.
예제:
exam21function outerFunction() { return function () { console.log("Hello World .. !"); // outerFunction()이 반환한 내부 함수가 실행된다. }; } outerFunction()(); // 1. outerFunction() 실행 // 2. 함수 하나를 반환받음 // 3. 반환된 함수를 바로 실행 const result = outerFunction(); result(); result(); // 반환받은 함수를 변수에 저장해 두고 여러 번 실행할 수 있다. // 출력결과 // Hello World .. ! // Hello World .. ! // Hello World .. !이 코드를 읽을 때는
outerFunction()이 바로"Hello World"를 출력한다고 보면 헷갈린다.정확한 흐름은 이렇다.
outerFunction()이 실행된다.- 내부 함수 하나를 돌려준다.
- 그 반환된 함수를 나중에 실행한다.
즉,
outerFunction의 결과는 값이 아니라 실행 가능한 함수다.
4. 동작에 따라 다른 함수를 반환하는 경우함수를 반환하는 구조가 더 흥미로운 이유는
조건에 따라 다른 함수를 돌려줄 수 있기 때문이다.즉, 먼저 어떤 동작을 고르고, 그다음 그 동작을 실제 값에 적용하는 흐름으로 볼 수 있다.
예제:
exam21_1function action(type) { if (type === "add") { return function (a, b) { console.log(a + b); // 더하기 동작을 하는 함수를 반환한다. }; } else if (type === "sub") { return function (a, b) { console.log(a - b); // 빼기 동작을 하는 함수를 반환한다. }; } else { return function (a, b) { console.log(a * b); // 그 외에는 곱하기 동작을 하는 함수를 반환한다. }; } } action("add")(10, 20); action("sub")(10, 20); action("mul")(10, 20); // 출력결과 // 30 // -10 // 200이 예제에서 꼭 봐야 할 것은
action("add")단계와(10, 20)단계가 나뉜다는 점이다.
action("add")→ 더하기 함수 하나를 고른다.(10, 20)→ 그 고른 함수를 실제로 실행한다.즉, 이 코드는
“함수를 선택하고, 그다음 실행한다”는 두 단계를 한 줄로 붙여 쓴 것이다.
5. 코드 예제에서 이어지는 개념이 구간은 뒤에서 배열 메서드와도 자연스럽게 이어진다.
forEach(),map(),filter()같은 메서드도 결국
함수를 넘겨서 동작을 맡기는 구조이기 때문이다.그래서 지금 단계에서는
- 함수를 값처럼 넘길 수 있다
- 함수를 값처럼 돌려줄 수 있다
- 필요하면 바로 실행도 가능하다
이 세 가지만 정확히 잡아도 충분하다.
6. 헷갈리기 쉬운 부분초보자는 보통
“함수는 그냥 호출하는 것 아닌가?”라고 생각한다.그래서
- 함수가 인수로 들어간다
- 함수가 반환된다
- 반환된 함수를 또 호출한다
이 흐름이 낯설게 느껴질 수 있다.
하지만 고차 함수는 결국
함수를 특별한 것이 아니라 값처럼 다룬다고 보면 정리가 된다.즉,
highOrderFunction(fn)→ 함수를 넘긴다outerFunction()→ 함수를 돌려받는다action("add")(10,20)→ 돌려받은 함수를 바로 실행한다이 세 가지를 각각 따로 읽으면 이해가 훨씬 쉬워진다.
4. BOM 객체
1. BOM이란 무엇인가
개념
BOM은Browser Object Model의 줄임말이다.
이름 그대로 브라우저와 관련된 기능을 객체 형태로 다루는 방식이라고 보면 된다.지금까지는 우리가 직접 객체를 만들고, 속성과 메서드를 넣고, 생성자 함수와
prototype까지 사용해 봤다.
이제부터는 방향이 조금 바뀐다.
이번에는 우리가 객체를 만드는 것이 아니라, 브라우저가 이미 만들어 둔 객체를 사용하는 단계로 들어간다.예를 들어 브라우저에서는
- 새 창을 열 수 있고
- 창의 위치를 움직일 수 있고
- 일정 시간이 지난 뒤 코드를 실행할 수 있고
- 현재 페이지 주소를 바꿔 다른 사이트로 이동할 수 있고
- 화면 크기나 브라우저 언어 같은 정보도 확인할 수 있다
이런 기능들을 자바스크립트에서 각각의 객체를 통해 다루게 된다.
즉,
BOM은
브라우저 창, 주소, 화면, 사용자 환경 정보처럼 브라우저 자체와 관련된 기능을 자바스크립트 객체로 다루는 흐름이라고 이해하면 된다.
왜 필요한가웹 페이지는 단순히 화면에 내용을 보여 주는 데서 끝나지 않는다.
- 팝업 창을 열어야 할 수도 있고
- 몇 초 뒤 자동으로 페이지를 이동시켜야 할 수도 있고
- 사용자의 브라우저 언어나 위치 정보를 확인해야 할 수도 있고
- 화면 크기에 맞춰 창 크기를 조절해야 할 수도 있다
이런 작업은 HTML 태그만으로 처리하기 어렵다.
그래서 브라우저가 제공하는 객체를 이용해 자바스크립트가 직접 제어하게 된다.즉,
BOM은
브라우저를 대상으로 동작을 시키는 도구 모음처럼 보면 된다.
핵심 특징
- 브라우저가 기본으로 제공하는 객체들이다.
- 창 제어, 주소 이동, 시간 예약, 화면 정보, 브라우저 정보 같은 기능을 다룬다.
- 대표적으로
window,location,screen,navigator가 자주 등장한다.
헷갈리기 쉬운 부분
BOM도 객체이고, 앞에서 배운 객체도 객체라서 처음에는 같은 말처럼 느껴질 수 있다.하지만 차이는 분명하다.
- 앞에서 배운 객체 → 내가 직접 만든 객체
BOM객체 → 브라우저가 이미 제공하는 객체즉, 이번 파트는
객체 문법을 다시 배우는 것이 아니라
브라우저가 제공하는 객체를 어떻게 활용하는지 배우는 단계다.
2. window 객체
개념
window는 브라우저 창과 관련된 기본 객체다.
브라우저 환경에서는 가장 바깥에서 중심 역할을 하는 객체라고 보면 된다.새 창을 열거나, 창의 위치를 움직이거나, 창 크기를 바꾸거나, 일정 시간 뒤 코드를 실행하는 기능이 모두 이 객체와 연결된다.
window는 최상위 객체이고 탭이나iframe마다 하나씩 존재한다고 이해하면 된다.
핵심 특징
- 새 창 열기 →
window.open()- 창 이동 →
moveTo(),moveBy()- 창 크기 조절 →
resizeTo(),resizeBy()- 시간 제어 →
setInterval(),setTimeout()실제로는
window.를 생략해서 쓰는 경우도 많지만,
이번에는 어떤 객체의 기능인지 흐름을 잡는 것이 중요하므로window와 연결해서 이해하는 것이 좋다.
코드 예제예제:
exam31<script> var child = window.open('', '', 'width=300, height=200'); child.moveTo(0, 0); setInterval(function () { child.moveBy(10, 10); child.document.write(new Date()); // 새 창을 조금씩 이동시키고 현재 시간을 계속 출력한다. }, 1000); </script>이 코드는 새 창을 하나 연 다음,
그 창을 1초마다 조금씩 움직이고 현재 시간을 계속 써 주는 예제다.코드 흐름은 이렇게 읽으면 된다.
window.open()으로 새 창을 연다.- 반환된 새 창 객체를
child에 저장한다.child.moveTo(0, 0)으로 처음 위치를 정한다.setInterval()로 1초마다 같은 작업을 반복한다.- 반복할 때마다
child.moveBy(10, 10)으로 창을 조금씩 이동한다.child.document.write(new Date())로 새 창 안에 현재 시간을 출력한다.이 예제에서 가장 중요한 점은
새 창도 하나의 객체처럼 받아서 제어할 수 있다는 것이다.
예제:
exam31_1<script> const child = window.open('/edu/first.html', '', 'width=300, height=200'); const width = screen.width; const height = screen.height; child.moveTo(0, 0); child.resizeTo(width, height); window.setInterval(function () { child.resizeBy(-20, -20); child.moveBy(10, 10); // 새 창 크기를 줄이면서 위치도 함께 이동시킨다. }, 2000); </script>이 코드는 새 창을 열고,
처음에는 화면 크기만큼 크게 만든 뒤 2초마다 창 크기를 줄이고 위치를 바꾸는 흐름이다.screen.width,screen.height,resizeTo(),resizeBy(),moveBy()를 함께 사용한다.이 예제를 보면
window객체의 역할은 단순히 창을 여는 것에서 끝나지 않는다.
열린 창을 계속 제어하는 것까지 이어진다.
헷갈리기 쉬운 부분여기서
child는 그냥 일반 변수가 아니다.
window.open()이 반환한 새 창 객체를 저장한 변수다.그래서
child.moveTo()child.moveBy()child.resizeTo()child.document.write()처럼 새 창을 대상으로 계속 작업할 수 있다.
즉,
현재 창과 새로 열린 창은 구분해서 봐야 한다는 점이 중요하다.
3. setInterval()과setTimeout()
개념브라우저에서는 코드를 지금 바로 실행하는 것만이 아니라,
일정 시간이 지난 뒤 실행하거나, 일정 시간 간격으로 반복 실행하는 것도 자주 필요하다.이때 많이 쓰는 것이
setInterval()setTimeout()이다.
핵심 특징
setInterval(function(){ ... }, 시간)
→ 일정 시간마다 계속 반복 실행setTimeout(function(){ ... }, 시간)
→ 일정 시간이 지난 뒤 한 번만 실행즉, 둘의 가장 큰 차이는
같은 작업을 계속 반복하느냐, 한 번만 실행하느냐다.
코드 예제예제:
setInterval()흐름setInterval(function () { child.moveBy(10, 10); child.document.write(new Date()); }, 1000);이 코드는 1초마다 계속 실행된다.
그래서 새 창이 조금씩 움직이고, 시간이 반복해서 출력된다.
예제:
exam32<h1>5초 후에 MDN 사이트로 이동합니다.</h1> <script> window.setTimeout(function () { location.href = "https://developer.mozilla.org/ko/"; // 5초 뒤 현재 페이지 주소를 바꿔 다른 사이트로 이동한다. }, 5000); </script>이 코드는 5초가 지난 뒤 한 번만 실행된다.
실행되면location.href가 바뀌고, 현재 페이지가 다른 사이트로 이동한다.
헷갈리기 쉬운 부분
setInterval()과setTimeout()은 이름이 비슷해서 자주 헷갈린다.
setInterval()→ 계속 반복setTimeout()→ 한 번만 실행이번 범위에서는 이 차이를 확실히 구분하는 것이 가장 중요하다.
4. location 객체
개념
location은 현재 보고 있는 웹 페이지의 주소와 관련된 정보를 담는 객체다.
주소를 읽을 수도 있고, 주소를 바꿔서 다른 페이지로 이동할 수도 있다.location은 현재 URL 정보를 담는 객체라고 이해하면 된다.
핵심 특징
location.href- 현재 페이지 주소 확인
- 다른 주소로 이동
즉,
location은
현재 페이지의 위치 정보와 이동 기능을 담당하는 객체다.
코드 예제예제:
exam32window.setTimeout(function () { location.href = "https://developer.mozilla.org/ko/"; }, 5000);여기서 핵심은
location.href다.
이 값에 다른 주소를 넣으면 현재 페이지가 그 주소로 이동한다.즉,
- 지금은 현재 페이지를 보고 있다가
- 5초 뒤
href값이 바뀌고- 그 결과 브라우저가 다른 사이트로 이동한다
는 흐름이다.
헷갈리기 쉬운 부분
location.href는 단순히 문자열 값을 바꾸는 것처럼 보여도,
브라우저에서는 현재 주소와 연결되어 있기 때문에 실제 페이지 이동이 일어난다.
5. screen 객체
개념
screen은 사용자의 화면 크기나 해상도와 관련된 정보를 얻을 때 사용하는 객체다.
즉, 브라우저 창 자체보다 사용자가 보고 있는 화면 전체 정보와 더 가깝다고 보면 된다.screen은 화면 크기나 해상도 정보를 얻는 객체다.
핵심 특징
screen.widthscreen.height이 값을 이용하면 현재 화면 크기를 기준으로 창 위치나 크기를 조절할 수 있다.
코드 예제예제:
exam31_1const width = screen.width; const height = screen.height; child.resizeTo(width, height); // 화면 전체 크기에 맞게 새 창 크기를 조절한다.이 부분은 화면 크기를 읽어 와서,
열어 둔 새 창의 크기를 그에 맞게 바꾸는 흐름이다.즉,
screen은
현재 사용 환경의 화면 정보를 가져오는 데 쓰이고,
그 정보가window쪽 창 제어와 연결된다.
헷갈리기 쉬운 부분
screen.width는 브라우저 창 안쪽의 너비와 완전히 같은 개념으로 보면 안 된다.
이번 단계에서는 그냥 사용자 화면 전체 크기 정보 정도로 이해하면 충분하다.
6. navigator 객체
개념
navigator는 브라우저 정보나 사용자 환경 정보를 다룰 때 사용하는 객체다.
브라우저 언어, 위치 정보 기능 같은 것이 이 객체와 연결된다.navigator는 브라우저 이름, 버전 같은 정보와 연결되는 객체다.즉,
navigator는
브라우저가 현재 환경에 대해 알려 주는 정보 창구처럼 보면 된다.
핵심 특징
navigator.languagenavigator.geolocation즉,
navigator는
브라우저가 사용자 환경에 대해 알려 주는 값을 다룰 때 사용한다.
코드 예제예제:
exam33const today = new Date(); console.log(navigator.language); // 현재 브라우저 언어 정보를 확인한다. console.log(new Intl.DateTimeFormat(navigator.language, { dateStyle: "full" }).format(today)); // 브라우저 언어에 맞춰 날짜 형식을 출력한다.이 코드는
navigator.language를 이용해
현재 브라우저가 어떤 언어 환경을 쓰고 있는지 확인한다.
그리고 그 언어 값을Intl.DateTimeFormat에 연결해서 날짜 형식을 맞춘다.즉,
navigator는
브라우저 환경 정보를 알려 주고, 그 정보가 다른 객체와 연결되어 활용될 수 있다는 점이 중요하다.
7. geolocation 활용
개념
geolocation은 사용자의 현재 위치 정보를 요청하는 기능이다.
위도와 경도 같은 정보를 가져올 수 있지만, 자동으로 바로 가져오는 것이 아니라 사용자 허용이 먼저 필요하다.
핵심 특징
navigator.geolocation.getCurrentPosition()- 성공했을 때 실행할 함수
- 실패했을 때 실행할 함수
- 권한 허용 필요
즉, 위치 정보 기능은
요청 → 허용 여부 확인 → 성공 또는 실패 처리 흐름으로 이해해야 한다.
코드 예제예제:
exam35<p id="demo">위치정보를 추출하려면 실행 버튼을 클릭하세요:</p> <button onclick="getLocation()">실행</button> <script> const x = document.getElementById("demo"); function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition, showError); // 위치 정보 기능이 있으면 현재 위치를 요청한다. } else { x.innerHTML = "이 브라우저는 geolocation을 지원하지 않습니다."; } } function showPosition(position) { window.alert("위도: " + position.coords.latitude + "\n경도: " + position.coords.longitude); // 위치 요청이 성공하면 위도와 경도를 보여 준다. } function showError(error) { switch (error.code) { case error.PERMISSION_DENIED: x.innerHTML = "사용자가 위치 기능 사용을 거부했습니다."; break; case error.POSITION_UNAVAILABLE: x.innerHTML = "위치를 구할 수 없습니다."; break; case error.TIMEOUT: x.innerHTML = "위치 정보를 가져오는 시간이 초과되었습니다."; break; case error.UNKNOWN_ERROR: x.innerHTML = "기타 에러"; } } </script>이 예제는 버튼을 누르면 위치 정보를 요청한다.
성공하면 위도와 경도를 보여 주고, 실패하면 오류 종류에 따라 다른 메시지를 출력한다.코드 흐름은 이렇게 읽으면 된다.
- 버튼을 누르면
getLocation()이 실행된다.navigator.geolocation지원 여부를 먼저 확인한다.- 지원되면 현재 위치를 요청한다.
- 성공하면
showPosition()이 실행된다.- 실패하면
showError()가 실행된다.이 예제에서 가장 중요한 점은
위치 정보는 단순히 함수 하나 호출로 끝나는 것이 아니라,
성공과 실패를 나눠서 처리해야 한다는 것이다.
헷갈리기 쉬운 부분위치 정보는 브라우저가 마음대로 알려 주는 것이 아니다.
사용자가 허용하지 않으면 실패할 수 있다.그래서 이 기능은
“무조건 값을 받는다”가 아니라
“성공할 수도 있고 실패할 수도 있으니 둘 다 처리해야 한다”는 기준으로 봐야 한다.
8. 브라우저 환경에 맞춘 출력 객체
개념브라우저 환경에서는 날짜, 시간, 숫자, 통화, 상대 시간 같은 값도
사용자의 언어나 지역 형식에 맞춰 다르게 보여 줄 필요가 있다.이때 사용하는 것이
Intl관련 객체들이다.이번 범위에서는
Intl.DateTimeFormatIntl.NumberFormatIntl.RelativeTimeFormat이 세 가지가 나온다.
핵심 특징
- 날짜/시간 형식 바꾸기
- 숫자/통화 형식 바꾸기
- 상대 시간 표현하기
navigator.language와 함께 연결 가능즉,
Intl은
값 자체를 바꾸는 것이 아니라, 보여 주는 형식을 지역에 맞게 바꾸는 도구라고 이해하면 된다.
코드 예제예제:
exam33const today = new Date(); let options = { dateStyle: "long" }; writeColor(new Intl.DateTimeFormat("ko-KR", options).format(today), "h3", "blue"); writeColor(new Intl.DateTimeFormat("en-US", options).format(today), "h3", "blue"); writeColor(new Intl.DateTimeFormat("ja-JP", options).format(today), "h3", "blue"); // 같은 날짜라도 언어와 지역에 따라 다른 형식으로 출력된다.이 코드는 같은 날짜를 한국어, 영어, 일본어 형식으로 각각 보여 준다.
즉, 날짜 값은 같아도 보여 주는 형식은 달라질 수 있다는 점이 중요하다.
예제:
exam34let options = { style: "currency", currency: "krw", currencyDisplay: "name" }; writeColor(new Intl.NumberFormat(navigator.language, options).format(50000), "h3", "red"); options.currency = "usd"; writeColor(new Intl.NumberFormat(navigator.language, options).format(50000), "h3", "red"); // 같은 숫자도 통화 설정에 따라 다른 방식으로 표현된다. options = { numeric: "always" }; const obj = new Intl.RelativeTimeFormat("ko-KR", options); writeColor(obj.format(1, "day"), "h3", "blue"); writeColor(obj.format(-1, "day"), "h3", "blue"); // 미래와 과거를 상대 시간 형식으로 표현한다.이 예제는 숫자를 통화 형식으로 출력하고,
또 하루 뒤, 하루 전 같은 표현도 만들어 낸다.여기서 꼭 봐야 할 것은
- 숫자 값 자체가 바뀌는 것은 아니라는 점
- 통화나 지역 설정에 따라 표현 방식이 달라진다는 점
- 양수와 음수에 따라 미래/과거 표현이 나뉜다는 점
이다.
헷갈리기 쉬운 부분
Intl은 계산을 하는 객체로 보면 안 된다.
핵심은 출력 형식을 맞춰 주는 것이다.즉,
- 날짜를 바꾸는 것이 아니라 날짜 표현 형식을 바꾸고
- 숫자를 바꾸는 것이 아니라 숫자 표시 방식을 바꾸고
- 시간의 흐름을 계산하기보다는 말로 표현하는 형식을 만든다
는 쪽으로 이해하면 된다.
9. history 객체
개념
history는 브라우저가 방문했던 URL 흐름과 관련된 객체다.
즉, 사용자가 어떤 페이지들을 거쳐 왔는지와 연결된다고 보면 된다.history는 브라우저가 접근했던 URL 정보와 관련된 객체다.
핵심 특징
- 방문 기록 흐름과 관련된다.
- 현재 범위에서는 개념 정도만 잡아 두면 충분하다.
이번 구간에는
history를 직접 조작하는 코드 예제가 없으므로,
지금은BOM을 구성하는 기본 객체 중 하나라는 정도만 기억하면 된다.
헷갈리기 쉬운 부분
history도BOM의 한 부분이지만,
이번 범위에서 실제 코드 중심으로 많이 다루는 것은window,location,screen,navigator쪽이다.그래서 지금은
“브라우저 방문 흐름과 관련된 객체” 정도로만 잡아 두면 충분하다.
10. BOM과 DOM의 경계
개념
document는 현재 문서 정보를 담는 객체다.
그런데 실제 학습 흐름에서는document를 자세히 파기 시작하면DOM파트로 넘어가게 된다.즉, 이번 글은
BOM중심이므로
- 창 제어
- 주소 이동
- 화면 정보
- 브라우저 환경 정보
까지를 중심으로 보고,
document는 뒤에서 문서 구조를 다루는DOM파트에서 더 깊게 보는 것이 자연스럽다.
헷갈리기 쉬운 부분
document도 브라우저에서 제공하는 객체라서 지금 범위와 완전히 끊어져 있는 것은 아니다.
하지만 이번 글의 중심은 문서 구조 조작이 아니라 브라우저 자체와 관련된 기능이다.그래서
document는
이번에는 연결만 하고, 본격 설명은 뒤의DOM에서 다루는 것이 맞다.
11. BOM 흐름 정리
정리 흐름
BOM은 브라우저가 기본으로 제공하는 객체를 다루는 흐름이다.window로 창을 열고 움직이고 크기를 바꿀 수 있다.setInterval()과setTimeout()으로 실행 시점을 조절할 수 있다.location으로 페이지 주소를 바꾸고 이동할 수 있다.screen으로 화면 크기 정보를 활용할 수 있다.navigator로 브라우저 언어와 사용자 환경 정보를 확인할 수 있다.geolocation으로 위치 정보를 요청할 수 있지만 성공과 실패를 함께 처리해야 한다.Intl로 날짜, 숫자, 통화, 상대 시간을 지역 형식에 맞게 출력할 수 있다.history는 방문 기록 흐름과 관련된 객체다.document는 뒤에서DOM으로 더 깊게 이어진다.즉, 이번 파트는
자바스크립트가 브라우저 안에서 어떻게 창, 주소, 시간, 화면, 사용자 환경을 다루는지 보는 단계라고 정리하면 된다.
5. DOM 객체
1. DOM이란 무엇인가
개념
DOM은Document Object Model의 줄임말이다.
브라우저는 HTML 문서를 그냥 글자 덩어리로 두지 않고, 태그 하나하나를 객체처럼 다룰 수 있는 구조로 바꿔서 읽는다.
이렇게 만들어진 객체 구조를DOM이라고 한다.쉽게 말하면,
- HTML은 화면의 재료이고
- 브라우저는 그 재료를 읽어서
- 자바스크립트가 건드릴 수 있는 객체 구조로 바꾼다
는 흐름이다.
그래서 자바스크립트는 HTML 태그를 단순 문자열로 대하는 것이 아니라,
- 찾고
- 읽고
- 바꾸고
- 추가하고
- 삭제하는
작업을 할 수 있게 된다.
즉,DOM은 문서를 자바스크립트로 다루기 위한 문서 객체 구조라고 이해하면 된다.
왜 필요한가HTML만으로는 화면을 처음 그릴 수는 있다.
하지만 화면이 한 번 그려진 뒤에
- 제목을 바꾸거나
- 버튼을 눌렀을 때 내용을 바꾸거나
- 이미지를 다른 것으로 바꾸거나
- 입력값을 읽거나
- 특정 영역만 보이게 하거나
- 클릭, 마우스오버, 제출 같은 동작에 반응하게 만들려면
문서를 다시 다룰 수 있어야 한다.
이때 필요한 것이
DOM이다.앞 글의
BOM이 브라우저 창, 주소, 화면처럼 브라우저 자체를 다뤘다면,
DOM은 그 안에 들어 있는 문서 내용 자체를 다루는 단계라고 보면 된다.
핵심 특징
- HTML 태그는 브라우저 안에서
DOM 객체가 된다.- 자바스크립트는
document를 통해 DOM에 접근한다.- 원하는 태그를 먼저 찾고, 그다음 내용을 바꾸거나 스타일을 바꾼다.
- 대부분의 화면 동작은
이벤트와 함께 움직인다.
헷갈리기 쉬운 부분초보자는
HTML 태그와DOM 객체를 완전히 같은 것으로 생각하기 쉽다.하지만 정확히는 이렇게 보는 편이 맞다.
- HTML 태그 → 문서에 적어 둔 원본 구조
- DOM 객체 → 브라우저가 그 구조를 읽고 만든 자바스크립트용 객체
즉,
DOM은 HTML을 자바스크립트가 만질 수 있게 바꿔 놓은 형태라고 이해하면 된다.
2. DOM 객체 찾기
개념
DOM조작의 시작은 항상 같다.
먼저 원하는 태그를 찾아야 한다.제목을 바꾸고 싶어도 제목 태그를 먼저 찾아야 하고,
이미지를 바꾸고 싶어도 이미지 태그를 먼저 찾아야 한다.그래서
DOM파트의 첫 핵심은
문서 안에서 원하는 객체를 찾는 방법이다.
핵심 특징
document.getElementById("id값")id로 하나를 찾는다.document.getElementsByTagName("태그명")- 태그 이름으로 여러 개를 찾는다.
document.querySelector("CSS선택자")- 선택자에 맞는 첫 번째 하나를 찾는다.
document.querySelectorAll("CSS선택자")- 선택자에 맞는 여러 개를 찾는다.
즉, 찾는 기준이 다를 뿐 결국 하는 일은 같다.
문서 안에서 원하는 DOM 객체를 찾는 것이다.
코드 예제예제:
exam1_1,exam1_2,exam1_3const outDom = document.getElementById("output"); // 출력 결과를 넣을 div를 id로 찾는다. const doms = []; for (let i = 1; i < 9; i++) doms.push(document.getElementById(`t${i}`)); // t1 ~ t8 id를 가진 DOM 객체를 순서대로 배열에 담는다.const outDom = document.getElementsByTagName("div")[1]; // div 태그를 모두 찾은 뒤 두 번째 div를 출력 영역으로 사용한다. const doms = []; doms.push(document.getElementsByTagName("h1")[0]); doms.push(document.getElementsByTagName("h2")[0]); doms.push(document.getElementsByTagName("p")[0]); // 태그명으로 찾으면 여러 개가 잡히므로 인덱스로 꺼내 쓴다.const outDom = document.querySelector("div:nth-of-type(2)"); // CSS 선택자로 두 번째 div를 찾는다. const doms = []; doms.push(document.querySelectorAll("h1")[0]); doms.push(document.querySelector("h2")); doms.push(document.querySelector("p")); // querySelector 계열은 CSS 선택자 방식으로 DOM 객체를 찾는다.이 세 예제는 결국 같은 태그들을 서로 다른 방식으로 찾는 흐름을 보여 준다.
즉,
id가 뚜렷하면getElementById()- 태그 이름으로 묶어서 찾으려면
getElementsByTagName()- 선택자 감각으로 찾고 싶으면
querySelector()계열이라고 보면 된다.
헷갈리기 쉬운 부분
getElementById()는 보통 하나를 찾는다.
반면getElementsByTagName()이나querySelectorAll()은 여러 개를 찾을 수 있다.그래서
- 하나를 바로 다루는 경우
- 여러 개 중에서
[0],[1]처럼 꺼내 써야 하는 경우를 구분해야 한다.
특히 초보자는
getElementsByTagName("h1")을 썼는데 왜 바로textContent를 못 쓰지?
여기서 많이 헷갈린다.이 경우는
h1하나가 아니라 찾은 결과 묶음이 돌아오기 때문이다.
3. DOM 객체가 실제로 어떻게 보이는지 확인하기
개념DOM 객체를 찾았다고 해서 바로 끝나는 것은 아니다.
초보자는 여기서 한 번 더 감을 잡아야 한다.찾은 결과가 문자열이 아니라 실제 DOM 객체라는 점이다.
즉,
document.getElementById(...)같은 코드가 반환하는 것은
단순 텍스트가 아니라 브라우저가 만든 태그 객체다.
핵심 특징
- DOM 객체 자체를 출력해 볼 수 있다.
- 객체 안의 순수 텍스트는
textContent로 볼 수 있다.- 태그 구조까지 포함한 내용은
innerHTML로 볼 수 있다.
코드 예제예제:
exam6_1let dom = document.getElementsByTagName("h1"); // h1 태그들을 모두 찾는다. writeNewLine(dom); // 찾은 결과 묶음 자체를 출력한다. writeNewLine(dom.length); // 몇 개가 잡혔는지 확인한다. writeNewLine(dom[0]); // 첫 번째 h1 DOM 객체 자체를 출력한다. writeNewLine(dom[0].textContent); // 첫 번째 h1의 글자 내용만 본다. writeNewLine(dom[0].innerHTML); // 첫 번째 h1의 내부 HTML 내용을 본다.이 코드는
h1태그를 찾은 뒤,
그 결과가 어떤 모습인지 여러 각도에서 확인하게 해 준다.여기서 꼭 봐야 할 점은 세 가지다.
dom자체를 보면 찾은 결과 묶음이 나온다.dom[0].textContent를 보면 태그 안의 글자만 나온다.dom[0].innerHTML을 보면 태그 안의 HTML 내용 기준으로 볼 수 있다.즉,
DOM은 단순 값이 아니라
내용과 구조를 가진 객체라는 점을 이 예제가 보여 준다.
헷갈리기 쉬운 부분
textContent와innerHTML은 비슷해 보여도 완전히 같지 않다.
textContent→ 글자 중심innerHTML→ HTML 구조까지 포함이 차이는 뒤에서 내용을 바꿀 때 더 중요해진다.
4. 내용 읽기와 내용 바꾸기
개념DOM 객체를 찾았다면 그다음은 내용을 바꾸는 단계다.
이때 가장 자주 쓰는 것이
textContentinnerHTML이다.
textContent는 글자 내용을 바꾸는 데 가깝고,
innerHTML은 HTML 태그 구조까지 포함해서 바꿀 수 있다.
핵심 특징
dom.textContent = "문자열"- 글자 그대로 넣는다.
dom.innerHTML = "<h2>문자열</h2>"- 태그까지 해석해서 넣는다.
dom.innerHTML += "..."- 기존 내용 뒤에 이어서 추가한다.
코드 예제예제:
exam2const dom = document.getElementsByTagName("div")[0]; // 내용을 바꿀 div를 찾는다. function update(num) { if (num == 1) { dom.innerHTML = "<h2>테스트하자</h2>"; // 태그를 실제 HTML로 해석해서 넣는다. } else if (num == 2) { dom.textContent = "<h2>테스트하자</h2>"; // 태그를 해석하지 않고 글자로 그대로 넣는다. } else { dom.innerHTML += "<h2>테스트하자</h2>"; // 기존 내용 뒤에 같은 구조를 계속 추가한다. } }이 예제는
innerHTML과textContent차이를 가장 직접적으로 보여 준다.읽는 순서는 이렇게 가면 된다.
innerHTML버튼을 누르면
<h2>태그가 실제 태그로 해석되어 들어간다.
textContent버튼을 누르면
<h2>도 그냥 글자로 보인다.
innerHTML +=버튼을 누르면
- 기존 내용 뒤에 같은 구조가 계속 추가된다.
즉, 이 예제의 핵심은
같은 문자열처럼 보여도, 어떤 속성으로 넣느냐에 따라 브라우저 해석 방식이 달라진다는 점이다.
헷갈리기 쉬운 부분초보자는
innerHTML과textContent를 거의 같은 것으로 보기 쉽다.하지만 차이는 분명하다.
innerHTML→ HTML 태그로 본다.textContent→ 문자 그대로 본다.그래서 태그를 실제로 넣고 싶을 때와,
그냥 글자만 보여 주고 싶을 때를 구분해야 한다.
5. 스타일 바꾸기
개념DOM 조작은 내용만 바꾸는 것이 아니다.
찾아낸 DOM 객체의 스타일까지 자바스크립트로 바꿀 수 있다.즉, 화면에 보이는 글자색, 배경색, 표시 방식도 DOM 객체를 통해 조절할 수 있다.
핵심 특징
dom.style.colordom.style.backgroundColordom.style["background-color"]스타일 이름을 쓸 때는 두 방식이 자주 나온다.
- 자바스크립트 식 표기 →
backgroundColor- 문자열 속성명 표기 →
["background-color"]
코드 예제예제:
exam6_1window.setTimeout(function() { dom.textContent = "오늘은 월요일"; // 5초 뒤 제목 내용을 바꾼다. dom.style.color = "red"; // 글자색을 빨간색으로 바꾼다. dom.style["background-color"] = "yellow"; // 배경색을 노란색으로 바꾼다. }, 5000);이 코드는 5초 뒤에 제목 내용을 바꾸고,
글자색과 배경색까지 함께 바꾼다.즉,
- DOM 객체를 찾은 뒤
- 내용만 바꾸는 것이 아니라
- 스타일도 이어서 바꿀 수 있다
는 점을 보여 준다.
예제:
exam12_1,exam12_2,exam12_3function updateColor() { const dom = document.querySelector("h1"); // 첫 번째 h1 태그를 찾는다. const colorCode = '#' + Math.round(Math.random() * 0xffffff).toString(16); // 랜덤 색상 코드를 만든다. dom.style.color = colorCode; // 제목 색상을 랜덤하게 바꾼다. }이 코드는 버튼을 누를 때마다 제목 색상을 랜덤하게 바꾼다.
즉, 스타일 조작은 고정값만 넣는 것이 아니라 동적으로도 바꿀 수 있다는 점을 보여 준다.
헷갈리기 쉬운 부분
style.color = "red"처럼 쓰는 건 쉽다.
하지만background-color같은 이름은-가 들어가므로 그대로 점 표기법으로 못 쓴다.그래서
backgroundColor["background-color"]이 둘 중 하나로 써야 한다는 점을 기억해야 한다.
6. 속성과 이미지 변경하기
개념DOM 조작은 글자 내용만 바꾸는 것이 아니다.
태그가 가지고 있는 속성(attribute)도 바꿀 수 있다.예를 들어
- 이미지의
src- 버튼의
data-*- 링크의
href같은 것도 DOM을 통해 읽고 바꾼다.
핵심 특징
- 이미지 바꾸기 →
img.src = ...- 속성 읽기 →
getAttribute()- 필요하면
setAttribute()로 연결해서 이해 가능
코드 예제예제:
exam12_1,exam12_2,exam12_3function updateImage() { const dom = document.querySelector("[src]"); // src 속성을 가진 첫 번째 요소, 즉 이미지 태그를 찾는다. const randomValue = Math.random(); const imageName = Math.floor(randomValue * 10) + 1; // 1 ~ 10 사이의 랜덤 이미지 번호를 만든다. dom.src = "../../images/" + imageName + ".jpg"; // 이미지 src 값을 바꿔 화면에 보이는 사진을 바꾼다. }이 코드는 버튼을 누를 때마다 이미지 파일명을 바꿔서
다른 그림이 보이게 만든다.여기서 중요한 것은
이미지 자체를 지우고 새로 만드는 것이 아니라,
이미지 태그의src속성값만 바꾼다는 점이다.
예제:
exam8_1function click_processing(e) { let h1dom = document.getElementsByTagName("h1")[0]; // 제목 역할을 하는 h1 태그를 찾는다. h1dom.textContent = e.target.textContent; // 클릭한 버튼의 글자를 제목 내용으로 바꾼다. h1dom.style.color = e.target.getAttribute("data-mycolor"); // 클릭한 버튼의 data-mycolor 값을 읽어 제목 색상으로 사용한다. }이 코드는 클릭한 버튼의 글자를 제목으로 넣고,
버튼에 들어 있던data-mycolor값을 읽어 제목 색상으로 사용한다.즉,
getAttribute()는
태그에 적혀 있는 속성값을 읽어 와서 다른 DOM 조작과 연결하는 도구라고 보면 된다.
헷갈리기 쉬운 부분초보자는 내용을 바꾸는 것과 속성을 바꾸는 것을 같은 일처럼 보기 쉽다.
하지만 다르다.
textContent→ 태그 안의 글자 바꾸기src,href,data-*→ 태그가 가진 속성 바꾸기 또는 읽기즉, 무엇을 바꾸는지 구분해서 봐야 한다.
7. 시간에 따라 DOM 바꾸기
개념DOM 조작은 한 번만 하는 것이 아니다.
시간 간격을 두고 계속 바꾸거나, 일정 시간이 지난 뒤 바꾸는 경우도 많다.이때 자주 같이 쓰는 것이
setTimeout()setInterval()clearInterval()이다.
핵심 특징
setTimeout()→ 일정 시간 뒤 한 번 실행setInterval()→ 일정 간격마다 반복 실행clearInterval()→ 반복 중지
코드 예제예제:
exam3,exam3_1const target = document.getElementsByTagName("output")[0]; // 시간을 보여 줄 output 태그를 찾는다. let interval_id; // 반복 실행을 중지할 때 사용할 id를 저장할 변수다. function startTime() { if (target.innerHTML) { window.alert("그만 클릭하라옹... 이미 시간 출력하고 있음!!"); // 이미 시간이 출력 중이면 중복 실행을 막는다. } else { target.innerHTML = "<h2>" + new Date().toLocaleString() + "</h2>"; // 현재 시각을 한 번 먼저 출력한다. interval_id = window.setInterval(function () { target.innerHTML = "<h2>" + new Date().toLocaleString() + "</h2>"; // 1초마다 시간을 다시 출력해서 화면을 갱신한다. }, 1000); } } function stopTime() { target.innerHTML = ""; // 화면에 보이던 시간을 지운다. window.clearInterval(interval_id); // 반복 실행을 멈춘다. }이 코드는 버튼을 누르면 현재 시간을 출력하고,
1초마다 그 시간을 계속 갱신한다.
그리고 다른 버튼을 누르면 출력과 반복을 중단한다.이 예제를 읽을 때 중요한 흐름은 이거다.
- 먼저
output태그를 찾는다.startTime()이 실행되면 현재 시각을 한 번 넣는다.- 그다음
setInterval()로 계속 갱신한다.stopTime()이 실행되면 내용을 지우고clearInterval()로 반복을 멈춘다.즉, DOM 조작은
시간 흐름과 결합해서 계속 바뀌는 화면도 만들 수 있다는 점이 중요하다.
헷갈리기 쉬운 부분
setInterval()만 있으면 반복은 되지만,
중간에 멈추려면clearInterval()이 필요하다.그래서 반복 작업은 보통
- 시작할 때 아이디를 저장하고
- 멈출 때 그 아이디로 종료
하는 구조로 이해하면 된다.
8. 폼과 입력값 다루기
개념DOM은 입력 폼도 다룬다.
즉, 사용자가 입력창에 넣은 값을 읽고, 제출 전에 확인하고, 선택한 항목에 따라 다른 동작을 시킬 수 있다.화면에 보이는 입력창도 결국 DOM 객체이기 때문에
자바스크립트가 그 값을 읽을 수 있다.
핵심 특징
- 입력값 읽기 →
value- 전송 시점 반응 →
submit이벤트- 필수 입력 →
required- 선택 박스 값 읽기 →
select.value
코드 예제예제:
exam14document.querySelector("form").addEventListener("submit", function() { const name = document.querySelector("[type='text']").value; // 이름 입력창의 현재 값을 읽는다. const age = document.querySelector("[type='number']").value; // 나이 입력창의 현재 값을 읽는다. const content = `이름 : ${name}, \n나이 : ${age}`; // 확인용 메시지를 만든다. window.alert(content); // 폼이 전송되기 전에 입력 내용을 먼저 보여 준다. });이 코드는 폼이 전송될 때 입력값을 먼저 읽어서
이름과 나이를 확인창처럼 보여 준다.
입력창에required도 있으므로 비어 있으면 전송 전에 검사된다.즉, 폼은 단순히 서버로 보내기 전에
자바스크립트가 중간에서 입력값을 읽고 확인하는 단계를 가질 수 있다.
예제:
exam13function go(){ location.href = document.getElementById("choice").value; // select에서 고른 option의 value를 읽어 그 주소로 이동한다. }이 코드는
select에서 고른 항목의 값을 읽어
그 주소로 바로 이동하게 만든다.즉,
form이나select도 DOM 객체로 다루면
사용자 선택값에 따라 다른 동작을 만들 수 있다.
헷갈리기 쉬운 부분초보자는 입력창에 보이는 글자와 실제 자바스크립트가 읽는 값을 따로 생각하지 못할 수 있다.
하지만 자바스크립트는
- 화면에 보이는 입력창을 DOM으로 찾고
- 그 안의 현재 값을
value로 꺼내 쓴다는 흐름으로 동작한다.
9. 화면 일부만 보이게 제어하기
개념DOM을 이용하면 화면 전체를 다 바꾸지 않아도 된다.
특정 구역만 보이게 하거나 숨기면서 화면을 전환할 수도 있다.이때 자주 쓰는 것이
style.display다.
핵심 특징
elem.style.display = "none"→ 숨기기elem.style.display = "block"→ 보이기- 여러 요소를 한꺼번에 숨기고 하나만 다시 보이게 할 수 있다
코드 예제예제:
exam15function displayTag(target) { document.querySelectorAll("section > *").forEach(function(elem) { elem.style.display = "none"; // section 안의 모든 article을 먼저 숨긴다. }); let dom = document.querySelector("#" + target); // 보여 줄 article 하나만 id로 다시 찾는다. dom.style.display = "block"; // 선택된 영역만 다시 보이게 만든다. }이 코드는 방명록 화면에서
- 리스트 보기
- 글쓰기
- 검색하기
중 하나만 보이게 만드는 역할을 한다.
흐름은 이렇게 읽으면 쉽다.
section안의 모든article을 먼저 숨긴다.- 클릭한 메뉴가 가리키는
id의 요소만 다시 찾는다.- 그 요소만
block으로 보여 준다.즉, DOM을 이용하면
한 페이지 안에서도 필요한 구역만 골라서 보여 주는 화면 제어가 가능하다는 점을 보여 준다.
헷갈리기 쉬운 부분이 예제는 페이지를 새로 이동하는 것이 아니다.
이미 있는 DOM 요소들의 보임/숨김 상태만 바꾸는 것이다.즉,
- 새 페이지 이동 아님
- 화면 일부 전환
이라는 차이를 기억해야 한다.
10. 이벤트란 무엇인가
개념
이벤트는 사용자의 행동이나 브라우저 상황에 따라 자동으로 발생하는 신호다.예를 들면
- 클릭
- 마우스 올리기
- 문서 로드
- 폼 제출
같은 것이 이벤트다.
왜 중요한가DOM 조작은 혼자 움직이지 않는다.
대부분은 “어떤 일이 일어났을 때” 반응한다.즉,
- 버튼을 클릭했을 때 제목 바꾸기
- 링크를 클릭했을 때 이동 막기
- 문서가 다 로드됐을 때 코드 실행하기
처럼 이벤트와 DOM 조작은 거의 항상 같이 간다.
헷갈리기 쉬운 부분이벤트는 우리가 직접 “만드는” 것보다
사용자 행동이나 브라우저 상태 변화에 따라 “발생하는 것”이라는 감각이 먼저 필요하다.
11. load 이벤트와 문서 준비 시점
개념DOM 조작은 문서가 준비된 뒤에 해야 안전할 때가 많다.
아직 태그가 다 만들어지지 않았는데 찾으려고 하면 원하는 요소를 못 찾을 수 있기 때문이다.그래서 문서가 다 로드된 뒤 실행하는
load이벤트가 중요하다.
핵심 특징
- 인라인 방식 →
body onload- 고전 이벤트 모델 →
window.onload = function() { ... }- 표준 이벤트 모델 →
window.addEventListener("load", function() { ... })
코드 예제예제:
exam4,exam4_1,exam4_2<body onload="window.alert('반갑습니다!! 오늘은 즐거운 '+getKorDay()+'욜입니다.')">window.onload = function() { window.alert('반갑습니다!! 오늘은 즐거운 '+getKorDay()+'욜입니다.'); }window.addEventListener("load", function() { window.alert('반갑습니다!! 오늘은 즐거운 '+getKorDay()+'욜입니다.'); });이 세 코드는 방식만 다를 뿐,
문서가 준비된 뒤 인사 메시지를 띄운다는 점은 같다.즉,
load이벤트는
문서가 준비된 뒤 DOM 조작이나 알림을 시작하는 기준 시점이라고 보면 된다.
헷갈리기 쉬운 부분세 방식은 결과는 비슷해도 연결 방식이 다르다.
- 태그에 직접 붙이기
- DOM 객체 속성에 넣기
- 메서드로 등록하기
이 차이는 뒤의 이벤트 모델에서 더 분명하게 보게 된다.
12. 이벤트 모델 3가지
개념이벤트를 연결하는 방식은 크게 세 가지로 볼 수 있다.
- 인라인 이벤트 모델
- 고전 이벤트 모델
- 표준 이벤트 모델
핵심 특징
- 인라인 이벤트 모델
- HTML 태그 안에 바로 작성
- 고전 이벤트 모델
- DOM 객체의 이벤트 속성에 함수 대입
- 표준 이벤트 모델
addEventListener()로 등록
코드 예제예제:
exam8_2function test1() { alert("인라인이벤트모델 버튼 클릭"); } function test2() { alert("고전이벤트모델 버튼 클릭"); btn1.onmouseover = null; // 고전 이벤트 모델은 이벤트 속성을 null로 만들어 해제할 수 있다. } function test3() { alert("표준이벤트모델 버튼 클릭"); btn2.removeEventListener("mouseover", test3); // 표준 이벤트 모델은 removeEventListener()로 해제한다. } var btn1 = document.querySelector("#b1"); var btn2 = document.getElementById("b2"); btn1.onmouseover = test2; // 고전 이벤트 모델로 연결한다. btn2.addEventListener("mouseover", test3); // 표준 이벤트 모델로 연결한다.이 예제는 세 이벤트 모델을 한 화면에서 비교하게 해 준다.
그리고 고전 모델은null로 해제하고, 표준 모델은removeEventListener()로 해제한다는 점까지 보여 준다.
예제:
exam7dom1.onclick = function () { alert("첫 번째 핸들러 수행(고전)"); }; dom1.onclick = function () { alert("두 번째 핸들러 수행(고전)"); }; // 고전 모델은 나중에 대입한 핸들러가 앞의 것을 덮어쓴다. dom2.addEventListener("click", function () { alert("첫 번째 핸들러 수행(표준)"); }); dom2.addEventListener("click", function () { alert("두 번째 핸들러 수행(표준)"); }); // 표준 모델은 여러 핸들러를 함께 등록할 수 있다.이 예제는 고전 모델과 표준 모델의 차이를 아주 분명하게 보여 준다.
고전 모델은 같은 속성에 다시 대입하면 이전 것이 덮어써지고,
표준 모델은 여러 핸들러를 계속 등록할 수 있다.
헷갈리기 쉬운 부분초보자가 가장 헷갈리는 지점은 이거다.
- 고전 모델 → 하나만 유지되기 쉽다
- 표준 모델 → 여러 개를 붙일 수 있다
그래서 실제로는 표준 이벤트 모델이 더 유연하다고 이해하면 된다.
13. 이벤트 객체와 이벤트 대상
개념이벤트가 발생하면 관련 정보가 함께 넘어온다.
이 정보를 담고 있는 것이이벤트 객체다.이벤트 객체를 이용하면
- 어떤 태그에서 이벤트가 시작됐는지
- 지금 어떤 태그가 이벤트를 처리하고 있는지
- 클릭한 대상의 텍스트나 속성값은 무엇인지
를 알 수 있다.
핵심 특징
thise.targete.currentTargettextContentgetAttribute()
코드 예제예제:
exam8_1function click_processing(e) { window.alert(this); // 현재 핸들러가 연결된 대상을 확인한다. window.alert(this.id); window.alert(this.textContent); // 현재 처리 중인 요소의 id와 글자를 본다. window.alert(e.target); // 실제 이벤트가 시작된 대상을 확인한다. window.alert(e.target.id); window.alert(e.target.textContent); // 실제 클릭된 요소의 id와 글자를 본다. let h1dom = document.getElementsByTagName("h1")[0]; h1dom.textContent = e.target.textContent; // 클릭한 버튼의 글자를 제목으로 넣는다. h1dom.style.color = e.target.getAttribute("data-mycolor"); // 클릭한 버튼의 data-mycolor 값을 읽어 제목 색상으로 사용한다. }이 코드는 이벤트가 발생했을 때
- 처리 중인 버튼 정보
- 실제 클릭된 대상 정보
- 그 대상의 텍스트와 속성값
을 이용해서 제목 내용을 바꾸고 색상도 바꾼다.
즉, 이벤트 객체는
누가 이벤트를 일으켰는지 알아내고, 그 정보를 다시 DOM 조작과 연결하는 핵심 도구다.
헷갈리기 쉬운 부분
this와e.target을 항상 똑같다고 보면 안 된다.초반에는 비슷해 보일 수 있지만,
이벤트 전파가 섞이면 둘의 의미가 달라질 수 있다.그래서 지금 단계에서는
e.target→ 실제 이벤트가 시작된 대상this또는e.currentTarget→ 현재 핸들러가 붙어 있는 대상정도로 먼저 구분해 두는 것이 좋다.
14. 기본 이벤트 막기
개념브라우저에는 원래 자동으로 일어나는 동작이 있다.
예를 들면
- 링크를 누르면 이동
- 폼을 제출하면 전송
같은 것이다.
그런데 경우에 따라서는 이 기본 동작을 막고,
자바스크립트가 먼저 확인하거나 다른 처리를 해야 할 수도 있다.
핵심 특징
- 인라인 →
return false- 고전 이벤트 모델 →
return false- 표준 이벤트 모델 →
preventDefault()
코드 예제예제:
exam9function go() { const answer = window.confirm("정말 갈겨?"); // 사용자에게 정말 이동할지 묻는다. console.log(answer ? "간답니다~~" : "안간다네요~~"); // 확인 결과를 콘솔에 남긴다. return answer; // true면 이동하고 false면 링크 기본 이동을 막는다. }이 예제는 링크를 클릭했을 때 무조건 이동하지 않고,
먼저 확인창을 띄운 뒤 사용자가 허용하면 이동하고 아니면 막는다.
예제:
exam8_3function test2() { alert("고전이벤트모델 버튼 클릭"); return false; // 고전 이벤트 모델에서는 false를 반환해 기본 동작을 막을 수 있다. } function test3(e) { e.preventDefault(); // 표준 이벤트 모델에서는 기본 동작을 직접 막는다. alert("표준이벤트모델 버튼 클릭"); }이 예제는 고전 모델에서는
return false,
표준 모델에서는preventDefault()로 기본 동작을 막는 차이를 보여 준다.
헷갈리기 쉬운 부분“클릭 이벤트를 처리한다”와
“원래 동작까지 막는다”는 다른 일이다.즉,
- 이벤트 핸들러 실행
- 기본 동작 유지 또는 중단
이 두 층을 같이 생각해야 한다.
15. 이벤트 전파와 버블링
개념이벤트는 한 요소에서만 끝나는 것이 아니라,
부모 요소 쪽으로 전달될 수 있다.예를 들어
h1을 클릭했더라도
h1- 그 부모인
div- 그 부모인
section- 더 바깥의
body까지 이벤트가 이어질 수 있다.
이 흐름을 이해할 때 자주 나오는 말이
- 버블링
- 캡처링
- 전파 중단
이다.
핵심 특징
e.target→ 실제 이벤트가 시작된 태그e.currentTarget→ 현재 이벤트를 처리 중인 태그addEventListener(..., true)→ 캡처링 쪽 동작 확인stopPropagation()→ 전파 중단
코드 예제예제:
exam10function clickHandler() { var dom1 = document.getElementsByTagName("h1")[0]; var dom2 = document.getElementsByTagName("div")[0]; var dom3 = document.getElementsByTagName("section")[0]; var dom4 = document.getElementsByTagName("body")[0]; // 클릭 이벤트를 연결할 h1, div, section, body를 각각 찾는다. dom1.addEventListener("click", displayAlert); dom2.addEventListener("click", displayAlert); dom3.addEventListener("click", displayAlert, true); dom4.addEventListener("click", displayAlert); // 같은 클릭 이벤트를 여러 태그에 연결해 전파 흐름을 관찰한다. } function displayAlert(e) { window.alert(`${e.target.nodeName} 태그 에서 ${e.type} 이벤트 발생!! --- ${e.currentTarget.nodeName} 태그가 이벤트 처리 위임받음`); // 실제 발생한 태그와 현재 처리 중인 태그를 함께 보여 준다. }이 예제는 같은 클릭 이벤트가 여러 태그를 따라 전달되는 모습을 보여 준다.
특히e.target과e.currentTarget을 비교하면,
이벤트가 발생한 태그와 현재 처리 중인 태그가 다를 수 있다는 점이 보인다.
예제:
exam10_1function displayAlert(e) { window.alert(`${e.target.nodeName} 태그 에서 ${e.type} 이벤트 발생!! --- ${e.currentTarget.nodeName} 태그가 이벤트 처리 위임받음`); e.stopPropagation(); // 여기서 이벤트 전파를 멈춰 더 위 부모로 올라가지 못하게 한다. }이 코드는 같은 구조이지만
stopPropagation()을 넣어서
이벤트가 더 위로 전달되지 않게 막는다.즉, 전파는 자동으로 일어날 수 있지만,
필요하면 중간에서 멈출 수도 있다.
헷갈리기 쉬운 부분초보자는 보통
“내가 클릭한 태그만 반응한다”라고 생각하기 쉽다.하지만 실제로는
- 이벤트는 퍼질 수 있고
- 부모 태그가 대신 처리할 수도 있고
- 발생한 태그와 처리한 태그가 다를 수도 있다
는 점을 같이 알아야 한다.
16. DOM 파트를 한 흐름으로 묶으면
정리 흐름
DOM은 HTML 문서를 객체처럼 다루는 방식이다.- 먼저 원하는 DOM 객체를 찾는다.
- 찾은 뒤 내용, 속성, 스타일을 바꾼다.
- 시간 흐름에 따라 화면을 계속 바꿀 수도 있다.
- 폼과 입력값도 DOM으로 읽어 처리한다.
- 특정 영역만 보이게 하거나 숨길 수도 있다.
- 이벤트를 연결해 사용자 동작에 반응한다.
- 이벤트 객체로 누가 이벤트를 일으켰는지 확인한다.
- 기본 동작을 막거나, 이벤트 전파를 제어할 수도 있다.
즉,
DOM파트는 단순히 “태그를 찾는 문법”에서 끝나지 않는다.처음에는
document로 찾고textContent,innerHTML로 바꾸고style과 속성을 수정하는 정도로 시작하지만점점
- 입력값 처리
- 화면 전환
- 이벤트 모델
- 이벤트 객체
- 기본 동작 제어
- 버블링과 전파 제어
까지 이어지면서,
결국 사용자와 상호작용하는 실제 웹 화면의 동작으로 연결된다.