📘 9.2.2 apply로 this 바꾸기 - 배열로 정보를 전달하는 방법
여러분께 인사드려요. 이전 시간에 call
이라는 특별한 능력을 배웠죠? call
로 this
를 자유자재로 바꿀 수 있다는 것을 알게 되었어요. 이제 call
의 쌍둥이 형제인 apply
를 만나볼 시간이에요.
apply
는 call
과 거의 같은 마음을 가지고 있지만, 한 가지 특별한 차이점이 있답니다. 바로 정보를 전달하는 방식이 다른 거예요. 마치 선물을 하나씩 건네는 것과 바구니에 정성스럽게 담아서 전하는 것의 차이와 같아요.
🧠 새로운 단어들과 친해지기
call
의 쌍둥이 형제 apply
와 친해지기 전에, 새로운 말들을 먼저 부드럽게 배워보겠어요.
단어 | 부드러운 설명 |
---|---|
apply 기능 | call 과 같이 this 를 바꿀 수 있지만, 정보들을 배열에 담아서 전달하는 따뜻한 방법이에요. |
정보 묶음 배열 | 기능에 전달할 값들을 배열에 정성스럽게 묶어놓은 것을 말해요. |
펼치기 | 배열 안의 값들을 하나씩 꺼내서 부드럽게 펼쳐주는 일이에요. |
apply
는 영어로 "적용하다"라는 뜻을 가지고 있어요. 기능을 특정 객체에 "적용"한다는 의미로 이해하면 좋을 것 같아요. call
과 마음은 똑같지만, 정보를 다루는 방식이 좀 더 정돈되어 있다고 생각하면 돼요.
✨ apply
가 무엇인지 천천히 알아보기
apply
는 call
의 똑똑한 쌍둥이 형제라고 할 수 있어요. 둘 다 this
를 원하는 객체로 바꾸는 능력을 가지고 있지만, 정보를 전달하는 방식에서 차이가 있어요.
call
은 정보를 하나씩 따로따로 전달했다면, apply
는 정보들을 배열에 담아서 한 번에 전달해요. 마치 친구에게 선물을 할 때 하나씩 건네는 것과 바구니에 모두 담아서 전하는 것의 차이와 같아요.
이런 특징 때문에 apply
는 정보가 이미 배열 형태로 준비되어 있을 때 특히 소중해져요. 또한 정보가 많을 때도 배열로 깔끔하게 정리해서 전달할 수 있어서 코드가 더 읽기 쉬워져요.
무엇보다 apply
의 가장 유명한 활용법은 배열에서 가장 큰 수나 가장 작은 수를 구할 때 사용하는 거예요. 이는 자바스크립트에서 정말 자주 사용되는 아름다운 방법이에요.
따뜻한 이야기: 마을의 선물 배달 방법
call
과 apply
의 차이를 더 가깝게 느낄 수 있도록 '마을의 선물 배달' 이야기를 들려드릴게요.
어떤 작은 마을에 철수 아저씨(call
)와 영희 아주머니(apply
)가 선물 배달 일을 하고 있다고 상상해보세요. 둘 다 마을 사람들에게 선물을 나눠주는 일을 해요.
철수 아저씨(call
)의 방법:
어떤 집에서 "빵, 우유, 사과를 주세요"라는 주문이 오면, 철수 아저씨는 빵을 한 손에, 우유를 다른 손에, 사과를 또 다른 주머니에... 이렇게 하나씩 따로 들고 가서 그 집에 전달해요. 즉, func.call(그집, 빵, 우유, 사과)
형태로 각각을 따로 전달하는 거예요.
영희 아주머니(apply
)의 방법:
같은 주문을 받으면, 영희 아주머니는 빵, 우유, 사과를 모두 하나의 바구니에 정성스럽게 담아서 그 집에 전달해요. 즉, func.apply(그집, [빵, 우유, 사과])
형태로 배열처럼 한꺼번에 전달하는 거죠.
두 방법 모두 그 집은 빵, 우유, 사과를 모두 받을 수 있지만, 배달 방식이 다른 거예요. 특히 선물이 많거나 이미 바구니에 담겨있을 때는 영희 아주머니의 방법이 더 편리하겠죠?
🎯 왜 apply
를 사용하는지 생각해보기
apply
라는 능력을 사용하는 이유는 여러 가지가 있어요.
첫째로, 배열로 된 정보 활용이 쉬워져요. 정보가 이미 배열 형태로 저장되어 있을 때, 그 배열을 그대로 기능에 전달할 수 있어서 매우 편안해요.
둘째로, 코드 정리에 도움이 돼요. 정보가 많을 때 하나씩 나열하는 것보다 배열로 묶어서 관리하는 것이 더 깔끔하고 실수도 줄일 수 있어요.
셋째로, 상황에 따라 달라지는 정보 처리가 가능해져요. 정보의 개수가 상황에 따라 달라질 때, 배열의 크기를 조절해서 유연하게 대응할 수 있어요.
마지막으로, 특별한 내장 기능과의 협력에 매우 소중해요. 특히 Math.max
나 Math.min
같은 기능은 배열을 직접 받을 수 없는데, apply
를 사용하면 배열의 값들을 펼쳐서 전달할 수 있어요.
⚙️ 기본 사용법을 차근차근 배우기
apply
의 사용법은 call
과 거의 비슷하지만, 정보 부분에서 중요한 차이가 있어요.
// apply 기본 사용법
기능이름.apply(this로_사용할_객체, [정보1, 정보2, 정보3]);
// call과 비교해보기
기능이름.call(객체, 정보1, 정보2, 정보3); // call: 하나씩 전달
기능이름.apply(객체, [정보1, 정보2, 정보3]); // apply: 배열로 전달
소중한 점들:
apply
의 첫 번째 정보는call
과 같이 "this
로 사용할 객체"예요.apply
의 두 번째 정보는 반드시 배열이어야 해요.- 배열 안의 값들이 기능에 하나씩 전달돼요.
🧪 직접 해보면서 천천히 배우기
이제 실제 예시를 통해서 apply
가 어떻게 움직이는지 자세히 알아보겠어요.
🔹 Ex1) call
과 apply
의 차이점 체험해보기
첫 번째 예시에서는 같은 결과를 만들어내는 call
과 apply
의 서로 다른 방법을 비교해보겠어요.
// 인사와 취미를 소개하는 기능
function introduceHobby(greeting, hobby, level) {
console.log(greeting + "! 저는 " + this.name + "입니다.");
console.log("제 취미는 " + hobby + "이고, 실력은 " + level + " 정도예요.");
}
// 소개할 사람
let person = { name: "지수" }; // 이름이 지수인 사람
console.log("=== call 방식으로 소개하기 ===");
// call: 정보를 하나씩 따로 전달
introduceHobby.call(person, "안녕하세요", "피아노", "중급");
console.log("\n=== apply 방식으로 소개하기 ===");
// apply: 정보를 배열로 묶어서 전달
introduceHobby.apply(person, ["안녕하세요", "피아노", "중급"]);
console.log("\n=== 결과는 완전히 똑같아요! ===");
이 코드를 보면, call
과 apply
모두 같은 기능을 같은 객체의 this
로 실행하지만, 정보 전달 방식만 다르다는 것을 확인할 수 있어요. 최종 결과는 완전히 동일하지만, 상황에 따라 더 편한 방법을 선택할 수 있어요.
🔹 Ex2) 이미 배열로 준비된 정보 활용해보기
두 번째 예시에서는 정보가 이미 배열 형태로 있을 때 apply
가 얼마나 유용한지 알아보겠어요.
// 시험 점수를 발표하는 기능
function announceScores(korean, math, english, science) {
console.log("=== " + this.name + "의 시험 점수 발표 ===");
console.log("국어: " + korean + "점");
console.log("수학: " + math + "점");
console.log("영어: " + english + "점");
console.log("과학: " + science + "점");
let total = korean + math + english + science;
let average = total / 4;
console.log("총점: " + total + "점, 평균: " + average + "점");
}
// 학생 정보
let student = { name: "현우" }; // 이름이 현우인 학생
// 점수가 이미 배열로 저장되어 있는 상황
let testScores = [95, 87, 92, 89]; // 국어, 수학, 영어, 과학 순서로 점수가 들어있어요
console.log("=== 배열 정보를 apply로 전달하기 ===");
// apply를 사용하면 배열을 그대로 전달할 수 있어요!
announceScores.apply(student, testScores);
console.log("\n=== 만약 call을 썼다면... ===");
// call을 쓰려면 배열을 하나씩 꺼내야 해요
announceScores.call(student, testScores[0], testScores[1], testScores[2], testScores[3]);
이 예시에서 apply
의 진가가 드러나요. 정보가 이미 배열로 준비되어 있을 때, apply
는 그 배열을 바로 사용할 수 있지만, call
은 배열의 각 요소를 하나씩 꺼내서 전달해야 하는 번거로움이 있어요.
🔹 Ex3) 배열에서 가장 큰 수와 가장 작은 수 구하기
세 번째 예시에서는 apply
의 가장 유명한 활용법인 배열에서 가장 큰 수와 가장 작은 수를 구하는 방법을 알아보겠어요.
// 학급 친구들의 키 (단위: cm)
let heights = [145, 152, 148, 156, 150, 147, 153];
console.log("=== 학급 친구들의 키 정보 ===");
console.log("키 목록:", heights);
// Math.max와 Math.min은 원래 배열을 직접 받을 수 없어요
// Math.max(heights); // 이렇게 하면 안 돼요!
console.log("\n=== apply로 가장 큰 키와 가장 작은 키 구하기 ===");
// apply를 사용해서 배열을 펼쳐서 전달
let tallest = Math.max.apply(null, heights); // null은 this를 사용하지 않는다는 뜻이에요
let shortest = Math.min.apply(null, heights); // Math.min도 마찬가지로 this를 안 써요
console.log("가장 큰 키: " + tallest + "cm");
console.log("가장 작은 키: " + shortest + "cm");
// 평균도 계산해보기
let total = 0;
for (let i = 0; i < heights.length; i++) {
total = total + heights[i];
}
let average = total / heights.length;
console.log("평균 키: " + average + "cm");
console.log("\n=== apply 없이는 이렇게 해야 해요 ===");
// apply 없이 하려면 이렇게 복잡해져요
let manualMax = Math.max(heights[0], heights[1], heights[2], heights[3], heights[4], heights[5], heights[6]);
console.log("수동으로 구한 가장 큰 키: " + manualMax + "cm");
이 예시에서 apply
의 강력함을 확실히 느낄 수 있어요. Math.max
와 Math.min
기능은 배열을 직접 받을 수 없지만, apply
를 사용하면 배열의 모든 값을 자동으로 펼쳐서 전달할 수 있어요. 참고로 여기서 null
을 첫 번째 정보로 사용한 이유는 Math.max
와 Math.min
이 this
를 사용하지 않는 기능이기 때문이에요.
🔄 apply
사용하는 순서 차근차근 정리하기
지금까지 배운 apply
사용 과정을 하나씩 차근차근 정리해볼게요.
첫 번째 단계는 기능과 객체 준비예요. 사용할 기능과 this
로 지정할 객체를 마음을 담아 미리 준비해둬요.
두 번째 단계는 정보 배열 만들기 단계예요. 기능에 전달할 정보들을 배열 형태로 준비해요. 이미 배열로 있다면 그대로 사용하면 되고, 아니라면 [값1, 값2, 값3]
형태로 만들어줘요.
세 번째 단계는 apply
기능 사용 단계예요. 기능이름.apply(객체, 배열)
형태로 apply
를 부드럽게 사용해요.
네 번째 단계는 배열 펼치기 단계예요. 자바스크립트가 자동으로 배열의 값들을 하나씩 꺼내서 기능에 전달해요.
마지막으로 가장 소중한 것은 결과 확인 단계예요. 기능이 의도한 객체의 this
로 실행되고, 배열의 값들이 올바르게 전달되었는지 확인해요.
🧚♀️ 따뜻한 이야기로 다시 배우기: 마을 급식실의 배식 시스템
지금까지 배운 내용을 따뜻한 이야기로 다시 정리해볼까요?
옛날에 마을 급식실이 있었어요. 이 급식실에는 call
아저씨와 apply
아주머니 두 명이 일하고 있었어요.
두 분 모두 "이 음식들을 ○○에게 전달해줘"라는 똑같은 일을 할 수 있었어요. 하지만 음식을 배식하는 방식이 달랐어요.
call
아저씨의 방법:
어떤 학생이 "밥, 국, 반찬을 주세요"라고 하면, call
아저씨는 "밥은 이 그릇에, 국은 저 그릇에, 반찬은 또 다른 그릇에..." 이렇게 하나씩 따로 담아서 학생에게 전달했어요.
apply
아주머니의 방법:
같은 주문을 받으면, apply
아주머니는 "밥, 국, 반찬을 모두 하나의 식판에 정성스럽게 담고..." 이렇게 정리해서 학생에게 전달했어요.
두 방법 모두 학생은 밥, 국, 반찬을 모두 받을 수 있었어요. 하지만 특별한 상황이 있었어요.
어느 날 "영양사 선생님"이라는 특별한 분이 왔어요. 이 선생님은 "이 음식들 중에서 가장 칼로리가 높은 것을 찾아줘"라는 특별한 부탁을 했어요. 그런데 음식들이 이미 식판(배열) 위에 들어있었어요.
call
아저씨는 식판을 하나씩 뒤져서 음식을 꺼내야 했지만, apply
아주머니는 식판 전체를 "가장 높은 칼로리 찾기 시스템"에 바로 전달할 수 있었어요. 그래서 apply
아주머니의 방법이 훨씬 더 효율적이고 편안했답니다.
🧠 자주 하는 실수와 조심할 점
apply
를 사용할 때 자주 하는 실수들을 미리 알아두면 더 안전하게 코딩할 수 있어요.
❌ 실수 1: apply
에 배열이 아닌 값 전달하기
function greet(message, name) {
console.log(message + ", " + name + "!");
}
let person = { name: "철수" };
// 잘못된 사용
greet.apply(person, "안녕하세요", "철수"); // 에러가 나요!
// 올바른 사용
greet.apply(person, ["안녕하세요", "철수"]); // 성공!
이런 실수가 생기는 이유는 apply
의 두 번째 정보는 반드시 배열이어야 한다는 규칙을 잊어버리기 때문이에요. call
에 익숙해져서 실수로 하나씩 전달하려고 하는 경우가 많아요.
❌ 실수 2: call
과 apply
를 잘못 선택하기
let person = { name: "영희" };
let data = ["안녕", 25, "학생"];
// 비효율적인 방법
someFunc.call(person, data[0], data[1], data[2]);
// 효율적인 방법
someFunc.apply(person, data);
이 문제가 생기는 이유는 상황에 맞는 방법을 선택하지 않기 때문이에요. 정보가 이미 배열로 있다면 apply
를 사용하는 것이 훨씬 효율적이고 깔끔해요.
❌ 실수 3: Math.max/min
에 배열을 직접 전달하기
let numbers = [10, 5, 8, 3, 12];
// 잘못된 방법
let max = Math.max(numbers); // 이상한 결과가 나와요!
// 올바른 방법
let max = Math.max.apply(null, numbers); // 12가 나와요!
이 실수가 생기는 이유는 Math.max
와 Math.min
기능이 배열을 직접 받을 수 없다는 사실을 모르기 때문이에요. 이 기능들은 개별 숫자들을 정보로 받도록 만들어져 있어서, 배열을 전달하려면 apply
로 펼쳐서 보내야 해요.
✏️ 직접 해보기 - 따뜻한 연습 문제들
이제 배운 내용을 연습 문제를 통해서 차근차근 익혀볼게요.
마음을 편안히 하고 코드와 함께 대화하듯 연습해보세요. 각 문제는 여러분이 apply
의 마음을 이해할 수 있도록 도와줄 거예요.
Ex1) 같은 기능을 call
과 apply
두 가지 방법으로 사용해보기
// 여행 계획을 발표하는 기능
function announcePlan(destination, duration, companion) {
console.log(this.name + "의 여행 계획:");
console.log("목적지: " + destination);
console.log("기간: " + duration + "일");
console.log("동행자: " + companion);
}
// 여행자 정보
let traveler = { name: "수현" }; // 이름이 수현인 여행자
// call 방식: 정보를 하나씩 전달
announcePlan.call(traveler, "제주도", 3, "가족");
// apply 방식: 정보를 배열로 전달
announcePlan.apply(traveler, ["제주도", 3, "가족"]);
이 연습을 통해 call
과 apply
의 정보 전달 방식 차이를 명확히 이해할 수 있어요.
Ex2) 배열에 있는 숫자들의 가장 큰 수와 가장 작은 수를 apply
로 구해보기
// 한 달 동안의 일일 기온 (섭씨)
let temperatures = [15, 18, 22, 19, 25, 28, 31, 29, 26, 23, 20, 17];
console.log("=== 이달의 기온 정보 ===");
console.log("일일 기온:", temperatures);
// apply를 사용해서 최고 기온과 최저 기온 구하기
let maxTemp = Math.max.apply(null, temperatures); // apply로 배열을 펼쳐서 가장 큰 수 찾기
let minTemp = Math.min.apply(null, temperatures); // apply로 배열을 펼쳐서 가장 작은 수 찾기
console.log("최고 기온: " + maxTemp + "℃");
console.log("최저 기온: " + minTemp + "℃");
console.log("기온 차이: " + (maxTemp - minTemp) + "℃");
이 문제는 apply
의 가장 실용적인 활용법을 연습하는 데 도움이 돼요.
Ex3) 이미 배열로 저장된 학생 정보를 apply
로 전달해보기
// 학급 정보를 출력하는 기능
function showClassInfo(studentName, grade, classNumber, teacher) {
console.log("=== 학급 정보 ===");
console.log("학생: " + studentName);
console.log("학년: " + grade + "학년");
console.log("반: " + classNumber + "반");
console.log("담임: " + teacher + "선생님");
console.log("소속: " + this.school);
}
// 학교 정보
let school = { school: "행복초등학교" }; // 학교 이름이 들어있는 객체
// 학생 정보가 이미 배열로 저장되어 있음
let studentInfo = ["김민준", 4, 2, "이"]; // 이름, 학년, 반, 담임선생님 순서
// apply로 배열 정보를 기능에 전달
showClassInfo.apply(school, studentInfo);
이 연습문제를 통해 실제 정보 처리에서 apply
를 어떻게 활용하는지 경험할 수 있어요.
🎮 보너스 문제 - 조금 더 깊이 있는 apply 활용법
조금 더 도전해보고 싶은 분들을 위한 보너스 문제예요. 천천히 생각해보세요.
보너스 Q1. 다음 코드의 결과를 예상해보세요
function calculateSum(a, b, c, d) {
console.log(this.title + ":");
let total = a + b + c + d;
console.log(a + " + " + b + " + " + c + " + " + d + " = " + total);
return total;
}
let calculator = { title: "계산 결과" };
let numbers = [10, 20, 30, 40];
let result = calculateSum.apply(calculator, numbers);
console.log("최종 결과: " + result);
정답:
- "계산 결과:"
- "10 + 20 + 30 + 40 = 100"
- "최종 결과: 100"
부드러운 설명: apply
가 numbers
배열을 펼쳐서 calculateSum(10, 20, 30, 40)
형태로 호출하고, this
는 calculator
객체를 가리키게 돼요.
보너스 Q2. 다음 중 올바른 apply
사용법은?
function showInfo(name, age, hobby) {
console.log(this.prefix + ": " + name + ", " + age + "살, 취미는 " + hobby);
}
let info = { prefix: "학생 정보" };
// A번
showInfo.apply(info, ["민수", 10, "축구"]);
// B번
showInfo.apply(info, "민수", 10, "축구");
정답: A번이 올바른 사용법이에요.
부드러운 설명: apply
는 정보를 반드시 배열 형태로 전달해야 해요. B번은 call
의 사용법으로, apply
에서는 작동하지 않아요.
📚 이전 단원 복습하기
9단원을 배우는 여러분을 위해 이전에 배운 내용을 차근차근 복습해볼게요.
복습 문제 1 - 7단원: 배열 사용하기
// 7단원에서 배운 배열을 사용해보세요
let fruits = ["사과", "바나나", "오렌지"]; // 과일 배열 만들기
fruits.push("포도"); // 배열 뒤에 포도 추가
console.log("과일 목록:", fruits);
// 배열의 길이 확인하기
console.log("과일 개수:", fruits.length);
// 첫 번째 과일과 마지막 과일 가져오기
console.log("첫 번째 과일:", fruits[0]);
console.log("마지막 과일:", fruits[fruits.length - 1]);
복습 포인트: 배열은 여러 개의 값을 하나로 묶어서 관리할 수 있어요. apply
에서 이런 배열을 그대로 활용할 수 있다는 점이 중요해요.
복습 문제 2 - 2단원: 연산자 사용하기
// 2단원에서 배운 연산자를 사용해보세요
let score1 = 85;
let score2 = 92;
let score3 = 78;
// 더하기 연산자로 총점 계산
let total = score1 + score2 + score3;
console.log("총점: " + total);
// 나누기 연산자로 평균 계산
let average = total / 3;
console.log("평균: " + average);
// 비교 연산자로 평균이 80 이상인지 확인
if (average >= 80) {
console.log("평균이 80 이상입니다!");
} else {
console.log("더 열심히 공부해요!");
}
복습 포인트: 연산자는 계산이나 비교를 할 때 사용해요. apply
에서 전달하는 값들도 이런 연산자로 처리할 수 있어요.
지금까지 apply
라는 기능에 대해 자세히 알아보았어요. apply
는 call
과 같은 목적을 가지고 있지만, 정보를 배열로 전달한다는 점에서 차이가 있어요. 특히 배열 정보를 다룰 때나 Math.max/min
같은 기능과 함께 사용할 때 정말 소중한 기능이에요.
✅ 학습 완료 체크리스트
이번 시간에 배운 내용들을 모두 이해했는지 확인해보세요.
학습 내용 | 이해했나요? |
---|---|
apply의 기본 개념 | ✅ |
기본 사용법과 문법 | ✅ |
call과의 차이점 | ✅ |
자주 하는 실수들 | ✅ |
실전 예제 이해 | ✅ |
🎯 추가 연습 문제들
조금 더 연습하고 싶은 분들을 위한 추가 문제들이에요.
추가 문제 1. call과 apply로 같은 결과를 만들어보세요.
// 답:
function introduce(hobby, age) {
console.log("저는 " + this.name + "이고, " + hobby + "를 좋아하며, " + age + "살입니다.");
}
let person = { name: "수민" };
// call 방식
introduce.call(person, "독서", 9);
// apply 방식
introduce.apply(person, ["독서", 9]);
추가 문제 2. 배열의 최댓값을 apply로 구해보세요.
// 답:
let scores = [85, 92, 78, 96, 88];
let highest = Math.max.apply(null, scores);
console.log("최고 점수: " + highest); // "최고 점수: 96"
추가 문제 3. 이미 배열로 있는 매개변수를 apply로 전달해보세요.
// 답:
function showInfo(name, grade, school) {
console.log(this.title + ": " + name + "은 " + school + " " + grade + "학년입니다.");
}
let info = { title: "학생 정보" };
let studentData = ["철수", 4, "행복초등학교"];
showInfo.apply(info, studentData);
📂 마무리 정보
오늘 배운 9.2.2
내용이 여러분의 자바스크립트 지식에 잘 자리 잡았나요? 다음 시간에는 더 재미있는 내용으로 만나요.
기억할 점: 오늘 배운 내용을 꼭 연습해보시고, 궁금한 점이 있으면 언제든 다시 돌아와서 읽어보세요.
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
'9. this와 친해지기 (this 바인딩) > 9.2 this 제어 방법' 카테고리의 다른 글
9.2.3 bind로 this 고정하기 - 영원히 변하지 않는 연결 (0) | 2025.07.13 |
---|---|
9.2.1 call로 this 바꾸기 - 도구를 빌려 쓰는 방법 (0) | 2025.07.12 |