콜백 함수 (Callback function)

1. 효율적 비동기 처리, 콜백 함수 (Callback function) 개요

개념코드 재사용, 비동기 처리를 위해 특정 작업이 완료된 후 실행되도록 다른 코드의 인수로 넘겨주는 실행 가능한 코드
사용
목적
이벤트 핸들링– 특정 이벤트에 대한 처리 함수를 등록 후 해당 이벤트 발생 시 호출
비동기 수행– Network 통신 등 오랜 시간이 소요되는 작업의 Non-Blocking I/O 처리
추상화/다형성– 함수 내부 로직 수정없이 외부 함수를 통해 원하는 동작을 자유롭게 교체
  • 콜백 함수 전달 시 콜백 함수의 포인터 (핸들), 서브루틴 또는 람다함수 형태로 넘겨주며, 효율적인 비동기(Async) 처리와 성능 최적화, 코드 재사용성 극대화, 이벤트 기반(Event-driven) 아키텍처 구현이 가능

 

2. 콜백 함수의 처리 절차 및 구성요소

(1) 콜백 함수의 처리 절차

콜백 함수 처리 절차
Callback 함수 등록
및 비동기 작업 수행
– 메인 스레드의 Call Stack에서 비동기 태스크와 콜백 함수 전달/등록 후 수행
비동기 작업 완료 시
Task Queue 등록
– 백그라운드 영역에서 비동기 작업 완료 시 해당 콜백 함수를 Task Queue에 등록
Call Stack 확인
dispatch
– 이벤트 루프가 Call Stack이 완전히 비어 있는지 확인한 후 콜백 함수를 꺼내 CPU가 수행할 수 있도록 dispatch
Call Stack Push,
Main Thread 완료
– 이벤트 루프가 콜백을 Call Stack으로 Push하여 메인 스레드에서 연산 완료

(2) 콜백 함수의 구성요소

구분구성요소역할
데이터
전달
/실행
호출자
(Caller)
– 콜백 함수를 매개변수로 전달받아 내부 로직에서 적절한 시점에 실행
– 콜백 함수 제어권 위임받아, 비동기 작업 완료 여부에 따라 콜백 호출
호출 대상
(Callee)
– 호출자(Caller)에게 인자로 넘겨져 나중에 실행되도록 예약된 함수
– 독립된 로직으로 호출자가 넘겨주는 데이터를 넘겨 받아 후속 연산
런타임
제어
태스크 큐
(Task Queue)
– 백그라운드 작업 후, 실행 대기 콜백 함수들이 FIFO 구조로 적재
– 콜백 함수들이 소실되지 않도록 순서대로 안전하게 보관
이벤트 루프
(Event Loop)
– 호출 스택(Call Stack)과 태스크 큐(Task Queue)의 상태를 상시 감시
– 태스크 큐에서 대기 중인 콜백 함수를 호출 스택으로 이동(Dispatch)
실행
보장
실행 컨텍스트
(Execution Context)
– 콜백 함수 선언 당시 주변의 변수와 스코프(Scope) 기억하는 메모리
– 나중에 실행되는 콜백 함수의 선언 당시의 상태와 변수 데이터에 접근
에러 핸들러
(Error Handler)
– 비동기 작업 성공 여부 판별, 예외 처리 위한 방어적 매개변수/분기
– 콜백 내부로 에러 상태를 명확히 전달, 안정적 예외 복구 보장
  • 프로그램에서 콜백 함수 사용 시 호출자와 콜백이 데이터를 교환, 태스크 큐와 이벤트 루프(런타임)가 실행 타이밍을 조율하며, 클로저와 에러 핸들러(안정성)가 환경과 예외를 방어하는 유기적인 조합으로 수행

 

3. 콜백 함수 사용 시 고려사항 및 예제

(1) 콜백 함수 사용 시 고려사항

구분고려사항목표
오류
관리
예외 처리의 분리– 예외 발생 시 프로세스 수행 보장 위해 콜백 내부에서 에러 처리
– 에러 인자 존재 시 런타임 예외 로깅 및 리턴하는 방어적 코드 작성
콜백 지옥과
가독성 관리
– 코드의 뎁스(Depth)가 3단계 이상 깊어지지 않도록 모니터링 수행
– Promise, async/await 문법으로 리팩토링, 동기식 코드로 구조 개선
S/W
제어
메모리 누수 방지– 이벤트 리스너 등 반복 등록 콜백 사용 후 적절한 해제 여부 확인
– removeEventListener 호출, 가비지 컬렉터(GC)로 메모리 정상  수거
제어권/신뢰성
확보
– 실행 횟수, 실행 가능성, 실행 속도를 고려하여 프로세스 제어권 확보
– 의도치 않은 다수 호출 방지(once 플래그 래퍼) 등 신뢰성 모듈 탑재

(2) 콜백 함수 예제

# 1. 나중에 실행될 콜백 함수를 정의
def send_sms(user):
    print(f"[콜백 실행] {user}님에게 '회원가입 완료' 문자를 발송했습니다.")

# 2. 메인 작업을 하는 함수이며, 인자로 콜백 함수 입력
def register_user(user_name, callback):
    print(f"[메인 작업] {user_name}님의 정보를 DB에 저장하는 중...")
    print("[메인 작업] 회원가입 처리가 완료되었습니다.")
    
    # 3. 메인 작업 종료 시 넘겨받은 콜백 함수를 실행(Call Back)
    callback(user_name)

# 4. 함수 호출 시 콜백 함수명을 인자로 전달
register_user("나신입", send_sms)
  • 회원가입 함수(register_user())에 콜백 함수인 send_sms를 인자로 위임 등록하고, 회원 가입 처리가 완료된 시점에 전달받은 콜백을 최종 호출해 실행

[결과]

[메인 작업] 나신입님의 정보를 DB에 저장하는 중…
[메인 작업] 회원가입 처리가 완료되었습니다.
[콜백 실행] 나신입님에게 ‘회원가입 완료’ 문자를 발송했습니다.

 
[참고]

  • Wikipedia, Callback (computer programming)
  • MDN Web Doc, Callback function
  • Massachusetts Institute of Technology(MIT), Callbacks and Graphical User Interfaces, Spring 2022

콘텐츠 사용 시 출처 표기 부탁 드리고, 댓글은 큰 힘이 됩니다^^