분석 환경, 어떻게 만들까요? conda·컨테이너·서버 작업의 기본
목차
📌 이 글에서 알 수 있는 것
- 같은 코드가 다른 결과를 내는 이유와 환경 기록법
- conda·mamba 채널 설정, 환경 만들기, environment.yml로 재생성
- Docker와 Apptainer(옛 Singularity)로 BioContainers 이미지 쓰기
- ssh·rsync·tmux로 서버 작업하기, Slurm 잡 제출과 흔한 실수
🧩 같은 코드, 다른 결과
도구·패키지 버전과 그것이 기대는 라이브러리(의존성)까지 합친 환경이 바뀌면 같은 명령도 다른 숫자를 내거나 돌지 않습니다.
2024년 연구는 PubMed Central 논문 3,467편에 딸린 Jupyter 노트북(코드와 결과를 담은 문서)을 자동으로 다시 돌렸습니다. 의존성 파일이 있는 Python 노트북 15,817개 중 패키지 설치까지 성공한 것은 10,388개, 오류 없이 끝난 것은 1,203개, 원래와 같은 결과는 879개였습니다. 전체의 41.65%(6,588개)는 모듈을 찾거나 불러오지 못해 멈췄고, 주원인은 의존성 누락이었습니다1. 환경은 만들 때부터 기록해야 합니다.
🐍 conda·mamba: 도구마다 작은 환경
conda는 패키지·환경 관리자이고, mamba는 대부분 같은 인자를 쓰는 대체 클라이언트입니다2. 최신 conda도 같은 libmamba 솔버(의존성 풀이 엔진)를 써서 mamba를 따로 깔 필요가 줄었습니다3. mamba 문서는 설치판으로 conda-forge가 기본 채널인 Miniforge를 권합니다43.
채널 설정(한 번만)
conda config --add channels bioconda
conda config --add channels conda-forge
conda config --set channel_priority strict
- 채널은 패키지 저장소입니다. bioconda(생물정보 도구)가 conda-forge(일반 패키지)에 크게 기대므로 conda-forge를 최우선에 둡니다. 나중에 추가한 채널이 위로 가니 이 순서대로 입력합니다5.
channel_priority strict: 높은 채널에 같은 이름의 패키지가 있으면 낮은 채널의 것은 후보에서 뺍니다. 섞여 깨지는 오류를 줄이지만 일부 조합은 풀리지 않을 수 있습니다6.- bioconda는 2024년 8월 권장 채널에서 defaults를 뺐습니다5. defaults(Anaconda 저장소)는 약관 수락이 필요하고, 직원·계약자 200명 초과 영리 조직은 유료 대상입니다(2025-07-15 약관)7.
- 자주 하는 실수: 순서를 거꾸로 넣거나 defaults를 남기는 것.
conda config --remove channels defaults로 빼고--show channels로 확인합니다.
환경 만들기와 버전 고정
conda create -n align -c conda-forge -c bioconda --strict-channel-priority \
samtools=1.25 bwa=0.7.19 fastp=1.4.0
conda activate align
-n align: 환경 이름. 프로젝트·단계별로 나누고 기본 환경(base)은 작게 둡니다. 환경이 작을수록 풀이가 빠릅니다3.-c: 이번에 쓸 채널. 명령줄에서는 앞에 쓴 채널이 우선입니다(conda config와 반대)5.samtools=1.25: 버전 고정. 빼면 그날 최신판이 깔립니다.- 나중에
conda install로 더하면 깔린 패키지가 바뀔 수 있어, 처음에 한 번에 넣습니다3. - 자주 하는 실수: base에 모든 도구를 깔아, 업데이트 한 번에 여러 도구가 함께 흔들리는 것.
기록하고 다시 만들기
conda env export -n align --no-builds > environment.yml
conda create -n align --file environment.yml # 같은 OS의 다른 서버에서
--no-builds: 빌드 번호(같은 버전의 재빌드 표시)를 빼고 버전만 남깁니다. bioconda는 빌드 번호를 넣으면 재생성이 오히려 막힐 수 있어 이 옵션을 권합니다3.--from-history는 직접 설치한 패키지만 남겨 운영체제가 달라도 만들기 쉽습니다. 대신 하위 의존성 버전은 기록되지 않습니다8.- conda 문서는 이제
conda create --file을 권합니다. YAML은 conda 26.3부터 읽으니, 그 전 버전(conda --version)에서는conda env create -f environment.yml을 씁니다89. - 자주 하는 실수: 분석이 끝난 뒤에야 내보내는 것. 바꿀 때마다 내보내 코드와 함께 둡니다.
bioconda는 Linux·macOS만 지원해, Windows에서는 WSL(Windows용 Linux 환경)이나 서버를 씁니다.
📦 컨테이너: Docker와 Apptainer
컨테이너는 도구와 운영체제 라이브러리까지 한 이미지로 묶습니다. bioconda 레시피가 병합되면 같은 도구의 Docker 이미지가 자동으로 만들어져 quay.io의 BioContainers 저장소에 올라갑니다10. 태그는 버전--빌드 형식(예: 1.25--h9dcdb79_0)이고 latest 태그는 없습니다11.
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD":/data -w /data \
quay.io/biocontainers/samtools:1.25--h9dcdb79_0 \
samtools flagstat sample.bam
--rm: 끝나면 컨테이너를 지웁니다12.-u: 내 사용자로 실행해 결과가 root 소유가 되지 않게 합니다12.-v "$PWD":/data: 현재 폴더를 컨테이너의 /data에 연결(bind mount)하고,-w로 그곳을 작업 폴더로 씁니다. 기본은 쓰기 가능이라 원본만 읽을 때는:ro를 붙입니다13.- 자주 하는 실수: 마운트 없이 실행해 입력을 못 찾거나, 결과를 컨테이너 안에 써서 잃는 것.
공용 HPC(여러 사용자가 함께 쓰는 고성능 계산 서버)에서는 흔히 Apptainer를 씁니다. Singularity 프로젝트가 2021년 11월 Linux Foundation으로 옮기며 바뀐 이름입니다14. 컨테이너 안에서도 같은 사용자로 실행되고 기본적으로 추가 권한을 얻지 못하며, 이미지가 SIF(Singularity Image Format) 파일 하나라 옮기기 쉽습니다15.
apptainer pull samtools_1.25.sif \
docker://quay.io/biocontainers/samtools:1.25--h9dcdb79_0
apptainer exec samtools_1.25.sif samtools flagstat sample.bam
pull: Docker 이미지를 받아 SIF 파일로 변환합니다16. 홈 용량이 작으면 캐시를APPTAINER_CACHEDIR·condapkgs_dirs로 옮깁니다.exec: 이미지 안의 프로그램 하나를 실행합니다. 홈과 현재 폴더, /tmp는 기본으로 연결되고, 다른 경로는--bind /data:/data:ro처럼 붙입니다17.- 자주 하는 실수: 홈 밖의 프로젝트·스크래치 경로를 bind하지 않아 파일이 없다고 나오는 것.
🔐 원격 작업: ssh·rsync·tmux
ssh-keygen -t ed25519
ssh-copy-id user@server
ssh user@server
ssh-keygen -t ed25519: 개인 키와 공개 키 한 쌍을 만듭니다. ed25519는 OpenSSH의 기본 키 유형입니다18. 암호문(passphrase)을 걸어 두세요.ssh-copy-id: 공개 키를 서버에 등록해 이후 비밀번호 없이 접속합니다. 기관 등록 방식이 있으면 따릅니다.- 자주 하는 실수: 개인 키(
id_ed25519)를 메일·메신저·AI 채팅에 붙여 넣는 것. 서버 비밀번호도 마찬가지입니다.
rsync -avP raw/ user@server:/project/raw/
-a: 권한·시간을 보존하는 보관 모드(-rlptgoD).-P:--partial --progress로 끊긴 파일을 남겨 이어받고 진행률을 보여 줍니다19.- 원본 끝
/는 “폴더 안 내용"을, 없으면 “폴더째” 복사합니다19.-n(dry run)으로 먼저 확인하세요. - 자주 하는 실수: 끝 슬래시를 잘못 써서 raw/raw/처럼 폴더가 한 겹 더 생기는 것.
tmux new -s align
tmux ls
tmux attach -t align
new -s align: 이름 붙인 세션을 만듭니다.Ctrl-b다음d로 세션을 남긴 채 빠져나옵니다20.ls,attach -t: 세션 목록을 보고 다시 붙습니다. 접속이 끊겨도 세션 안 작업은 계속됩니다.- 자주 하는 실수: 로그인 노드(접속해 처음 닿는 공용 노드)의 tmux에서 몇 시간짜리 정렬을 돌리는 것. 긴 계산은 잡으로 냅니다.
nohup bash run.sh > run.log 2>&1 &
nohup: 접속 종료 신호(SIGHUP)를 무시하고 명령을 계속 실행합니다. 출력을 지정하지 않으면 nohup.out에 쌓입니다21.> run.log 2>&1 &: 표준 출력과 오류를 한 로그로 모으고 뒤에서 실행합니다.- 자주 하는 실수:
&만 써서 접속 종료 때 함께 끝날 수 있는 것. 공용 서버의 긴 계산은 sbatch로 냅니다.
🗂️ Slurm: 잡으로 내기
Slurm은 여러 사용자의 계산 요청을 받아 노드에 배정하는 잡 스케줄러입니다.
#!/bin/bash
#SBATCH --job-name=align
#SBATCH --cpus-per-task=8
#SBATCH --mem=32G
#SBATCH --time=12:00:00
#SBATCH --output=%x_%j.log
set -eo pipefail
eval "$(conda shell.bash hook)" # 배치 스크립트에서 conda activate를 쓰기 위한 초기화
conda activate align
bwa mem -t $((SLURM_CPUS_PER_TASK - 2)) -R '@RG\tID:s1\tSM:sample' \
ref.fa sample_R1.fastq.gz sample_R2.fastq.gz \
| samtools sort -@ 2 -o sample.bam
#SBATCH줄은 스크립트 맨 위에 모읍니다. 주석이 아닌 첫 명령 뒤의#SBATCH는 무시됩니다22.set -eo pipefail: 파이프 중간 명령이 실패하면 잡도 실패로 끝냅니다.--cpus-per-task=8: 작업 하나에 쓸 CPU 수. bwa 6개와 sort 추가 2개(-@ 2)로 요청 수에 맞춥니다.-R은 GATK가 요구하는 read group(7편).--mem=32G: 노드당 메모리. 단위를 빼면 MiB(메비바이트)로 읽힙니다22.--time=12:00:00: 최대 실행 시간. 도달하면 종료 신호(SIGTERM)에 이어 강제 종료(SIGKILL)로 끝납니다22.--output=%x_%j.log: 잡 이름(%x)과 번호(%j)로 로그 파일을 만듭니다22. 파티션·계정 옵션은 기관 지침을 따릅니다.
sbatch align.sh
squeue -u $USER
scancel 123456
sacct -j 123456 --format=JobID,State,Elapsed,MaxRSS,ReqMem
squeue -u: 내 잡의 상태(대기 PD, 실행 R)를 봅니다23.scancel: 잡 번호로 취소합니다24.sacct: 끝난 잡의 상태와 실제 사용량을 봅니다. State가 OUT_OF_MEMORY면 메모리, TIMEOUT이면 시간이 부족했던 것입니다(회계 기능이 켜진 서버)25.- 자주 하는 실수: 과하게 요청해 오래 대기하는 것. sacct의 MaxRSS(최대 실제 메모리,
.batch줄에 표시)로 다음 요청을 조정합니다.
🔑 체크섬: 옮긴 파일이 같은지
sha256sum sample_R1.fastq.gz sample_R2.fastq.gz > checksums.sha256
sha256sum -c checksums.sha256
- 보내는 쪽에서 파일별 지문(해시)을 만들고 받는 쪽에서
-c로 대조합니다. 일치하면 OK, 다르면 FAILED입니다26. md5sum은 업체·공개 데이터가 준 MD5 값과 대조할 때 씁니다(보안 목적에는 SHA-2 권장)26. 오래된 macOS에서는shasum -a 256 -c를 씁니다.- 자주 하는 실수: 전송 “완료"만 보고 넘어가는 것. 크기가 같아도 내용은 다를 수 있습니다.
⚠️ 한계와 주의
- 환경 파일도 완벽하지 않습니다. 오래된 패키지가 채널에서 빠지거나 운영체제가 바뀌면 다시 풀리지 않을 수 있어, 오래 보관할 분석은 이미지(SIF)도 남깁니다.
- 재현성 연구의 범위: 앞의 수치는 공개 Python 노트북을 자동 재실행한 결과라, 다른 언어나 사람이 손본 재실행에 그대로 옮길 수 없습니다1.
🏛️ 지금 어디까지 왔나
- 버전(2026-11-06 확인): conda 26.9.4, mamba 2.10.0, Miniforge 26.9.4-2, Apptainer 1.5.5, Slurm 26.05 문서, rsync 3.5.2, tmux 3.8, Docker Engine 29.9.3.
- 흐름: 환경·컨테이너를 묶어 실행하는 워크플로 관리자(Nextflow·Snakemake)는 9편에서 다룹니다.
- 한국: KISTI 국가슈퍼컴퓨팅센터의 뉴론 시스템은 Slurm을 쓰고, 지침서에 Conda·Singularity 부록이 있습니다27. 서버에 따라
singularity명령을 씁니다.
🧪 연구자 노트
- 내 분석은 프로젝트마다 conda 환경을 따로 만들어 씁니다. 다른 사람에게 넘기거나 논문에 쓸 분석은 컨테이너로 고정하는 편이 안전합니다.
environment.yml은 분석을 시작할 때 바로 남기세요. 나중에 기억에 의존해 버전을 되살리기는 어렵습니다.
🙋 그래서 나에게는? — 실습 전 체크리스트
- 채널을 conda-forge·bioconda, strict로 설정했고 defaults 사용 여부를 기관 정책과 맞췄다
- 프로젝트별 환경에 버전을 고정해 설치했고, base에는 설치하지 않았다
- environment.yml과
버전--빌드이미지 태그를 코드와 함께 보관한다 - ssh 키에 암호문을 걸었고, 개인 키·비밀번호를 어디에도 붙여 넣지 않았다
- 전송 뒤 체크섬을 대조했다
- 긴 계산은 sbatch로 냈고, sacct로 실제 사용량을 확인해 다음 요청을 조정한다
⚠️ 이 글은 의학적 조언이 아니며, 특정 제품을 권하지 않습니다. 실제 조건은 사용하는 도구 설명서와 기관 SOP·서버 사용 지침을 우선하세요.
❓ 자주 묻는 질문
Q. conda와 컨테이너 중 무엇을 써야 하나요? A. 탐색 단계에서는 conda 환경이 가볍고 편합니다. 결과를 오래 보관하거나 다른 서버에서 똑같이 돌리려면 컨테이너 이미지도 함께 남기세요.
Q. pip로 설치해도 되나요? A. conda 문서는 별도 환경에서 conda로 깔 수 있는 것을 먼저 깔고 pip는 마지막에 쓰라고 합니다. pip 패키지도 environment.yml에 기록되는지 확인하세요8.
Q. 서버에서 Docker를 쓸 수 없다고 합니다.
A. 공용 HPC에서는 흔합니다. 같은 이미지를 apptainer pull docker://quay.io/biocontainers/도구:태그로 SIF로 바꿔 쓰면 됩니다.
📚 오믹스 기술 시리즈
- 1편 WGS 플랫폼 비교
- 2편 WGS 커버리지·깊이 설계
- 3편 WGS 데이터 처리와 QC
- 4편 WGS vs WES vs 패널
- 5편 리눅스 명령줄 기본기
- 6편 분석 환경 만들기 (이 글)
- 7편 FASTQ·BAM 실전
- 8편 VCF·BED 실전
- 9편 워크플로 관리
- 10편 R과 Python
- 11편 RNA-seq 실험 설계
- 12편 RNA-seq 데이터 분석
- 13편 small RNA-seq 실험 설계
- 14편 small RNA-seq 데이터 분석
참고
Samuel S, Mietchen D. Computational reproducibility of Jupyter notebooks from biomedical publications. GigaScience 2024;13:giad113. doi:10.1093/gigascience/giad113 ↩︎ ↩︎
mamba. User guide (mamba 2.10.0, 2026-11-06 확인) — mamba.readthedocs.io ↩︎
Bioconda. FAQs (2026-11-06 확인) — bioconda.github.io/faqs.html ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
mamba. Mamba installation (2026-11-06 확인) — mamba.readthedocs.io ↩︎
Bioconda. Usage (Bioconda 공식 문서, 2026-11-06 확인) — bioconda.github.io ↩︎ ↩︎ ↩︎
conda. Managing channels (conda 26.9.4, 2026-11-06 확인) — docs.conda.io ↩︎
Anaconda. Terms of Service FAQs (약관 2025-07-15, 2026-11-06 확인) — anaconda.com ↩︎
conda. Managing environments (conda 26.9.4, 2026-11-06 확인) — docs.conda.io ↩︎ ↩︎ ↩︎
conda. Changelog 26.3.0 (2026-03-30, 2026-11-06 확인) — github.com/conda/conda ↩︎
BioContainers. What is BioContainers (2026-11-06 확인) — biocontainers-edu.readthedocs.io ↩︎
Quay.io. biocontainers/samtools 태그 목록 (2026-11-06 확인) — quay.io/repository/biocontainers/samtools ↩︎
Docker. docker container run 레퍼런스 (Docker Engine 29.9.3, 2026-11-06 확인) — docs.docker.com ↩︎ ↩︎
Docker. Bind mounts (2026-11-06 확인) — docs.docker.com ↩︎
Apptainer. Community announcement: Singularity is now Apptainer (2021-11-30) — apptainer.org ↩︎
Apptainer. User Guide 1.5: Introduction (Apptainer 1.5.5, 2026-11-06 확인) — apptainer.org ↩︎
Apptainer. Support for Docker and OCI containers (2026-11-06 확인) — apptainer.org ↩︎
Apptainer. Bind paths and mounts (2026-11-06 확인) — apptainer.org ↩︎
OpenSSH. Release notes (OpenSSH 10.6p2, 2026-11-06 확인) — openssh.com ↩︎
rsync(1) manual (rsync 3.5.2, 2026-11-06 확인) — download.samba.org ↩︎ ↩︎
tmux(1) manual (tmux 3.8, 2026-11-06 확인) — man.openbsd.org ↩︎
SchedMD. sbatch (Slurm 26.05, 2026-11-06 확인) — slurm.schedmd.com ↩︎ ↩︎ ↩︎ ↩︎
SchedMD. squeue (Slurm 26.05, 2026-11-06 확인) — slurm.schedmd.com ↩︎
SchedMD. scancel (Slurm 26.05, 2026-11-06 확인) — slurm.schedmd.com ↩︎
SchedMD. sacct (Slurm 26.05, 2026-11-06 확인) — slurm.schedmd.com ↩︎
GNU coreutils. md5sum(1)·sha256sum(1) manual (2026-11-06 확인) — man7.org ↩︎ ↩︎
KISTI 국가슈퍼컴퓨팅센터. Neuron user guide: Running jobs through scheduler (SLURM) (2026-08-12 갱신, 2026-11-06 확인) — docs-ksc.gitbook.io ↩︎