If you're seeing this message, it means we're having trouble loading external resources on our website.

웹 필터가 올바르게 작동하지 않으면 도메인 *. kastatic.org*.kasandbox.org이 차단되어 있는지 확인하세요.

주요 내용

버튼 함수

"JS란?" 과정을 들었다면 로직 응용: 첫 버튼 과제나 버튼 만들기 심화에서 간단한 버튼 몇 개를 만들어 보았을 것입니다. 잊었다면 간단한 버튼을 만드는 방법을 복습해 봅시다.
먼저 버튼의 가장 기본적인 성질은 무엇일까요?
  1. 도형의 형상 (일반적으로 직사각형입니다)
  2. 버튼의 기능을 설명하는 라벨이나 아이콘 등
  3. 사용자가 버튼을 클릭하면 반응할 것 (다른 곳 말고)
1과 2는 꽤 쉽게 할 수 있습니다:
fill(0, 234, 255);
rect(100, 100, 150, 50, 5);
fill(0, 0, 0);
textSize(19);
text("Useless button", 110, 133);
3번을 구현하려면 mouseClicked 함수를 사용자가 클릭할 때 호출하고 이 함수는 mouseXmouseY가 버튼의 경계선 안에 있는지 확인해야 합니다. 위 버튼은 아래 보이는 것 처럼 x=100에서 x=250까지, y=100에서 y=150까지 범위를 갖습니다.
이 4개의 좌표를 &&으로 한꺼번에 묶을 수 있습니다:
mouseClicked = function() {
    if (mouseX >= 100 && mouseX <= 250 &&
        mouseY >= 100 && mouseY <= 150) {
        println("Still pretty useless");    
    }
};
버튼 안과 밖을 모두 클릭해서 제대로 작동하는지 확인해 보세요 :
정확하게 작동하긴 하지만 걱정이 되는군요. 이 코드를 재사용하기 쉽지 않을 것 같습니다. 버튼의 위치를 변경하고 싶으면 얼마나 많은 일을 해야 할까요? (한번 시도해 보세요!) 위에서 mouseClicked 함수 내 좌표 관련 코드는 "하드코딩(hardcoding)" 되어 있습니다. 좀 더 깨끗하게 코드를 쓸 순 없는지 생각하게 되네요.
먼저 버튼이 작동하도록 위치와 크기 변수를 만들고 변수 하나만 바꾸면 위치가 바뀌도록 해 봅시다. 아래 프로그램에 btnX, btnY, btnWidth, btnHeight을 추가했습니다. 변수 값을 변경하고 버튼을 클릭해 보세요.
훨씬 낫네요. 그러나 버튼을 추가하고자 한다면 얼마나 작업을 더 해야 할까요? 모든 것을 복사하고 붙여서 btn2X, btn2Y를 만들어야 할까요? 전혀 재미있을 것 같지 않네요. 버튼 부분을 만들 때 필요한 함수는 유지하고 다른 부분은 매개변수를 이용해서 만드는 것이 좀 더 좋을 겁니다. 다시 말하자면 변수를 매개변수로 변환하는 것입니다.
var drawButton = function(btnX, btnY, btnWidth, btnHeight) {
    fill(0, 234, 255);
    rect(btnX, btnY, btnWidth, btnHeight, 5);
    fill(0, 0, 0);
    textSize(19);
    textAlign(LEFT, TOP);
    text("Useless button", btnX+10, btnY+btnHeight/4);
};
그 후 다음과 같이 함수를 호출합니다:
drawButton(100, 100, 150, 50);
그러나 mouseClicked 코드는 어떨까요? 이 코드에 어떤 문제가 있는지 알겠나요?
mouseClicked = function() {
    if (mouseX >= btnX && mouseX <= (btnX+btnWidth) &&
        mouseY >= btnY && mouseY <= (btnY+btnHeight)) {
        println("Still pretty useless");    
    }
};
이 모든 코드를 합치면 "btnX 가 정의되지 않았습니다"라는 오류가 발생합니다. btnX를 함수의 매개변수로 변환하기 때문에 btnX 는 더 이상 전역 변수(global variable)가 아닙니다. drawButton 함수를 재사용하기에는 좋아졌지만 mouseClicked 함수는 확인해야 할 좌표가 무엇인지를 알 방법이 없습니다.
따라서 drawButton에 정보를 전달하는 좋은 방법을 알아내야 합니다. 그리고 해당 정보를 mouseClicked에서 받을 수 있도록 해야 합니다. 다음의 방안을 생각해 볼 수 있습니다:
  1. 위치와 크기에 대한 전역변수를 다시 도입합니다. (btnX, btnY, btnWidth, btnHeight)
  2. 모든 매개변수를 저장하는 전역 배열을 도입합니다. (var btn1 = [...];)
  3. 매개변수를 저장하는 전역 객체를 도입합니다. (var btn1 = {..})
  4. 객체지향적 원칙을 이용하여 버튼을 정의하고 프로퍼티를 저장합니다. (var btn1 = new Button(...))
어떤 것을 선택할 건가요? 첫 번째 방법은 너무 많은 전역 변수를 추가해야 해서 전역 변수 알레르기가 생길지도 모릅니다. 두 번째 방법의 경우 배열 인덱스를 기반으로 데이터를 잡는 코드는 읽기 어렵기 때문에 좋지 않습니다. 세 번째 방법은 오직 한 개의 전역 변수만을 도입하고 훨씬 더 읽기 쉬운 코드를 만들기 때문에 좋습니다. 네 번째 방법도 좋습니다. 객체지향적 원칙을 이용하여 제네릭한 Button 객체형을 생성하기 때문에 좋지만 나중을 위해 남겨 두도록 하겠습니다.
다음과 같이 전역 btn1 객체를 생성합니다.
var btn1 = {
    x: 100,
    y: 100,
    width: 150,
    height: 50
};
그리고 단일 객체를 입력받은 후 프로퍼티를 잡을 수 있도록 drawButton 함수를 수정합니다.
var drawButton = function(btn) {
    fill(0, 234, 255);
    rect(btn.x, btn.y, btn.width, btn.height, 5);
    fill(0, 0, 0);
    textSize(19);
    textAlign(LEFT, TOP);
    text("Useless button", btn.x+10, btn.y+btn.height/4);
};
mouseClicked 함수는 객체의 프로퍼티를 확인할 것입니다.
mouseClicked = function() {
    if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
        mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height))     {
        println("Still pretty useless");    
    }
};
아래에 시도해 보세요! 전과 같이 버튼의 여러 매개변수를 변경해보고 모든 것이 잘 작동하는지 확인해 보세요.
여태까지 과정은 여러 버튼 추가를 쉽게 해주는 것이 주 목적입니다. 코드 재사용 테스트이죠. 할 수 있나요?
새로운 전역변수 btn2로 시작해 보겠습니다. 이 변수는 첫 번째 버튼과 y 값이 다릅니다.
var btn2 = {
    x: 100,
    y: 200,
    width: 150,
    height: 50
};
그리고 버튼을 그립니다.
drawButton(btn2);
배경에 버튼 두 개를 성공적으로 그리겠지만 첫 번째 버튼만 클릭에 반응할 것입니다. 다음과 같이 코드를 복사한 후 btn1btn2로 바꾸면 두 번째 버튼도 반응하도록 할 수 있습니다.
mouseClicked = function() {
    if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
        mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height))     {
        println("Still pretty useless");    
    }

    if (mouseX >= btn2.x && mouseX <= (btn2.x+btn2.width) &&
        mouseY >= btn2.y && mouseY <= (btn2.y+btn2.height))     {
        println("2nd one still quite useless!");    
    }
};
그러나 반복되는 코드가 싫지 않나요? 버튼 객체를 확인하고 커서가 그 안에 있는지 확인해주는 isMouseInside 함수를 만들어 봅시다.
var isMouseInside = function(btn) {
    return (mouseX >= btn.x &&
            mouseX <= (btn.x+btn.width) &&
            mouseY >= btn.y && 
            mouseY <= (btn.y+btn.height));
};
이제 이 함수를 mouseClicked 함수 내부에 넣으면 반복되는 코드의 양을 줄일 수 있습니다:
mouseClicked = function() {
    if (isMouseInside(btn1))     {
        println("Still pretty useless");    
    } else if (isMouseInside(btn2))     {
        println("2nd one still quite useless!");    
    }
};
훨씬 간단하지요? 버튼 여러개를 그리고 새로운 버튼을 쉽게 추가할 수 있게 하기 위해서 함수를 사용했습니다. 아래에서 확인해 보세요.
프로그램에 모든 버튼의 배열를 만들고 버튼의 라벨과 색깔을 조정하는 것도 가능합니다. 여기서는 함수를 이용하여 간단한 버튼을 생성하는 방법의 기본을 배워 봤습니다. 다음에는 객체지향적 원칙을 이용하여 버튼을 생성하는 방법에 대해 살펴보도록 하겠습니다.