JavaScript 함수 —
선언 · 파라미터 · return 완전 정리
같은 값을 여러 번 계산해야 할 때마다 코드를 복사-붙여넣기 하면 실수도 늘고 관리도 힘들어진다. 이럴 때 쓰는 게 함수(function)다. 아래는 두 수를 더해서 결과를 돌려주는 가장 단순한 함수 adder()다.
▸ adder(24567, 98374) 실행 결과
24567 + 98374는 122941
▸ gugudan(3) 실행 결과 (prompt에 "3" 입력 시)
3x1=3
3x2=6
3x3=9
3x4=12
3x5=15
3x6=18
3x7=21
3x8=24
3x9=27
두 수를 더하는 계산이 프로그램 여러 곳에서 필요하다고 해보자. 함수 없이는 document.write(24567 + 98374) 같은 코드를 필요할 때마다 새로 써야 한다. 값이 바뀔 때마다 코드를 고쳐야 하고, 실수할 여지도 그만큼 늘어난다.
함수는 "이 계산 로직을 adder라는 이름으로 한 번만 정의해두고, 필요할 때마다 이름만 불러 쓰자"는 약속이다. 로직은 한 곳에만 있으니 수정도 한 곳만 고치면 된다.
adder(24567, 98374)만 봐도 "두 수를 더하는구나"를 바로 알 수 있다.함수를 만드는 기본 형태는 정해져 있다. function 키워드로 "지금부터 함수를 선언한다"고 알리고, 뒤에 함수 이름, 괄호 안에 매개변수, 중괄호 안에 실행할 코드를 적는다.
이렇게 function으로 선언만 해두면 브라우저는 이 함수를 기억만 해둘 뿐, 이 시점에 실행하지는 않는다. 실행은 나중에 함수 이름을 부를 때(호출할 때) 일어난다.
function adder(a, b)에서 a와 b는 매개변수(parameter)다. 함수를 선언하는 시점에는 아직 실제 값이 없다. "나중에 호출할 때 값 두 개를 이 이름으로 받겠다"는 빈 자리, 일종의 상자 이름표다.
함수가 adder(24567, 98374)로 호출되는 순간, 첫 번째 값 24567은 a에, 두 번째 값 98374는 b에 순서대로 채워진다. 이렇게 채워진 뒤에야 함수 몸통 안에서 a + b 같은 계산이 의미를 가진다.
adder(24567, 98374)와 adder(98374, 24567)는 결과는 같아도(덧셈이라서) 실제로는 a·b에 들어가는 값이 서로 바뀐다.
함수 안에서 sum = a + b;까지만 계산하고 끝나면, 그 계산 결과는 함수 안에 갇혀 있다. 함수 밖에서는 sum이라는 변수 자체가 존재하지 않으니 이 값을 알 방법이 없다.
return sum;은 "이 함수를 호출한 자리로 sum 값을 돌려주고, 함수 실행을 여기서 끝낸다"는 뜻이다. return을 만나는 순간 그 아래 코드가 있어도 실행되지 않고 함수가 즉시 종료된다.
호출한 쪽은 결과를 받을 수 없음
→ 호출식의 값은
undefined값이 되어 밖으로 전달됨
→
let n = adder(...)로 받을 수 있음함수를 만들어두기만 하면 아무 일도 일어나지 않는다. adder(24567, 98374)처럼 이름 뒤에 괄호를 붙이고 실제 값을 넣어 불러야 비로소 함수 안의 코드가 실행된다. 이것을 호출(call)이라고 한다.
이때 adder(24567, 98374) 자체는 함수가 return한 값(122941)으로 치환된다고 생각하면 쉽다. 그래서 let n = adder(24567, 98374);는 결국 let n = 122941;과 같은 효과를 낸다. 이렇게 반환값을 변수에 담아두면 이후 코드에서 그 값을 계속 재사용할 수 있다.
let sum;은 adder 함수 안에서 선언됐다. 이렇게 함수 몸통 안에서 만든 변수를 지역변수(local variable)라 부르는데, 이 변수는 그 함수가 실행되는 동안만 존재하고 함수가 끝나면 사라진다.
즉 adder 함수 밖에서 console.log(sum)을 실행하면 에러가 난다. sum이라는 이름은 adder 함수 안에서만 의미가 있다. 이 덕분에 다른 함수에서 같은 이름 sum을 써도 서로 충돌하지 않는다 — 각자의 함수 안에 갇혀 있기 때문이다.
이제 두 번째 예제 gugudan()을 보자. 이 함수는 몇 단을 출력할지를 코드에 직접 적지 않고, 사용자가 직접 입력하도록 만든다. 이때 쓰는 것이 prompt()다.
prompt(질문, 기본값)은 브라우저에 입력창을 띄우고, 사용자가 입력한 값을 항상 문자열(string)로 돌려준다. 사용자가 "3"이라고 숫자처럼 보이는 값을 입력해도, JavaScript 입장에서는 숫자 3이 아니라 문자 "3" 한 글자다.
m * i 같은 곱셈에 쓰면 예상과 다르게 동작할 수 있다.gugudan(n) 함수 안에서 가장 먼저 하는 일이 let m = parseInt(n);이다. parseInt()는 문자열 맨 앞부터 숫자로 읽을 수 있는 만큼 읽어서 진짜 숫자(number) 타입으로 바꿔주는 함수다.
문제는 사용자가 "abc"처럼 숫자로 바꿀 수 없는 값을 입력할 수도 있다는 점이다. 이때 parseInt("abc")의 결과는 NaN(Not a Number, "숫자가 아님"이라는 특수 값)이 된다. isNaN(m)은 바로 이 상황을 걸러내는 검사다 — "m이 NaN인가?"를 true/false로 알려준다.
여기에 m < 1 || m > 9 조건까지 ||(또는)로 묶여서, "숫자가 아니거나, 1보다 작거나, 9보다 크면" 전부 잘못된 입력으로 처리한다. 구구단은 1~9단만 의미가 있기 때문이다.
NaN === NaN은 놀랍게도false다 — 그래서m === NaN처럼 비교하면 절대 안 걸러진다- 반드시 전용 함수
isNaN(m)으로만 "숫자가 아님"을 검사한다 Number.isNaN(m)도 같은 목적이지만 더 엄격하게 타입까지 확인한다
조건이 참이면 alert("잘못입력하셨습니다.")로 사용자에게 경고창을 띄운 뒤, 값 없이 return;만 실행한다. 이렇게 함수 초반에 "이 상황이면 더 볼 것도 없이 끝낸다"고 미리 빠져나가는 패턴을 early return(조기 반환)이라 부른다.
early return이 없다면 어떻게 될까? 잘못된 값(예: m이 NaN)이 그대로 아래 for문까지 흘러가서 NaNx1=NaN 같은 의미 없는 결과를 9줄이나 출력하게 된다. 조건에 걸리자마자 즉시 return으로 빠져나가면 이런 불필요한 실행을 막을 수 있다.
- 잘못된 상황을 함수 맨 앞에서 먼저 걸러내 코드 흐름이 명확해진다
- if-else를 깊게 중첩하지 않아도 되어 코드가 읽기 쉬워진다
- 정상 케이스만 함수 뒷부분에 남아 핵심 로직이 눈에 잘 띈다
입력값이 1~9 사이의 정상적인 숫자라는 게 확인되면, for(let i=1; i<=9; i++)로 i를 1부터 9까지 하나씩 늘려가며 m * i를 계산해 화면에 출력한다.
m이 3이라면 i가 1일 때 "3x1=3", i가 2일 때 "3x2=6"... i가 9가 될 때까지 총 9줄을 출력하고 반복문이 끝나면 함수도 자연스럽게 종료된다. return 없이 끝나는 함수는 값을 돌려주지 않을 뿐, 실행 자체는 정상적으로 끝난다.
| 실수 | 증상 | 해결 |
|---|---|---|
| return을 빠뜨림 | 함수 호출 결과가 undefined로 나옴 |
값을 돌려줘야 하면 반드시 return 값; 작성 |
| prompt 결과를 그냥 계산에 씀 | "3" + "4"가 34로 문자열 연결되어버림 | parseInt()로 숫자 타입 변환 후 계산 |
| 매개변수 개수와 인자 개수 불일치 | 덜 넘긴 매개변수는 undefined가 됨 |
함수 선언의 매개변수 순서·개수에 맞춰 호출 |
| early return 없이 그대로 진행 | 잘못된 입력에도 for문이 실행되어 이상한 값 출력 | 검증 실패 시 alert 후 return;으로 즉시 종료 |
| isNaN 검사를 생략함 | "abc" 같은 값이 그대로 통과해 NaN 결과 발생 | isNaN(m)으로 숫자 여부 먼저 확인 |
| 지역변수를 함수 밖에서 사용하려 함 | "sum is not defined" 에러 발생 | 필요한 값은 return으로 꺼내 변수에 저장 |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| JavaScript 객체 생성 — new Date · String · Array 완전 정리 (0) | 2026.07.03 |
|---|---|
| JavaScript 전역 함수 — eval · parseInt · isNaN 완전 정리 (0) | 2026.07.03 |
| JavaScript break · continue — 반복 제어 완전 정리 (0) | 2026.07.03 |
| JavaScript switch — 커피 주문 완전 정리 (0) | 2026.07.03 |
| JavaScript 반복문 — for · while · do-while 완전 정리 (0) | 2026.07.03 |
왕진 블로그

댓글