콘텐츠로 이동

15. 시스템 함수

R을 쓰다 보면 데이터가 아니라 "R이 지금 어떤 상태로 실행되고 있는가" 자체가 문제가 되는 순간이 있습니다. 예를 들어 저자의 컴퓨터에서는 잘 실행되던 스크립트가 다른 사람의 컴퓨터에서는 파일을 찾지 못하거나, 한글이 깨져 보이거나, R 버전 차이로 다른 결과가 나오는 일이 흔히 벌어집니다. 또한 최근에는 R 스크립트 안에서 외부 API를 호출하는 경우가 늘면서, API 키처럼 유출되면 안 되는 값을 코드에 직접 적지 않고 안전하게 관리하는 방법도 중요해졌습니다.

아래와 같은 질문들은 지금까지 배운 데이터 처리 함수로는 답할 수 없고, 이 장에서 다루는 "시스템 함수"로만 답할 수 있습니다.

getwd()                  # 지금 R이 어느 폴더를 기준으로 파일을 찾고 있는가?
R.version.string          # 이 컴퓨터에는 R이 몇 버전 설치되어 있는가?
Sys.info()["sysname"]     # 운영체제는 무엇인가?
Sys.getenv("MY_API_KEY")  # 코드에 직접 적지 않은 API 키를 어떻게 불러올 수 있는가?

이 장에서 다루는 함수는 크게 두 갈래로 나뉩니다.

절 다루는 내용 대표 함수
15.1 작업 환경 R 세션을 둘러싼 폴더·환경변수·로캘(지역 설정)·설치 경로를 조회하거나 바꾸는 함수 getwd(), Sys.getenv(), Sys.setlocale(), .libPaths(), Sys.which()
15.2 세션 정보 R 세션 자체(버전, 운영체제, 전역 옵션, 실행 시간)에 대한 정보를 조회하는 함수 sessionInfo(), Sys.info(), options(), Sys.sleep(), system.time()

이 장의 함수는 대부분 Sys.xxx() 형태의 이름을 가지며, 다음과 같은 공통 규칙을 따릅니다.

  • 인자 없이 호출하면 현재 상태를 조회합니다.
  • 값을 인자로 넘기면 그 값으로 설정합니다.
  • 조회 함수와 설정 함수가 쌍을 이루는 경우가 많습니다(getwd() ↔ setwd(), Sys.getenv() ↔ Sys.setenv(), Sys.getlocale() ↔ Sys.setlocale()).

일러두기: 이 장의 함수들은 실행하는 컴퓨터의 운영체제·설치된 R 버전·로캘에 따라 결과가 달라집니다. 다만 함수의 동작 방식과 반환값의 형식(구조)은 어느 환경에서나 동일합니다.

15.1 작업 환경

R 스크립트에서 read.csv("data.csv")처럼 상대경로로 파일을 지정하면, R은 지금 자신이 어느 폴더에 있다고 생각하는지(작업 디렉토리)를 기준으로 그 파일을 찾습니다. 또한 API 키·비밀번호처럼 코드에 직접 적으면 안 되는 값, 한글이 포함된 파일을 읽을 때 인코딩이 맞지 않아 글자가 깨지는 문제, 여러 R 버전을 오갈 때 패키지가 어느 폴더에 설치되는지 등도 모두 "지금 이 R 세션을 둘러싼 환경이 어떻게 설정되어 있는가"의 문제입니다.

협업자에게 스크립트 폴더를 통째로 전달했는데 "파일을 찾을 수 없습니다"라는 오류가 났다면, 가장 먼저 확인해야 할 것은 두 사람의 작업 디렉토리가 다른지 여부입니다.

getwd()   # 나와 협업자의 작업 디렉토리가 같은 폴더를 가리키는지 먼저 확인

15.1절의 함수들은 "지금 상태를 알려줘(조회)"와 "이렇게 바꿔줘(설정)"라는 두 가지 동작을 공통으로 지원하며, 대상에 따라 다음과 같이 나뉩니다.

함수 확인·설정 대상
getwd() / setwd() 작업 디렉토리(파일을 찾는 기준 폴더)
Sys.getenv() / Sys.setenv() / Sys.unsetenv() 운영체제 환경변수
Sys.setlocale() / Sys.getlocale() 로캘(언어·문자 인코딩·날짜 표기 등 지역 설정)
.libPaths() 패키지가 설치·검색되는 라이브러리 경로
Sys.which() 외부 프로그램(git, pandoc 등)의 설치 경로

getwd() / setwd()

getwd()는 현재 R 세션의 작업 디렉토리(working directory) 경로를 반환합니다. setwd(dir)는 작업 디렉토리를 dir로 변경합니다.

주요 인자

  • dir : 변경할 디렉토리의 경로(문자열). 절대경로("C:/Users/이름/문서", "/home/user/project")와 상대경로("..", "./data") 모두 쓸 수 있고, "~"는 운영체제의 사용자 홈 디렉토리를 가리킵니다. R은 Windows에서도 경로 구분자로 \ 대신 /를 그대로 인식하므로, 코드에서는 운영체제와 무관하게 /를 쓰는 것이 안전합니다.

작업 디렉토리는 read.csv("data.csv")처럼 상대경로로 파일을 지정했을 때 R이 그 파일을 찾는 기준 폴더입니다. 상대경로를 쓰면 폴더를 통째로 옮기거나 다른 컴퓨터에서 실행해도 코드가 그대로 동작하므로, setwd("C:/Users/철수/Desktop/...")처럼 특정 컴퓨터에만 존재하는 절대경로를 스크립트에 하드코딩하는 것은 피하는 것이 좋습니다. RStudio를 쓴다면 .Rproj 파일을 이용한 프로젝트로 폴더를 관리하면, 그 프로젝트를 열 때마다 작업 디렉토리가 자동으로 프로젝트 폴더로 맞춰져 이 문제를 근본적으로 피할 수 있습니다.

getwd()
#> [1] "C:/r-project"

setwd("data")   # 하위 폴더로 이동(상대경로)
getwd()
#> [1] "C:/r-project/data"

setwd("..")     # 상위 폴더로 복귀
getwd()
#> [1] "C:/r-project"

Sys.getenv() / Sys.setenv() / Sys.unsetenv()

Sys.getenv(x, unset = "", names = NA)는 운영체제의 환경변수(environment variable) 값을 조회합니다. Sys.setenv(...)는 환경변수를 설정하고, Sys.unsetenv(x)는 환경변수를 제거합니다.

주요 인자

  • x(Sys.getenv) : 조회할 환경변수 이름(문자벡터). 생략하면(기본값 NULL) 설정된 환경변수 전체를 이름-값 쌍으로 반환합니다.
  • unset : x로 지정한 이름의 환경변수가 존재하지 않을 때 대신 반환할 값(기본값은 빈 문자열 "").
  • names : 반환값에 환경변수 이름을 붙일지 여부. 기본값 NA는 x의 길이가 1보다 클 때만 이름을 붙입니다.
  • ...(Sys.setenv) : 이름 = 값 형태로 설정할 환경변수들.
  • x(Sys.unsetenv) : 제거할 환경변수 이름(문자벡터).
Sys.getenv("R_HOME")   # R이 설치된 경로를 담은 환경변수
#> [1] "C:/PROGRA~1/R/R-46~1.1"

Sys.getenv("NONEXISTENT_VAR_XYZ", unset = "(설정되지 않음)")
#> [1] "(설정되지 않음)"

Sys.setenv(MY_API_KEY = "abcd1234")
Sys.getenv("MY_API_KEY")
#> [1] "abcd1234"

Sys.unsetenv("MY_API_KEY")
Sys.getenv("MY_API_KEY", unset = "(제거됨)")
#> [1] "(제거됨)"

실전 활용: API 키를 코드에 노출하지 않고 관리하기

최근에는 R 스크립트에서 생성형 AI API처럼 인증키(API key)가 필요한 외부 서비스를 호출하는 일이 많아졌습니다. 이때 api_key <- "sk-abcd1234..."처럼 키 값을 코드에 그대로 적으면, 그 스크립트를 GitHub 같은 공개 저장소에 올리는 순간 키가 함께 노출되는 사고로 이어질 수 있습니다.

이런 값은 스크립트가 아니라 사용자 홈 디렉토리의 .Renviron 파일에 이름=값 형태로 한 줄씩 적어 두면, R을 시작할 때 자동으로 읽어 들여 세션 내내 Sys.getenv()로 조회할 수 있습니다. .Renviron 파일은 다음과 같이 base R의 file.edit()로 바로 열 수 있으며(파일이 없으면 새로 만듭니다), 편집기 창을 열 뿐 화면에 출력되는 값은 없습니다.

file.edit(file.path(Sys.getenv("HOME"), ".Renviron"))
# .Renviron 파일 내용 예시(따옴표 없이 이름=값 형태로 한 줄씩)
MY_API_KEY=abcd1234...

파일을 저장하고 R 세션을 재시작하면 Sys.getenv("MY_API_KEY")로 값을 불러올 수 있습니다. 이 방식이 안전한 이유는 .Renviron 파일이 스크립트와 분리된 별도 파일이기 때문입니다 — GitHub 저장소를 만들 때 .gitignore에 .Renviron을 추가해 두면, 실수로 커밋에 포함시킬 위험도 함께 막을 수 있습니다.

Sys.setlocale() / Sys.getlocale()

Sys.setlocale(category = "LC_ALL", locale = "")는 R 세션의 로캘(locale) — 언어, 문자 인코딩, 날짜·통화 표기 방식 등 지역 설정 — 을 변경합니다. Sys.getlocale(category = "LC_ALL")은 현재 로캘을 조회합니다.

주요 인자

  • category : 변경(조회)할 로캘의 범주. "LC_ALL"(기본값, 전체 일괄)을 비롯해 "LC_CTYPE"(문자 인코딩), "LC_TIME"(날짜·시간 표기 언어), "LC_COLLATE"(문자열 정렬 순서), "LC_MONETARY"(통화 표기) 등으로 세분화해서 지정할 수 있습니다.
  • locale : 설정할 로캘 이름. 빈 문자열 ""(기본값)은 운영체제가 지정한 기본 로캘을 그대로 사용한다는 뜻입니다. macOS·Linux에서는 "ko_KR.UTF-8"처럼 "언어_국가.인코딩" 형식을, Windows에서는 R 4.2 이상부터 "Korean_Korea.utf8" 형식(그 이전 버전은 "Korean")을 주로 사용합니다.

한글이 포함된 CSV 파일을 읽었을 때 글자가 깨지거나, 그래프의 한글 축 제목이 네모(☐)로 표시되는 문제의 상당수는 R 세션의 로캘과 파일의 실제 인코딩이 어긋나기 때문에 생깁니다. 문제가 발생하면 가장 먼저 Sys.getlocale()로 현재 설정을 확인하는 것이 진단의 출발점입니다.

Sys.setlocale("LC_ALL", "ko_KR.UTF-8")
Sys.getlocale()
#> [1] "LC_COLLATE=ko_KR.UTF-8;LC_CTYPE=ko_KR.UTF-8;LC_MONETARY=ko_KR.UTF-8;LC_NUMERIC=C;LC_TIME=ko_KR.UTF-8"

LC_TIME이 한국어로 설정되면 format()으로 날짜를 표시할 때 요일도 한글로 나옵니다(10.3절 참고).

format(Sys.Date(), "%Y년 %m월 %d일 %A")
#> [1] "2026년 07월 22일 수요일"

💡 최신 동향: Windows의 UTF-8 지원. R 4.2.0(2022년 4월 출시)부터 Windows용 R은 새로운 C 런타임(UCRT)을 기반으로 UTF-8을 네이티브 인코딩으로 지원하기 시작했습니다. 그 이전까지는 Windows에서 한글 등 비영어권 문자를 다룰 때 인코딩 문제가 자주 발생했지만, R 4.2 이상 버전에서는 macOS·Linux와 마찬가지로 UTF-8을 기본으로 다룰 수 있어 이런 문제가 크게 줄었습니다. 다만 완전히 사라진 것은 아니므로, 여전히 한글이 깨진다면 (1) 스크립트 파일 자체가 UTF-8로 저장되어 있는지(RStudio 기준 File → Save with Encoding), (2) Sys.getlocale()의 LC_CTYPE이 UTF-8 계열인지를 함께 확인해 보는 것이 좋습니다.

.libPaths()

.libPaths(new, include.site = TRUE)는 R이 패키지를 설치하거나 찾을 때 검색하는 라이브러리(library) 경로들을 조회하거나 설정합니다.

주요 인자

  • new : 새로 지정할 라이브러리 경로(문자벡터). 생략하면 현재 설정을 조회만 합니다. 지정하면 기존 경로에 이어 붙이는 것이 아니라 완전히 교체한다는 점에 유의해야 합니다.
  • include.site : TRUE(기본값)이면 R 설치 시 기본으로 지정되는 사이트 라이브러리 경로를 결과에 포함해서 유지합니다.
.libPaths()
#> [1] "C:/Users/사용자명/AppData/Local/R/win-library/4.6"
#> [2] "C:/Program Files/R/R-4.6.1/library"

install.packages()로 패키지를 설치하면 이 목록의 첫 번째 경로에 저장되고, library()로 패키지를 불러올 때도 이 목록을 순서대로 검색합니다. Windows에서는 보통 "C:/Users/사용자명/AppData/Local/R/win-library/4.6"처럼 사용자별 폴더가 첫 번째로 잡힙니다. 한 컴퓨터에 여러 R 버전을 함께 설치해 둔 경우, 프로젝트별로 패키지 버전이 꼬이지 않도록 라이브러리 경로를 분리해서 관리하는 목적으로도 활용됩니다.

Sys.which()

Sys.which(names)는 git, pandoc처럼 R 밖에 설치된 외부 프로그램의 실행 파일 경로를 운영체제의 PATH 환경변수에서 찾아 반환합니다. 찾지 못하면 빈 문자열을 반환합니다.

주요 인자

  • names : 경로를 찾을 실행 파일 이름(문자벡터). 확장자 없이 이름만 넣으면 됩니다.
Sys.which(c("python3", "git", "pandoc"))
#>                                                             python3 
#> "C:\\Users\\사용자명\\AppData\\Local\\MICROS~1\\WINDOW~1\\python3.exe" 
#>                                                                 git 
#>                                   "C:\\PROGRA~1\\Git\\cmd\\git.exe" 
#>                                                              pandoc 
#>             "C:\\Users\\사용자명\\AppData\\Local\\Pandoc\\pandoc.exe"

Sys.which("nonexistent_prog_xyz")
#> nonexistent_prog_xyz 
#>                   "" 

R Markdown·Quarto 문서를 렌더링할 때 필요한 pandoc, 버전 관리를 위한 git, reticulate 패키지로 파이썬 코드를 함께 쓸 때 필요한 python처럼, 최근 R 작업 환경은 R 자체뿐 아니라 여러 외부 프로그램과 함께 구성되는 경우가 많습니다. 스크립트 맨 앞에서 Sys.which()로 필요한 프로그램이 실제로 설치되어 PATH에 잡혀 있는지 미리 점검해 두면, 나중에 원인을 알기 어려운 오류를 만나는 대신 "이 프로그램이 설치되어 있지 않습니다" 같은 명확한 안내를 미리 보여줄 수 있습니다.

참고로 외부 프로그램의 경로를 확인하는 데 그치지 않고 직접 실행까지 해야 한다면 base R의 system()·system2()를 사용할 수 있습니다. 다만 운영체제·셸(shell)에 따라 인자 처리 방식이 달라질 수 있어 사용에 주의가 필요하므로, 빠른 참고를 목표로 하는 이 매뉴얼에서는 별도로 다루지 않습니다.

15.2 세션 정보

코드가 아니라 "이 코드가 어떤 R 환경에서 실행되었는가" 자체를 기록하고 공유해야 하는 경우가 있습니다. 예컨대 논문이나 보고서의 재현성(reproducibility)을 위해 사용한 R·패키지 버전을 남겨야 하거나, 코드가 예상보다 느리게 실행될 때 정확히 어느 부분이 시간을 잡아먹는지 측정해야 하는 상황입니다.

협업자가 "제 컴퓨터에서는 결과가 다르게 나와요"라고 알려왔을 때, 가장 먼저 요청하게 되는 것이 바로 sessionInfo()의 출력입니다. 두 사람의 R 버전이나 패키지 버전이 다르면 똑같은 코드도 다른 결과를 낼 수 있기 때문입니다.

15.2절의 함수들은 R 세션 자체에 대한 정보를 조회하거나, 세션이 코드를 실행하는 데 걸리는 시간을 다룹니다.

함수 알려주는 정보
sessionInfo() R 버전, 운영체제, 로캘, 로드된 패키지 목록
Sys.info() 운영체제 종류, 컴퓨터 이름, 로그인 계정
options() / getOption() R 세션 전역 설정값(출력 자릿수, 경고 처리 방식 등)
Sys.sleep() (정보 조회가 아니라) 세션 실행을 일정 시간 멈춤
system.time() 특정 코드의 실행에 걸린 시간

sessionInfo() / R.version

sessionInfo()는 현재 R 세션의 버전, 운영체제, 로캘, 부착된(attached) 패키지 목록 등 세션 전반의 정보를 한 번에 요약해서 보여주는 함수입니다. R.version은 함수가 아니라 R 자체의 버전 정보를 담은 리스트이며, R.version.string은 그 정보를 사람이 읽기 좋은 한 줄 문자열로 정리해 둔 것입니다.

주요 인자

  • package : 세션 정보에 특정 패키지의 인용(citation) 정보까지 함께 포함하고 싶을 때 그 패키지 이름을 문자벡터로 지정합니다. 생략하면(기본값 NULL) 현재 세션에 로드된 패키지 목록만 보여줍니다.
sessionInfo()
#> R version 4.6.1 (2026-06-24 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> Matrix products: default
#>   LAPACK version 3.12.1
#> 
#> locale:
#>  [1] LC_COLLATE=ko_KR.UTF-8  LC_CTYPE=ko_KR.UTF-8    LC_MONETARY=ko_KR.UTF-8
#>  [4] LC_NUMERIC=C            LC_TIME=ko_KR.UTF-8
#> 
#> time zone: Asia/Seoul
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#> [1] compiler_4.6.1 tools_4.6.1

패키지를 여럿 불러온 상태라면 other attached packages·loaded via a namespace 항목에 그 패키지들의 버전까지 함께 표시됩니다. 질문 게시판(Stack Overflow 등)에 R 관련 오류를 질문할 때 sessionInfo() 출력을 함께 첨부하는 것이 관례처럼 자리 잡은 것도 이 때문입니다.

버전 번호만 간단히 확인하고 싶다면 R.version.string이 더 간결합니다.

R.version.string
#> [1] "R version 4.6.1 (2026-06-24 ucrt)"

R.version$major   # 주(major) 버전
R.version$minor   # 부(minor) 버전
#> [1] "4"
#> [1] "6.1"

실전 활용: 세션 정보를 파일로 남기기. GitHub에 공개하는 프로젝트라면, 분석 스크립트를 실행할 때마다 sessionInfo() 결과를 텍스트 파일로 함께 저장해 두면 나중에 "이 결과는 어떤 환경에서 나온 것인가"를 추적하는 데 도움이 됩니다. capture.output()(14.3절 print()·cat()과 함께 참고)으로 콘솔 출력을 문자벡터로 붙잡은 뒤 writeLines()로 저장하면 됩니다.

writeLines(capture.output(sessionInfo()), "session_info.txt")

Sys.info() / .Platform

Sys.info()는 R이 실행되고 있는 운영체제와 사용자 계정에 대한 정보를 이름 붙은 문자형 벡터로 반환합니다. .Platform은 함수가 아니라 R이 빌드된 플랫폼 환경을 담은 리스트(상수)로, 운영체제별로 분기하는 코드를 짤 때 자주 참조합니다.

Sys.info()가 반환하는 주요 원소

  • sysname : 운영체제 종류("Windows", "Darwin"(macOS), "Linux" 등).
  • release, version : 운영체제 배포판·커널의 세부 버전 정보.
  • nodename : 컴퓨터 이름(호스트명).
  • machine : CPU 아키텍처("x86_64", "arm64" 등).
  • login, user, effective_user : 로그인 계정명과 R을 실질적으로 실행 중인 계정명.
Sys.info()
#>           sysname           release           version          nodename 
#>         "Windows"          "10 x64"     "build 26200"         "DESKTOP" 
#>           machine             login              user    effective_user 
#>          "x86-64"           "사용자"           "사용자"           "사용자" 
#>           udomain 
#>         "DESKTOP"

이름 붙은 벡터이므로 [ ]로 필요한 원소만 꺼낼 수 있습니다.

Sys.info()["sysname"]
#>  sysname 
#>  "Windows" 

.Platform에서 가장 자주 쓰이는 원소는 OS.type("unix" 또는 "windows")입니다. macOS와 Linux는 내부적으로 "unix"로 같이 묶인다는 점에 유의해야 합니다(둘을 구분하려면 Sys.info()["sysname"]의 "Darwin" 여부를 확인해야 합니다).

.Platform$OS.type
#> "windows"

if (.Platform$OS.type == "windows") {
  cat("Windows 환경입니다.\n")
} else {
  cat("Unix 계열(macOS/Linux) 환경입니다.\n")
}
#> Windows 환경입니다.

options() / getOption()

options(...)는 R 세션 전체에 영향을 주는 전역 옵션을 설정하거나 조회합니다. getOption(x, default = NULL)은 옵션 하나의 현재 값만 간단히 조회할 때 씁니다.

주요 인자

  • ...(options) : 이름 = 값 형태로 지정할 옵션들. 인자 없이 options()만 호출하면 현재 설정된 옵션 전체를 리스트로 반환합니다. 옵션 이름만 문자열로 넘기면 그 이름의 현재 값을 리스트로 반환합니다.
  • x(getOption) : 조회할 옵션 이름(문자열 하나).
  • default(getOption) : 그 옵션이 설정되어 있지 않을 때 대신 반환할 값(기본값 NULL).

자주 다루는 옵션으로는 숫자 출력 자릿수를 정하는 digits, 지수 표기와 일반 표기 중 무엇을 우선할지 정하는 scipen, 경고 메시지 처리 방식을 정하는 warn(0: 함수 실행이 끝난 뒤 모아서 출력(기본값), 1: 경고가 발생하는 즉시 출력, 2: 경고를 오류로 승격시켜 즉시 중단) 등이 있습니다.

getOption("digits")
#> [1] 7

old <- options(digits = 3)
pi
#> [1] 3.14
options(old)   # 원래 설정으로 복원
pi
#> [1] 3.141593
print(100000000)
#> [1] 1e+08

old <- options(scipen = 100)   # 지수 표기 대신 일반 표기를 강하게 선호
print(100000000)
#> [1] 100000000
options(old)

options()로 설정을 바꾸는 코드는 그 값이 세션 전체(또는 함수 밖)에까지 영향을 준다는 점을 기억해야 합니다. 사용자 정의 함수 안에서 잠깐 옵션을 바꿔야 한다면, 위 예제처럼 기존 값을 old에 저장해 두었다가 되돌리거나, on.exit(options(old))(17장 참고)로 함수가 끝날 때 자동으로 복원하도록 짜는 것이 안전합니다.

주의: 예전 R 코드나 문서에서 options(stringsAsFactors = FALSE)라는 구문을 자주 보게 됩니다. R 3.x까지는 data.frame()·read.table()이 문자열 열을 기본적으로 팩터(factor)로 자동 변환했고, 이 동작을 끄기 위해 이 옵션을 관례적으로 지정했습니다. R 4.0.0부터는 이 기본값 자체가 FALSE로 바뀌었고, 이 옵션은 더 이상 data.frame()·read.table()의 동작에 영향을 주지 않습니다. 최신 R에서는 신경 쓰지 않아도 되는 옵션입니다.

getOption("stringsAsFactors")
#> NULL

Sys.sleep()

Sys.sleep(time)은 R 세션의 실행을 지정한 시간만큼 멈춥니다.

주요 인자

  • time : 멈출 시간(초 단위, 소수점 지정 가능).

데이터 계산 자체와는 관계없어 보이지만, 외부 웹사이트나 API에 반복적으로 요청을 보내는 코드(예: 여러 페이지를 순회하며 데이터를 수집하는 웹 스크레이핑)를 짤 때 요청 사이에 Sys.sleep()으로 짧은 지연을 두는 것이 실무에서 매우 흔하게 쓰입니다. 서버에 짧은 시간 안에 너무 많은 요청을 보내면 접속이 차단될 수 있는데, 이를 예방하는 가장 간단한 방법이기 때문입니다.

t0 <- Sys.time()
Sys.sleep(1)
Sys.time() - t0
#> Time difference of 1.001185 secs

system.time()

system.time(expr, gcFirst = TRUE)는 표현식 expr을 실제로 실행하면서 그 실행에 걸린 시간을 측정합니다.

주요 인자

  • expr : 실행 시간을 측정할 코드(표현식).
  • gcFirst : TRUE(기본값)이면 측정을 시작하기 전에 가비지 컬렉션(gc())을 먼저 실행해, 이전에 실행된 코드가 남긴 메모리 정리 작업이 이번 측정 시간에 섞여 들어가는 것을 줄입니다.

반환값은 user(R과 그 하위 연산이 실제 계산에 사용한 CPU 시간), system(운영체제에 파일 입출력 등을 요청하는 데 사용한 CPU 시간), elapsed(측정을 시작해서 끝날 때까지 실제로 체감한 총 시간)로 이루어진 벡터입니다. 보통 코드가 얼마나 "느리게 느껴지는가"를 볼 때는 elapsed 값을 확인합니다.

8장 서두에서 살펴본 것처럼, R에서는 for() 반복문보다 벡터화된 코드가 더 관용적이면서도 더 빠릅니다. system.time()으로 이 차이를 직접 확인할 수 있습니다.

f_loop <- function(n) {
  s <- 0
  for (i in 1:n) s <- s + sqrt(i)
  s
}
f_vec <- function(n) sum(sqrt(1:n))

system.time(f_loop(2000000))
#>   사용자   시스템 elapsed
#>    0.02    0.02    0.05

system.time(f_vec(2000000))
#>  사용자  시스템 elapsed 
#>   0.01   0.00    0.01

같은 계산인데도 원소 하나씩 반복하는 f_loop()보다 한 번에 벡터 단위로 계산하는 f_vec()가 눈에 띄게 빠른 것을 확인할 수 있습니다.

참고로 system.time()은 코드 한 번을 실행한 시간만 측정하므로, 매번 실행 시간이 조금씩 흔들리는 짧은 코드를 여러 번 반복 실행해 통계적으로 비교하려면 base R의 범위를 벗어나는 microbenchmark나 bench 같은 패키지가 흔히 쓰입니다(이 매뉴얼이 다루는 Base R 범위 밖입니다).