함수 패턴

2025. 3. 30. 22:18Web Development/JavaScript

즉시 실행 함수 표현식(IIFE)

즉시 실행 함수 표현식(Immediately Invoked Function Expression)은 정의되자마자 즉시 실행되는 함수입니다.

// 기본 IIFE 문법
(function() {
  console.log("즉시 실행됩니다!");
})(); // "즉시 실행됩니다!" 출력

// 매개변수 전달
(function(name) {
  console.log("안녕하세요, " + name + "님!");
})("홍길동"); // "안녕하세요, 홍길동님!" 출력

// 화살표 함수로 IIFE
(() => {
  console.log("화살표 함수 IIFE");
})(); // "화살표 함수 IIFE" 출력

// 반환값 받기
const result = (function() {
  const a = 5;
  const b = 3;
  return a * b;
})();

console.log(result); // 15 출력

// 모듈 패턴
const counter = (function() {
  let count = 0;
  
  return {
    increment: function() {
      count++;
    },
    decrement: function() {
      count--;
    },
    getCount: function() {
      return count;
    }
  };
})();

counter.increment();
counter.increment();
console.log(counter.getCount()); // 2 출력

재귀 함수

재귀 함수는 자기 자신을 호출하는 함수입니다. 복잡한 문제를 더 작은 문제로 나누어 해결할 때 유용합니다.

// 기본 재귀 함수: 팩토리얼 계산
function factorial(n) {
  if (n <= 1) return 1; // 기저 조건(재귀 종료 조건)
  return n * factorial(n - 1); // 재귀 호출
}

console.log(factorial(5)); // 120 출력 (5! = 5 * 4 * 3 * 2 * 1)

// 피보나치 수열
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(7)); // 13 출력 (0, 1, 1, 2, 3, 5, 8, 13, ...)

// 깊은 복사 구현
function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // 원시값이나 null은 그대로 반환
  }
  
  // 배열인 경우
  if (Array.isArray(obj)) {
    return obj.map(item => deepCopy(item));
  }
  
  // 객체인 경우
  const copy = {};
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  
  return copy;
}

const original = { a: 1, b: { c: 2 }, d: [3, 4] };
const copied = deepCopy(original);
copied.b.c = 10;
console.log(original.b.c); // 2 (원본은 변경되지 않음)
console.log(copied.b.c); // 10

재귀 함수 사용 시 주의사항:

  • 반드시 종료 조건(기저 조건)을 설정해야 함
  • 호출 스택 제한으로 인한 스택 오버플로우 가능성
  • 동일한 작업을 반복 계산하는 비효율성 (메모이제이션으로 해결 가능)
// 메모이제이션을 적용한 피보나치 함수
function fibonacciMemo(n, memo = {}) {
  if (n in memo) return memo[n];
  if (n <= 1) return n;
  
  memo[n] = fibonacciMemo(n - 1, memo) + fibonacciMemo(n - 2, memo);
  return memo[n];
}

console.log(fibonacciMemo(40)); // 성능이 크게 향상됨

고차 함수

고차 함수(Higher-Order Function)는 함수를 인자로 받거나 함수를 반환하는 함수입니다.

// 함수를 인자로 받는 고차 함수
function applyOperation(a, b, operation) {
  return operation(a, b);
}

const add = (x, y) => x + y;
const subtract = (x, y) => x - y;
const multiply = (x, y) => x * y;

console.log(applyOperation(5, 3, add)); // 8 출력
console.log(applyOperation(5, 3, subtract)); // 2 출력
console.log(applyOperation(5, 3, multiply)); // 15 출력

// 함수를 반환하는 고차 함수
function createValidator(validationFunc) {
  return function(value) {
    return {
      value,
      isValid: validationFunc(value),
    };
  };
}

const isPositive = num => num > 0;
const isAdult = age => age >= 18;

const validatePositive = createValidator(isPositive);
const validateAdult = createValidator(isAdult);

console.log(validatePositive(10)); // { value: 10, isValid: true }
console.log(validatePositive(-5)); // { value: -5, isValid: false }
console.log(validateAdult(20)); // { value: 20, isValid: true }

함수형 프로그래밍 기법

JavaScript에서는 함수를 일급 객체로 취급하므로 함수형 프로그래밍 패턴을 적용할 수 있습니다.

// 순수 함수(Pure Function)
function add(a, b) {
  return a + b; // 외부 상태에 의존하지 않고, 부수 효과가 없음
}

// 커링(Currying)
function curry(fn) {
  return function(a) {
    return function(b) {
      return fn(a, b);
    };
  };
}

const curriedAdd = curry(add);
const addFive = curriedAdd(5);
console.log(addFive(3)); // 8 출력

// 함수 합성(Function Composition)
const compose = (f, g) => x => f(g(x));

const double = x => x * 2;
const square = x => x * x;

const doubleAndSquare = compose(square, double);
console.log(doubleAndSquare(3)); // 36 출력 (3 * 2 = 6, 6 * 6 = 36)

// 배열 메서드를 활용한 함수형 프로그래밍
const numbers = [1, 2, 3, 4, 5];

// map: 변환
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// filter: 필터링
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]

// reduce: 누적
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15

// 메서드 체이닝
const result = numbers
  .filter(n => n % 2 === 0) // [2, 4]
  .map(n => n * n)          // [4, 16]
  .reduce((acc, curr) => acc + curr, 0); // 20

console.log(result); // 20

'Web Development > JavaScript' 카테고리의 다른 글

배열  (0) 2025.03.30
객체  (0) 2025.03.30
클로저(Closure)  (0) 2025.03.30
스코프  (0) 2025.03.30
함수의 정의와 호출  (0) 2025.03.30