0Pricing
R Academy · 강의

withCallingHandlers()와 재시작

비지역 조건 처리를 위해 withCallingHandlers()를 사용합니다.

withCallingHandlers()와 재시작은(는) CoddyKit의 무료 R Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 R Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

tryCatch와 withCallingHandlers 비교

핵심 차이는 다음과 같습니다. tryCatch()는 비지역적 종료를 설정하므로 조건이 포착되면 제어가 표현식 밖으로 이동하고 돌아오지 않습니다. withCallingHandlers()는 호출 스택을 그대로 유지하며 처리 후 실행을 재개할 수 있습니다.

# tryCatch: execution does NOT continue after warning
tryCatch({
  warning('first')
  cat('This line is never reached\n')
}, warning = function(w) cat('tryCatch caught:', w$message, '\n'))

withCallingHandlers는 실행을 유지함

withCallingHandlers()를 사용하면 처리기가 실행되지만 조건이 신호를 보낸 후에도 실행이 계속됩니다. 단, 처리기 자체가 오류를 발생시키거나 재시작을 호출하는 경우는 예외입니다. 호출 스택은 풀리지 않습니다.

withCallingHandlers({
  warning('first warning')
  cat('Execution continues here\n')
  warning('second warning')
  cat('And here too\n')
}, warning = function(w) {
  cat('Handler saw:', w$message, '\n')
  invokeRestart('muffleWarning')
})

muffleWarning 재시작

경고 처리기 내부에서 invokeRestart('muffleWarning')을 호출하면 R의 기본 처리기가 경고를 출력하지 않도록 억제할 수 있습니다. 이를 사용하지 않으면 처리기가 실행된 후에도 R이 기본 메커니즘을 통해 경고를 출력합니다.

# Without muffleWarning: warning still shows after handler
withCallingHandlers({
  warning('test')
}, warning = function(w) {
  cat('Handler ran\n')
  # no muffleWarning: default handler still fires
})

muffleMessage 재시작

마찬가지로 메시지 처리기 내부에서 invokeRestart('muffleMessage')를 호출하면 사용자 지정 처리기가 메시지를 처리한 후 해당 메시지를 표시하지 않게 할 수 있습니다. suppressMessages()는 이 메커니즘을 사용합니다.

withCallingHandlers({
  message('Progress: 50%')
  message('Progress: 100%')
}, message = function(m) {
  cat('[LOG]', trimws(m$message), '\n')
  invokeRestart('muffleMessage')
})

중단 없이 경고 기록하기

withCallingHandlers()의 실용적인 용도는 코드가 끝까지 실행되도록 하면서 경고를 로그 벡터에 수집하는 것입니다. tryCatch()는 첫 번째 경고에서 중단하지만 withCallingHandlers()는 모든 경고를 수집합니다.

warnings_log <- character(0)
result <- withCallingHandlers({
  x <- log(-1)
  y <- sqrt(-4)
  c(x, y)
}, warning = function(w) {
  warnings_log <<- c(warnings_log, w$message)
  invokeRestart('muffleWarning')
})
cat('Warnings logged:', length(warnings_log), '\n')
cat(warnings_log, sep = '\n')

invokeRestart() 개념

재시작은 조건을 신호로 알리는 코드가 제공할 수 있는 미리 정의된 복구 전략입니다. invokeRestart(name)은 이러한 전략 중 하나를 선택합니다. 기본 제공 재시작에는 'muffleWarning'과 'muffleMessage'가 있으며, withRestarts()로 사용자 지정 재시작을 정의할 수 있습니다.

# withRestarts() offers named recovery options
divide_safe <- function(x, y) {
  withRestarts(
    {
      if (y == 0) stop('division by zero')
      x / y
    },
    use_zero = function() 0,
    use_na   = function() NA
  )
}
# A handler can pick a restart
withCallingHandlers(
  divide_safe(10, 0),
  error = function(e) invokeRestart('use_zero')
)

withCallingHandlers와 tryCatch 결합

두 가지를 중첩할 수 있습니다. 바깥쪽에 withCallingHandlers()를 사용해 조건을 기록하거나 개수를 세고, 안쪽에 tryCatch()를 사용해 대체값을 제공하십시오. 바깥 처리기가 조건을 먼저 확인합니다.

n_warnings <- 0L
result <- withCallingHandlers(
  tryCatch(log(-1), warning = function(w) -999),
  warning = function(w) {
    n_warnings <<- n_warnings + 1L
    cat('Logged warning #', n_warnings, '\n')
  }
)
cat('Result:', result, '\n')

사용자 지정 조건 클래스

클래스가 c('myError', 'error', 'condition')인 목록에 structure()를 호출하면 사용자 지정 조건 클래스를 만들 수 있습니다. 처리기는 클래스를 기준으로 일치하므로 사용자 지정 클래스를 사용하면 모든 오류를 포착하지 않고 특정 오류 유형만 포착할 수 있습니다.

my_error <- function(msg, data = NULL) {
  structure(
    class = c('my_error', 'error', 'condition'),
    list(message = msg, data = data)
  )
}
tryCatch(
  stop(my_error('custom error', data = 42)),
  my_error = function(e) cat('Custom handler, data=', e$data, '\n'),
  error    = function(e) cat('Generic handler\n')
)

withCallingHandlers를 사용할 때

실행을 중단하지 않고 조건을 관찰하거나 기록하려면 withCallingHandlers()를 사용하십시오. 조건에서 복구하여 대체값을 반환하려면 tryCatch()를 사용하십시오. 두 함수는 서로 다른 문제를 해결합니다.

# withCallingHandlers: observe all, continue
withCallingHandlers(
  for (x in c(4, -1, 9, -4)) cat(suppressWarnings(sqrt(x)), ''),
  warning = function(w) cat('[warn]', '')
)
cat('\n')

조건 신호 전달 과정

조건에 신호가 전달되면 R은 처리기를 찾기 위해 호출 스택을 따라 위로 올라갑니다. withCallingHandlers() 처리기는 동적 컨텍스트에서 실행되므로 호출 스택이 유지됩니다. tryCatch() 처리기는 스택이 풀린 후 실행되므로 원래 컨텍스트가 사라집니다.

# Demonstrate: withCallingHandlers handler can see full stack
f <- function() {
  withCallingHandlers(
    g(),
    warning = function(w) {
      cat('Caught in f, stack length:', sys.nframe(), '\n')
      invokeRestart('muffleWarning')
    }
  )
}
g <- function() warning('from g')
f()

suppressWarnings() 구현

suppressWarnings(expr)는 본질적으로 withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning'))입니다. 이를 이해하면 특정 경고 유형만 억제하는 자체 변형을 만들 수 있습니다.

# Suppress only NaN warnings, not others
suppress_nan_warn <- function(expr) {
  withCallingHandlers(expr, warning = function(w) {
    if (grepl('NaN', conditionMessage(w)))
      invokeRestart('muffleWarning')
  })
}
suppress_nan_warn(log(-1))   # NaN warning suppressed
tryCatch(
  suppress_nan_warn(warning('other issue')),
  warning = function(w) cat('Other warning kept:', w$message, '\n')
)

빠른 확인

withCallingHandlers()와 tryCatch()의 주요 차이점은 무엇입니까?

재시작: 핵심 정리

withCallingHandlers와 재시작의 핵심 정리:

  • withCallingHandlers() = 지역 처리기, 호출 스택 유지, 실행 계속 가능
  • tryCatch() = 비지역적 종료, 스택이 풀림, 대체값 반환 가능
  • invokeRestart('muffleWarning')은 경고의 기본 출력을 억제합니다.
  • invokeRestart('muffleMessage')는 메시지의 기본 출력을 억제합니다.
  • 중단 없이 모든 조건을 수집하거나 기록하려면 withCallingHandlers()를 사용하십시오.
  • 사용자 지정 조건 클래스를 사용하면 특정 오류 유형만 선택적으로 포착할 수 있습니다.
log_vec <- character(0)
withCallingHandlers({
  message('start')
  warning('low memory')
  message('end')
}, message = function(m) {
  log_vec <<- c(log_vec, paste('MSG:', trimws(m$message)))
  invokeRestart('muffleMessage')
}, warning = function(w) {
  log_vec <<- c(log_vec, paste('WARN:', w$message))
  invokeRestart('muffleWarning')
})
cat(log_vec, sep = '\n')

자주 묻는 질문

“withCallingHandlers()와 재시작” 강의는 무료인가요?

네 — “withCallingHandlers()와 재시작” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 R Academy 강의 전체를 잠금 해제할 수 있습니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“withCallingHandlers()와 재시작”에서 뭘 배우나요?

비지역 조건 처리를 위해 withCallingHandlers()를 사용합니다. 브라우저에서 직접 실행하는 실습 코드로 R Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

R Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 R Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“withCallingHandlers()와 재시작” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 R Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 R Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. R의 오류, 경고, 메시지
  2. 오류 복구를 위한 tryCatch()
  3. withCallingHandlers()와 재시작
  4. stop()과 warning()으로 견고한 함수 작성하기
← R Academy(으)로 돌아가기