논문 분석 코드가 다른 컴퓨터에서 안 돌아갈 때: renv·Conda·Docker로 재현 환경 남기는 법

서로 다른 컴퓨터 세 대 사이에 R 패키지 잠금 파일, Conda 환경 명세, 컨테이너 상자가 층별로 연결된 연구 코드 재현 환경 구성도

논문 분석을 마치고 코드와 데이터를 공동연구자에게 보냈는데, 상대방 컴퓨터에서는 패키지가 설치되지 않거나 같은 함수가 다른 결과를 내는 일이 있다. 심사자가 저장소를 내려받았지만 절대 경로 오류로 첫 스크립트부터 멈추기도 하고, R 패키지가 요구하는 시스템 라이브러리가 없어 설치 단계에서 실패하기도 한다. 이때 단순히 현재 설치된 패키지 목록을 복사하는 것만으로는 부족하다.

핵심 결론은 보존해야 할 환경의 층에 따라 도구를 선택해야 한다는 것이다. R 패키지와 설치 출처를 남기려면 renv, Python과 명령행 도구를 함께 관리하려면 Conda가 기본 선택이다. 운영체제 패키지, 컴파일러, R·Python 실행기와 실행 플랫폼까지 맞춰야 한다면 Docker를 결합한다. 어떤 파일을 만들었는가보다 더 중요한 기준은 새 컴퓨터나 CI에서 설치부터 결과 파일 생성까지 실제로 다시 수행되는가이다.

먼저 오류를 환경 문제와 코드 문제로 나눈다

재현 환경을 만들기 전에 실패 지점을 분류해야 한다. 잠금 파일은 패키지 이름·버전·출처처럼 해결된 의존성 상태를 기록하는 파일이지만, 데이터 누락이나 만료된 API 인증 정보를 고쳐 주지는 않는다. 다음 순서로 최초 오류를 확인하면 불필요하게 Docker부터 만드는 일을 줄일 수 있다.

  1. 패키지 누락 또는 버전 충돌: 패키지를 찾을 수 없다는 메시지, 함수 인자 변경, 바이너리 호환성 오류가 나타나는지 본다.
  2. 시스템 라이브러리와 컴파일 도구: 헤더 파일, C·C++·Fortran 컴파일러, libcurl·libxml2·GDAL 같은 외부 라이브러리 누락인지 확인한다.
  3. 실행기와 플랫폼: R·Python 버전, Windows·macOS·Linux 차이, x86-64와 ARM64 차이를 기록한다.
  4. 파일과 실행 순서: 개인 사용자명이 들어간 절대 경로, 작업 디렉터리 가정, 대소문자 차이, 먼저 생성되어야 하는 중간 파일을 점검한다.
  5. 외부 서비스: API, 데이터베이스, 클라우드 저장소, 비공개 저장소의 URL·권한·토큰 만료 여부를 확인한다.
  6. 코드 자체: 입력 형식 변경, 난수 시드 누락, 수동 조작 단계, 메모리 부족처럼 환경 파일만으로 해결되지 않는 원인을 분리한다.

공개된 R 프로젝트의 실행 실패를 조사한 연구에서도 선언되지 않은 의존성, 잘못된 파일 경로, 시스템 수준 문제가 주요 장벽으로 분류됐다. 이 결과는 컨테이너가 모든 오류를 해결한다는 뜻이 아니라, 먼저 의존성과 경로를 명시해야 컨테이너도 정상적으로 만들어진다는 점을 보여 준다. 연구 범위와 결과는 Computational Reproducibility of R Code Supplements on OSF에서 확인할 수 있다.

renv·Conda·Docker가 보존하는 층은 서로 다르다

도구 주로 보존하는 요소 별도로 기록할 요소 적합한 상황
renv R 패키지 버전, 저장소와 설치 출처, 프로젝트별 R 라이브러리 실제 R 설치, 운영체제 패키지, 컴파일러, 외부 프로그램 R 중심 통계 분석과 문서 생성
Conda Python·R 실행기, Conda 패키지, 일부 비언어 도구와 라이브러리 명세 형식에 따라 운영체제별 해결 결과, pip·외부 프로그램, 인증 정보 Python 또는 R·Python·명령행 도구가 섞인 분석
Docker 베이스 이미지 위의 운영체제 사용자 공간, 시스템 패키지, 실행기와 언어 패키지 호스트 커널, CPU·가속기 조건, 외부 데이터·비밀정보, 빌드 시점의 가변 자원 운영체제 의존 설치와 배포 환경까지 맞춰야 하는 프로젝트

renv의 공식 문서는 renv가 해결하는 범위를 주로 R 패키지로 한정한다. renv.lock에는 R 버전도 기록되지만 해당 R 버전을 설치해 주지는 않으며, 운영체제·시스템 라이브러리·컴파일러 보존은 별도 문제라고 설명한다. 자세한 범위는 renv 소개와 주의사항에서 확인할 수 있다.

Docker도 완전한 가상 컴퓨터와 같지는 않다. 컨테이너는 필요한 파일과 사용자 공간을 격리하지만 여러 컨테이너가 호스트 커널을 공유한다. CPU 명령어, GPU 드라이버, 커널 기능에 민감한 분석이라면 이미지가 같아도 목표 장비에서 확인해야 한다. Docker의 컨테이너 구조는 Docker 공식 컨테이너 설명을 참고할 수 있다.

프로젝트 유형에 따른 선택 기준

  • R만 사용하고 CRAN·Bioconductor·Git 저장소 패키지가 중심: 먼저 renv를 적용한다. 시스템 라이브러리 설치가 단순하고 공동연구자의 운영체제가 비슷하다면 renv.lock과 README만으로도 관리 가능한 경우가 많다.
  • Python과 명령행 분석 도구를 함께 사용: Conda 환경 명세를 기본으로 한다. Python 버전, BLAS 구현, 생물정보학 프로그램처럼 Conda 채널에서 함께 해결되는 구성요소를 한 환경으로 관리하기 쉽다.
  • R과 Python을 한 파이프라인에서 사용: 실행기와 공통 시스템 도구는 Conda 또는 Docker에 두고, R 패키지의 세부 출처는 renv로 관리하는 결합 방식을 검토한다. 두 관리자가 같은 R 패키지를 중복 통제하지 않도록 책임 범위를 README에 적는다.
  • 운영체제 패키지 설치가 복잡하거나 심사 환경을 통일해야 함: Dockerfile을 추가한다. 다만 Docker를 쓸 수 없는 HPC에서는 기관이 허용하는 Apptainer 등의 런타임을 별도로 확인해야 한다.

R 프로젝트는 renv.lock을 만든 뒤 빈 라이브러리에서 복원한다

renv 1.2.4 공식 문서를 2026년 9월 16일 확인한 기준으로, 기본 작업은 프로젝트 초기화, 상태 확인, 스냅샷, 복원 순서다. snapshot()은 현재 프로젝트 라이브러리의 패키지 상태를 renv.lock에 기록하고, restore()는 그 기록을 이용해 프로젝트 라이브러리를 복구한다. 잠금 파일에는 renv와 R의 버전, 활성 저장소, 패키지 버전과 설치 출처가 포함된다. 세부 구조는 renv 잠금 파일 문서와 snapshot 공식 참조에서 확인할 수 있다.

install.packages('renv')
renv::init()
renv::status()
renv::snapshot()

저장소에는 적어도 renv.lock, .Rprofile, renv/activate.R, renv/settings.json을 포함한다. 개인 컴퓨터에서 생성된 renv/library 전체를 복사하는 방식은 운영체제와 로컬 경로에 묶일 수 있으므로 복원 가능한 메타데이터를 공유하는 편이 낫다.

그다음 원래 프로젝트와 분리된 새 디렉터리에 저장소를 다시 내려받고, 필요한 R 버전을 설치한 뒤 다음과 같이 실행한다. 캐시 덕분에 설치가 성공한 것인지 확인하려면 빈 캐시나 새 CI 실행기도 이용한다.

R -s -e 'renv::restore()'
Rscript analysis/run_all.R

restore()가 성공해도 분석 전체가 재현됐다고 판단해서는 안 된다. 최종 표·그림·모델 파일이 지정한 위치에 생성되는지, 기준 결과와 비교 가능한지까지 확인해야 한다. 정확한 저장소만 허용하도록 엄격하게 복원할 수도 있지만, 기록된 저장소가 사라지면 대체 저장소로 넘어가지 않고 실패할 수 있다. 관련 옵션은 renv restore 공식 참조에 설명돼 있다.

Conda는 공유용 명세와 정확 복원용 명세를 구분한다

2026년 9월 16일 확인한 Conda 안정 문서는 26.7.2이며, 현재 conda export는 환경 YAML·JSON, explicit, requirements 형식을 제공한다. 설치된 플러그인에 따라 추가 형식이 나타날 수 있으므로, 다른 연구자에게 명령을 안내할 때는 Conda 버전과 사용한 내보내기 형식을 함께 적어야 한다. 현재 명령과 형식은 conda export 공식 문서에서 확인할 수 있다.

다른 운영체제에 전달할 공유본

conda export --from-history --format=environment-yaml --file=environment.yml

--from-history는 사용자가 명시적으로 설치한 패키지만 내보내 플랫폼별 하위 의존성을 제외한다. 따라서 Windows·macOS·Linux에서 다시 해결할 가능성을 높이지만, 새 컴퓨터에서 솔버가 당시와 다른 하위 버전을 선택할 수 있으므로 정확한 복제본은 아니다. pip로 추가한 패키지가 있다면 별도 requirements 파일이나 environment.yml의 pip 구역에 빠짐없이 기록됐는지 확인한다. Conda와 pip를 섞을 때는 Conda 패키지를 먼저 설치하고 남은 항목을 pip로 설치하라는 공식 권고도 Conda 환경 관리 문서에 제시돼 있다.

같은 플랫폼을 정확히 복원할 명세

conda export --format=explicit --file=explicit-linux-64.txt
conda create --name paper-repro --file explicit-linux-64.txt

explicit 파일은 전체 패키지 URL과 빌드가 포함된 동일 플랫폼용 명세다. macOS ARM64에서 만든 파일을 Linux x86-64에서 그대로 사용하는 용도가 아니므로 파일명과 README에 osx-arm64, linux-64 같은 대상 플랫폼을 적는다.

여러 플랫폼의 해결 결과를 함께 고정할 때

다중 플랫폼 잠금 파일이 필요하면 별도 잠금 파일 플러그인이나 conda-lock을 검토한다. 현재 conda-lockfiles는 Conda의 base 환경에 설치하는 플러그인이며, conda-lock·pixi 형식 지원과 대상 플랫폼별 내보내기를 제공한다. 플러그인 설치 조건과 형식별 별칭은 conda-lockfiles 공식 문서에서 확인해야 한다. 협업 저장소에는 사람이 수정하는 공유용 environment.yml과 기계가 생성한 플랫폼별 잠금 파일을 함께 두고, 잠금 파일을 수동 편집하지 않는 구성이 명확하다.

Docker가 필요한 시점과 베이스 이미지 고정법

R 또는 Conda 복원이 시스템 라이브러리 설치에서 계속 실패하거나, 심사자가 동일한 Linux 사용자 공간에서 명령 하나로 실행해야 한다면 Dockerfile을 추가한다. R 프로젝트의 경우 renv 메타데이터를 먼저 복사해 패키지를 복원한 뒤 분석 코드를 복사하는 구조를 사용할 수 있다. 필요한 libcurl·libxml2 등의 시스템 패키지는 renv::restore()보다 먼저 설치해야 한다는 설명과 예시는 renv와 Docker 공식 안내에 제시돼 있다.

FROM <base-image>@sha256:<actual-digest>
WORKDIR /project
RUN apt-get update && apt-get install -y --no-install-recommends \
    <required-system-packages> \
    && rm -rf /var/lib/apt/lists/*
COPY renv.lock .Rprofile ./
COPY renv/activate.R renv/settings.json ./renv/
RUN R -s -e 'renv::restore()'
COPY . .
CMD ["Rscript", "analysis/run_all.R"]

ubuntu:24.04처럼 버전 태그를 붙여도 게시자가 같은 태그가 가리키는 이미지를 갱신할 수 있다. Docker 공식 문서는 태그가 변경 가능하므로 동일한 이미지를 보장하려면 digest를 함께 고정하라고 설명한다. 그러나 digest를 고정하면 보안 수정도 자동 반영되지 않으므로, 논문 결과를 생성한 digest를 보존하면서 별도 일정으로 업데이트 이미지를 만들고 재검증하는 편이 안전하다. 이 상충 관계는 Docker 빌드 모범 사례에서 확인할 수 있다.

Dockerfile만 보존하고 실제 이미지를 보관하지 않으면 apt 저장소나 외부 다운로드 URL이 사라져 미래의 빌드가 실패할 수 있다. 장기 보존이 중요하다면 Dockerfile, 이미지 digest, 빌드 로그, 사용한 이미지의 등록 위치와 논문 시점 태그를 함께 기록한다. 비공개 이미지라면 접근 권한과 보존 기간도 확인해야 한다.

잠금 파일이 있어도 복원이 실패하는 조건

  • 패키지 저장소나 특정 바이너리·소스 아카이브가 삭제됐다.
  • 로컬 폴더에서 설치한 패키지가 잠금 파일에는 기록됐지만 원본 소스가 공유되지 않았다.
  • 비공개 Git 저장소, 사설 Conda 채널, 컨테이너 레지스트리에 접근할 인증 방식이 없다.
  • R·Python 버전은 기록했지만 설치 방법과 대상 CPU 아키텍처가 다르다.
  • 패키지 설치에 필요한 운영체제 헤더, 컴파일러, Java, CUDA와 드라이버 조건을 남기지 않았다.
  • 분석 코드가 개인 홈 디렉터리, 외장 디스크, 대소문자가 다른 파일명에 의존한다.
  • API와 웹 데이터가 갱신됐거나 호출 한도·인증 토큰·네트워크 정책이 달라졌다.
  • 병렬 계산, 난수, 하드웨어별 수치 라이브러리 차이로 결과가 비트 단위로 같지 않다.

비밀정보는 잠금 파일이나 Docker 이미지에 넣지 않는다. README에는 필요한 환경변수 이름과 발급 절차만 기록하고, 실제 토큰은 CI 비밀 저장소나 기관의 자격증명 관리 체계에서 주입한다. 원자료가 갱신될 수 있다면 데이터 파일의 영구 식별자, 버전, 체크섬과 접근일도 계산 환경과 별도로 보존한다.

제출 전에는 설치가 아니라 결과 생성까지 시험한다

  1. 프로젝트를 새 임시 디렉터리 또는 새 가상머신·CI 실행기에 복제한다.
  2. README만 보고 필요한 R, Conda, Docker 버전과 실행 명령을 찾을 수 있는지 확인한다.
  3. 캐시와 기존 사용자 라이브러리에 의존하지 않은 상태에서 환경을 복원한다.
  4. 하나의 진입 명령으로 전처리부터 최종 표·그림 생성까지 실행한다.
  5. 기대 출력 파일의 존재 여부, 행 수·해시·허용 오차 등 프로젝트에 적합한 검증 조건을 자동 확인한다.
  6. 소요 시간, CPU·메모리·GPU 요구량, 생략 가능한 장시간 단계를 README에 기록한다.
  7. 실패하면 전체 화면 캡처보다 명령, 종료 코드, 첫 원인 오류, 운영체제·아키텍처, 패키지 관리자 버전이 포함된 로그를 남긴다.

독립 실행을 점검하는 CODECHECK의 저자 안내도 README, 필요한 데이터와 코드, 실행 결과 목록, 라이선스를 최소 구성으로 제시한다. 투고 규정 자체는 학술지와 학회마다 다르지만, 제3자가 문서만 보고 워크플로를 실행하고 성공 여부를 판단할 수 있어야 한다는 기준은 재현 패키지 구성에 유용하다. 구체적인 항목은 CODECHECK 저자 가이드에서 확인할 수 있다.

재현 패키지의 최소 구성

  • 논문에 사용한 코드의 고정 릴리스 또는 커밋 식별자
  • 상대 경로로 정리한 코드·데이터·출력 디렉터리
  • 입력 데이터의 출처, 버전, 체크섬, 접근 제한 설명
  • renv.lock, 공유용 environment.yml, 플랫폼별 explicit 또는 잠금 파일 중 필요한 항목
  • 필요한 경우 digest를 고정한 Dockerfile과 이미지 위치
  • 설치, 실행, 예상 소요 시간과 결과 위치를 적은 README
  • run_all.R, 셸 스크립트, Makefile 등 하나의 실행 진입점
  • 기대 출력과 허용 오차를 확인하는 검증 스크립트
  • 코드·데이터 라이선스와 비공개 자원 접근 절차
  • 깨끗한 환경의 성공 로그, 확인 날짜, 운영체제와 CPU 아키텍처

최종 판단

패키지 버전 충돌만 문제인 R 프로젝트라면 renv부터 적용하고, Python 실행기와 여러 분석 도구가 섞였다면 Conda의 공유용 명세와 정확 복원용 명세를 분리한다. 시스템 라이브러리와 실행 플랫폼이 결과에 영향을 주거나 심사 환경을 통일해야 할 때 Docker를 추가한다. 복잡한 프로젝트에서는 하나만 선택하기보다 Docker가 운영체제와 실행기를, renv 또는 Conda가 언어 패키지를 담당하도록 층을 나누는 편이 관리하기 쉽다.

최종 제출 기준은 잠금 파일의 존재가 아니다. 인터넷에서 새로 받은 저장소가 문서에 적힌 명령만으로 환경을 만들고, 입력 데이터에서 논문의 핵심 결과 파일을 생성하며, 실패할 경우 원인을 추적할 로그를 남기는지가 판단 기준이다.

검증이 더 필요한 부분

  • 투고 대상 학술지·학회가 요구하는 코드, 데이터, 컨테이너 이미지 제출 형식과 영구 식별자 조건
  • 공동연구자와 심사자가 사용할 운영체제·CPU·GPU에서의 실제 복원 성공 여부
  • 기관 HPC가 Docker를 허용하는지, Apptainer 등 대체 런타임을 요구하는지 여부
  • 사용 중인 Conda 설치에서 지원되는 export 형식과 conda-lockfiles 플러그인 설치 상태
  • 비공개 패키지·사설 채널·컨테이너 레지스트리의 접근 권한, 라이선스와 보존 기간
  • Dockerfile에 기록할 실제 베이스 이미지 digest와 논문 제출 시점의 보안 업데이트 상태

출처 및 확인일

renv, Conda, Docker와 CODECHECK 공식 문서는 2026년 9월 16일 확인했다. Conda 명령과 플러그인 지원 범위, Docker 이미지 태그와 digest, 학술지 제출 규정은 이후 변경될 수 있으므로 실제 제출 직전에 다시 확인해야 한다.

함께 읽을 글