browser()
browser( )가 호출되면 명령의 수행이 중지되고, 해당 시점부터 디버깅 모드가 시작된다. 디버깅 모드가 되면 browser( )가 호출된 행에서 접근 가능한 변수 및 함수의 내용을 볼 수 있으며, 코드를 한 행씩 실행하거나 다시 browser( )가 호출될 때까지 명령의 실행을 재개할 수 있다.
browser( )가 실행되는 환경을 살펴보자. 다음 코드는 1에서 10까지의 합을 구하다가 i가 5 이상일 때 수행을 정지하고 browser( )를 수행하는 예다.
> sum_to_ten <- function() { + sum <- 0 + for (i in 1:10) { + sum <- sum + i + if (i >= 5) { + browser() + } + } + return(sum) + }
이 코드를 실행하면 다음과 같이 ‘Browse’라는 새로운 프롬프트가 출력된다.
> sum_to_ten()
Called from: sum_to_ten()
Browse[1]>
이 프롬프트는 i가 5인 상황에서 정지된 그 환경을 그대로 가지고 있다. 따라서 i나 sum의 값을 출력해보거나 일반적인 R 명령 프롬프트에서 하는 모든 작업을 해볼 수 있다. 다음은 browser( )가 호출된 상태에서 i와 sum 값을 출력하고 i와 sum의 합을 구하는 예를 보여준다.
Browse[1]> i [1] 5 Browse[1]> sum [1] 15 Browse[1]> sum + i [1] 20
Browse 프롬프트에서는 다음 표에 보인 명령들을 사용할 수 있다.
명령 |
의미 |
c |
continue. 다음 browser( ) 명령을 만날 때까지 코드의 수행을 재개 |
n |
next. 현재 수행한 명령의 다음 명령을 수행 |
Q |
Quit. browser( )를 종료 |
현재 예에서는 i가 5 이상일 때 매번 browser( )가 호출되게 했으므로, i가 5일 때 정지된 상태에서 c를 입력하면 i가 6일 때 다시 browser( )로 진입한다.
Browse[1]> c Called from: sum_to_ten() Browse[1]> i [1] 6 Browse[1]> sum [1] 21
n은 정지된 상태의 다음 문장을 차례로 수행하는 명령이다. n을 입력할 때마다 현재 수행 중인 문장을 출력하여 보여주므로 어느 코드가 수행되었는지를 알 수 있다.
Browse[1]> n debug at #3: i Browse[2]> n debug at #4: sum <- sum + i
browser( )의 수행을 마치려면 Q를 입력한다.
Browse[2]> Q
>
browser( )는 함수의 사용법을 알아보는 데도 유용하다. 예를 들어, plyr의 ddply( )가 주어진 함수에 어떤 값들을 넘기고 있는지 확인하는 데도 쓸 수 있다. 다음은 ddply를 사용해 아이리스 데이터를 붓꽃의 종Species별로 묶었을 때 지정한 함수에 어떤 행들이 넘어오는지를 확인하는 목적으로 browser( )를 사용한 예다.
> library(plyr) > ddply(iris, .(Species), function(rows) { browser() }) Called from: .fun(piece, ...) Browse[1]> head(rows) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa
지금까지 디버깅을 위한 여러 가지 방법을 살펴봤다. 그러나 코드 완결성을 위해서는 디버깅에 의존하기보다는 testthat과 같은 유닛 테스팅을 자주 또는 먼저 작성하여 좀 더 다양한 테스트를 수행하기를 권한다. 테스트를 작성하면 사전에 예상하지 못한 다양한 입력에 대해 코드를 검증해볼 수 있으며, 코드를 수정할 때 새로운 버그가 생기지 않았음을 좀 더 쉽게 확인할 수 있기 때문이다.