더북(TheBook)

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 프롬프트에서는 다음 표에 보인 명령들을 사용할 수 있다.

표 5-21 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과 같은 유닛 테스팅을 자주 또는 먼저 작성하여 좀 더 다양한 테스트를 수행하기를 권한다. 테스트를 작성하면 사전에 예상하지 못한 다양한 입력에 대해 코드를 검증해볼 수 있으며, 코드를 수정할 때 새로운 버그가 생기지 않았음을 좀 더 쉽게 확인할 수 있기 때문이다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.