챕터 23 선수지식: 전사체 분석 파이프라인 구축에 들어가기 전 알아야 할 것
1. 23챕터는 무엇을 하려는 장인가요?
23챕터는 Snakemake를 사용해 RNA-seq 분석 파이프라인을 구축하는 장입니다. RNA-seq은 RNA를 시퀀싱해서 어떤 유전자가 얼마나 발현되는지 보는 방법입니다. 이론적 배경은 9장 전사체학 기초에서 다루었으니, 자세한 내용이 필요하면 7~9장 선수지식 중 9장 부분을 참고하면 됩니다.
이 장의 핵심은 개별 명령어 하나하나가 아니라, 여러 분석 단계를 하나의 자동화된 흐름으로 묶는 것입니다. FASTQ 품질 확인, 어댑터 제거, STAR 정렬, 유전자별 count 생성 같은 과정을 손으로 하나씩 실행할 수도 있습니다. 하지만 샘플이 6개, 60개, 600개가 되면 사람이 일일이 명령어를 치는 방식은 실수하기 쉽습니다.
그래서 Snakemake 같은 워크플로우 관리 도구를 사용합니다.
23장을 한 문장으로 요약하면 이렇습니다.
“RNA-seq 분석 과정을 Snakefile이라는 설계도에 적어 두고, Snakemake가 필요한 작업을 순서대로 실행하게 만드는 장입니다.”
2. 워크플로우 관리 도구가 왜 필요한가요?
생명정보학 분석은 보통 한 번의 명령어로 끝나지 않습니다. 원자료를 검사하고, 정리하고, 정렬하고, 결과를 요약하고, 통계를 내고, 그림을 그리는 여러 단계가 이어집니다.
문제는 각 단계의 입력과 출력이 연결되어 있다는 점입니다. 예를 들어 STAR 정렬은 trimmed FASTQ가 있어야 실행됩니다. trimmed FASTQ는 cutadapt가 만들어야 합니다. cutadapt는 원본 FASTQ가 있어야 실행됩니다. FastQC 보고서는 원본 FASTQ를 직접 입력으로 사용합니다.
이런 관계를 사람이 머릿속으로만 관리하면 실수가 쉽게 납니다. 어떤 파일을 다시 만들었는데 뒤쪽 결과를 갱신하지 않을 수도 있고, 샘플 하나만 빠뜨릴 수도 있고, 파일 이름을 잘못 적을 수도 있습니다.
Snakemake는 이런 파일 의존성을 관리합니다. 최종적으로 어떤 파일이 필요하다고 말하면, 그 파일을 만들기 위해 어떤 중간 파일이 필요한지 거꾸로 추적하고, 필요한 rule을 순서대로 실행합니다.
초보자는 Snakemake를 “분석 조립 라인의 관리자”라고 생각하면 됩니다. 각 기계가 어떤 재료를 받아 어떤 제품을 만드는지 적어 두면, 관리자가 전체 순서를 맞춰 실행하는 식입니다.
3. Snakefile과 rule의 기본 감각
Snakemake에서는 분석 과정을 Snakefile이라는 파일에 적습니다. 이 파일 안에는 여러 개의 rule이 들어갑니다. rule은 하나의 작업 단위입니다.
가장 기본 구조는 다음과 같습니다.
rule 규칙명:
input:
"인풋 파일명"
output:
"아웃풋 파일명"
shell:
"쉘 명령"
input은 이 작업을 하기 위해 필요한 파일입니다. output은 이 작업이 성공했을 때 만들어져야 하는 파일입니다. shell은 실제로 실행할 명령어입니다.
예를 들어 다음 rule은 FASTQ를 BAM으로 바꾸는 작업을 나타냅니다.
rule bwa_map:
input:
"data/genome.fa",
"data/samples/A.fastq"
output:
"mapped_reads/A.bam"
shell:
"bwa mem {input} | samtools view -Sb - > {output}"
이것은 “data/genome.fa와 data/samples/A.fastq가 있으면, shell 명령을 실행해서 mapped_reads/A.bam을 만들 수 있다”라는 뜻입니다.
Snakemake는 output 파일이 이미 있고 input보다 최신이면 굳이 다시 실행하지 않을 수 있습니다. 반대로 output이 없거나 input이 바뀌었으면 다시 실행해야 한다고 판단할 수 있습니다.
4. 와일드카드는 반복 작업을 줄이는 방법입니다
샘플이 하나뿐이면 파일 이름을 직접 적어도 됩니다. 하지만 RNA-seq 분석에서는 보통 샘플이 여러 개입니다. 원문에서도 SRR4420293부터 SRR4420298까지 여러 샘플을 다룹니다.
이때 매 샘플마다 rule을 따로 쓰면 너무 비효율적입니다. 그래서 Snakemake는 와일드카드를 사용합니다.
"data/samples/{sample}.fastq"
여기서 {sample}은 빈칸 같은 자리입니다. 이 자리에 A, B, C, SRR4420293 같은 샘플 이름이 들어갈 수 있습니다.
expand 함수는 여러 샘플 이름을 넣어 파일 목록을 한 번에 만들어줍니다.
expand("data/{sample}/processed.txt", sample=["A", "B", "C"])
이 결과는 다음과 같습니다.
[
"data/A/processed.txt",
"data/B/processed.txt",
"data/C/processed.txt"
]
초보자는 expand를 “파일 이름 자동 생성기”라고 생각하면 됩니다. 여러 샘플을 처리할 때 실수를 줄여줍니다.
5. rule all은 최종 목표 목록입니다
Snakemake에서 rule all은 보통 최종적으로 만들고 싶은 결과 파일 목록을 적는 곳입니다. 직접 무언가를 처리하는 rule이라기보다는, 전체 파이프라인의 목표를 선언하는 rule입니다.
예를 들어 원문에서는 모든 샘플에 대해 FastQC 보고서와 STAR의 ReadsPerGene.out.tab 파일을 만들도록 합니다.
rule all:
input:
expand("fastqc/{sample}_1_fastqc.html", sample=SAMPLES),
expand("fastqc/{sample}_2_fastqc.html", sample=SAMPLES),
expand("star_output/{sample}/ReadsPerGene.out.tab", sample=SAMPLES)
이것은 “최종적으로 이 파일들이 모두 존재하면 파이프라인이 완료된 것으로 보겠다”는 뜻입니다.
Snakemake는 이 목록을 보고, 각 파일을 만들 수 있는 rule을 찾습니다. 그리고 그 rule에 필요한 input이 없으면, 그 input을 만들 수 있는 다른 rule을 다시 찾습니다. 이렇게 거꾸로 추적하며 실행 계획을 세웁니다.
이 감각이 매우 중요합니다. Snakemake는 위에서 아래로 무조건 순서대로 실행하는 단순 스크립트가 아닙니다. output과 input의 연결 관계를 보고 필요한 작업을 결정하는 도구입니다.
6. dry-run은 실행 전 시뮬레이션입니다
원문에서는 실제 실행 전에 다음 명령어를 사용합니다.
snakemake --dry-run
dry-run은 실제 명령어를 실행하지 않고, 어떤 작업이 실행될 예정인지 계획만 보여주는 기능입니다. 분석 파이프라인에서는 매우 중요합니다. 왜냐하면 한 번 실행하면 시간이 오래 걸리거나, 많은 파일이 만들어지거나, 기존 결과를 덮어쓸 수 있기 때문입니다.
초보자는 dry-run을 “실행 전 리허설”이라고 생각하면 됩니다. 실제로 무대에 올라가기 전에 동선을 점검하는 것입니다.
snakemake --cores 4
이 명령은 실제로 파이프라인을 실행합니다. --cores 4는 최대 4개의 CPU 코어를 사용하겠다는 뜻입니다. 여러 rule이나 thread를 활용해 병렬 실행할 수 있습니다.
7. RNA-seq 파이프라인의 각 단계 이해하기
원문 23장의 RNA-seq 파이프라인은 크게 다음 흐름입니다.
FastQC는 원본 FASTQ의 품질을 검사합니다. 이 내용은 19장과 이어집니다. read 품질이 괜찮은지, 어댑터가 남아 있는지, GC 함량이 이상하지 않은지 등을 봅니다.
cutadapt는 어댑터와 poly-A 꼬리를 제거합니다. RNA-seq에서는 RNA 분자의 poly-A tail이나 어댑터 서열이 분석에 방해될 수 있습니다. 그래서 잘라내는 과정이 필요합니다.
STAR는 RNA-seq read를 참조 유전체에 정렬합니다. 일반 DNA 정렬과 달리 RNA-seq 정렬은 스플라이싱을 고려해야 합니다. 진핵생물의 유전자는 엑손과 인트론으로 이루어져 있고, 성숙한 mRNA에서는 인트론이 제거됩니다. 그래서 RNA-seq read는 유전체상에서 떨어져 있는 두 엑손을 가로질러 정렬될 수 있습니다. STAR는 이런 splice-aware alignment에 특화된 도구입니다.
--quantMode GeneCounts 옵션을 사용하면 STAR가 유전자별 read count도 함께 계산해줍니다. 이 결과가 ReadsPerGene.out.tab 파일입니다.
8. STAR 인덱스는 왜 FASTA와 GTF가 모두 필요한가요?
STAR로 RNA-seq read를 정렬하려면 먼저 STAR 인덱스를 만들어야 합니다. 이때 참조 유전체 FASTA와 유전자 주석 GTF가 필요합니다.
FASTA는 염색체의 실제 염기서열입니다. 즉 기준이 되는 DNA 문장입니다. GTF는 유전자와 엑손이 유전체의 어느 위치에 있는지 알려주는 주석 파일입니다. 즉 유전체 문장 위에 “여기부터 여기까지가 이 유전자의 엑손입니다”라고 표시한 지도입니다.
DNA-seq read를 정렬할 때는 대체로 유전체 서열 자체가 중요합니다. 하지만 RNA-seq에서는 스플라이싱 때문에 유전자 구조 정보가 매우 중요합니다. STAR는 GTF 정보를 사용해 splice junction을 더 잘 처리할 수 있습니다.
초보자는 이렇게 기억하면 됩니다.
- FASTA: 기준 유전체의 글자 내용입니다.
- GTF: 그 글자들 중 어디가 유전자, 엑손, 전사체인지 표시한 주석입니다.
- STAR index: FASTA와 GTF를 바탕으로 만든 RNA-seq 정렬용 고속 검색 목차입니다.
9. ReadsPerGene.out.tab은 어떤 파일인가요?
ReadsPerGene.out.tab은 STAR가 만들어주는 유전자별 count 파일입니다. 각 유전자에 몇 개의 read가 매핑되었는지 담고 있습니다. 24장에서 차등 발현 분석을 할 때 이 파일들이 입력으로 사용됩니다.
이 파일의 처음 4줄은 보통 유전자 count가 아니라 전체 정렬 관련 통계입니다. 그래서 Python으로 읽을 때 skiprows=4를 사용합니다. 24장 코드에서도 이 부분이 나옵니다.
그 이후 줄들은 유전자별 count입니다. 보통 다음과 같은 열 구조를 가집니다.
| 열 | 의미 |
|---|---|
| 1열 | gene ID |
| 2열 | unstranded count |
| 3열 | forward stranded count |
| 4열 | reverse stranded count |
여기서 중요한 개념이 strandedness입니다.
10. Strandedness는 무엇인가요?
RNA-seq 라이브러리는 방향성 정보를 보존할 수도 있고, 보존하지 않을 수도 있습니다. 이것을 strandedness라고 합니다.
unstranded는 방향 정보를 사용하지 않는 방식입니다. read가 어느 DNA 가닥에서 왔는지 구분하지 않습니다.
forward stranded와 reverse stranded는 read의 방향 정보를 사용합니다. 실험 키트에 따라 실제 유전자의 방향과 read 방향이 같은 방식일 수도 있고 반대 방식일 수도 있습니다.
왜 이것이 중요할까요? 유전체에는 서로 반대 방향으로 겹치거나 가까이 있는 유전자가 있을 수 있습니다. 방향 정보를 잘못 선택하면 어떤 유전자의 발현량을 엉뚱하게 계산할 수 있습니다.
그래서 원문에서는 ReadsPerGene.out.tab의 2열, 3열, 4열 합계를 비교해서 어떤 열을 사용할지 판단합니다. 대부분의 count가 특정 열에 몰려 있다면 해당 방향성 열을 사용하는 것이 맞을 가능성이 큽니다.
입문 단계에서는 다음 정도로 이해하면 충분합니다.
RNA-seq count를 만들 때는 “어느 열이 내 실험 방식에 맞는 count인가?”를 확인해야 합니다.
24장 예제에서는 unstranded 열을 사용합니다. 하지만 실제 분석에서는 실험 라이브러리 유형에 맞게 선택해야 합니다.
11. 설정 파일 YAML은 왜 쓰나요?
원문 후반부에서는 config.yaml 같은 설정 파일 사용을 소개합니다. 분석이 복잡해지면 Snakefile 안에 샘플 목록, 참조 유전체 경로, thread 수, 도구 옵션 등을 모두 직접 적는 것이 불편해집니다.
YAML 파일은 설정값을 따로 보관하는 메모장 같은 역할을 합니다.
samples:
- SRR4420293
- SRR4420294
- SRR4420295
reference_dir: /path/to/reference
threads: 4
이렇게 설정을 분리하면, 분석 코드는 그대로 두고 샘플 목록이나 경로만 바꿀 수 있습니다. 재현성도 좋아집니다. 나중에 다른 사람이 봐도 어떤 샘플과 어떤 참조 유전체를 사용했는지 확인하기 쉽습니다.
초보자는 YAML을 “파이프라인의 환경설정 파일”이라고 이해하면 됩니다.
12. shell, script, run 블록은 어떻게 다른가요?
Snakemake rule 안에서는 작업 내용을 여러 방식으로 적을 수 있습니다. 처음에는 shell만 알아도 충분하지만, 본편을 읽다 보면 script나 run도 나올 수 있습니다.
| 블록 | 의미 | 언제 쓰나요? |
|---|---|---|
shell |
터미널 명령어를 실행합니다. | fastqc, cutadapt, STAR처럼 외부 프로그램을 부를 때 씁니다. |
script |
별도 Python/R 스크립트를 실행합니다. | 코드가 길어져 Snakefile 안에 넣기 불편할 때 씁니다. |
run |
Snakefile 안에 Python 코드를 직접 씁니다. | 간단한 파일 처리나 조건 처리를 Python으로 바로 하고 싶을 때 씁니다. |
즉 shell은 “명령어 실행”, script는 “외부 코드 파일 실행”, run은 “Snakefile 안에서 Python 실행”에 가깝습니다.
13. Snakemake 옵션을 겁먹지 않고 읽는 법
본편에는 실행 옵션이 여럿 나옵니다. 전부 외울 필요는 없지만, 다음 정도는 미리 봐두면 좋습니다.
| 옵션 | 뜻 |
|---|---|
-n 또는 --dry-run |
실제 실행하지 않고 실행 계획만 보여줍니다. |
-p 또는 --printshellcmds |
실행될 shell 명령어를 화면에 보여줍니다. |
-F 또는 --forceall |
결과 파일이 이미 있어도 강제로 다시 실행합니다. |
--dag |
rule 사이의 의존성 그래프를 그릴 수 있게 출력합니다. |
분석 파이프라인을 처음 돌릴 때는 보통 -n으로 계획을 확인하고, 문제가 없어 보이면 실제 실행으로 넘어갑니다. 에러가 났을 때는 -p가 도움이 됩니다. 어떤 명령어가 실제로 실행됐는지 볼 수 있기 때문입니다.
14. ReadsPerGene.out.tab 열을 고르는 연습
STAR의 ReadsPerGene.out.tab은 유전자별 count를 담지만, 열을 아무거나 고르면 안 됩니다. 보통 2열은 unstranded count, 3열과 4열은 strandedness 방향에 따른 count입니다.
예를 들어 어떤 라이브러리에서 여러 유전자의 count를 합쳤더니 다음과 같다고 합시다.
2열 unstranded 합계 = 1,200
3열 forward 합계 = 50
4열 reverse 합계 = 1,150
이 경우 4열이 대부분의 read를 담고 있으므로 reverse-stranded 방식일 가능성이 큽니다. 반대로 3열이 크면 forward-stranded일 가능성이 큽니다. 라이브러리 방향성을 모른 채 임의의 열을 쓰면, 이후 차등 발현 분석 전체가 틀어질 수 있습니다.
15. 23챕터 들어가기 전 최소 체크리스트
23장을 읽기 전에 다음 질문에 답할 수 있으면 좋습니다.
- Snakemake는 왜 필요한가요?
Snakefile은 무엇인가요?rule의input,output,shell은 각각 무엇을 뜻하나요?- 와일드카드
{sample}은 왜 쓰나요? expand는 무엇을 자동으로 만들어주나요?rule all은 왜 최종 목표 목록인가요?dry-run은 왜 실제 실행 전에 해봐야 하나요?- RNA-seq에서 STAR가 일반 DNA 정렬기와 다른 점은 무엇인가요?
- STAR 인덱스를 만들 때 FASTA와 GTF가 모두 필요한 이유는 무엇인가요?
ReadsPerGene.out.tab의 2, 3, 4열은 왜 구분해서 봐야 하나요?
이 질문들이 이해된다면 23장의 Snakefile은 단순한 코드 덩어리가 아니라, 파일들이 서로 이어지는 분석 설계도로 보일 것입니다.
문제 풀이
전사체 분석 파이프라인 구축
주관식 답안은 Gemini API로 채점합니다. API 키는 이 브라우저에만 저장됩니다.
-
1. [쉬움] 객관식
23챕터의 핵심 목표로 가장 적절한 것을 고르라.
-
2. [쉬움] 객관식
워크플로우 관리 도구가 필요한 이유로 가장 적절한 것을 고르라.
-
3. [쉬움] 객관식
Snakefile에서 rule이 의미하는 것으로 가장 적절한 것을 고르라.
-
4. [쉬움] 객관식
wildcard의 주된 역할로 가장 적절한 것을 고르라.
-
5. [쉬움] 객관식
rule all의 의미로 가장 적절한 것을 고르라.
-
6. [쉬움] 객관식
dry-run의 목적에 가장 가까운 것을 고르라.
-
7. [보통] 객관식
RNA-seq 파이프라인에서 STAR의 역할로 가장 적절한 것을 고르라.
-
8. [보통] 객관식
STAR index 생성에 FASTA와 GTF가 함께 쓰이는 이유로 가장 적절한 것을 고르라.
-
9. [보통] 객관식
다음 Snakemake 구조에서
output의 의미로 가장 적절한 것을 고르라.rule trim: input: "raw/{sample}.fastq.gz" output: "trimmed/{sample}.fastq.gz" shell: "cutadapt -o {output} {input}" -
10. [보통] 객관식
다음 rule에서
{sample}의 역할로 가장 적절한 것을 고르라.rule align: input: "trimmed/{sample}.fastq.gz" output: "bam/{sample}.bam" -
11. [보통] 객관식
다음 rule all의 의미로 가장 적절한 것을 고르라.
SAMPLES = ["A", "B"] rule all: input: expand("counts/{sample}.ReadsPerGene.out.tab", sample=SAMPLES) -
12. [보통] 객관식
다음 명령의 의도로 가장 적절한 것을 고르라.
snakemake -n -
13. [어려움] 객관식
다음 상황에서 Snakemake가 align rule을 다시 실행할 가능성이 가장 높은 경우를 고르라.
output bam/S1.bam은 존재한다. input trimmed/S1.fastq.gz가 그 이후에 수정되었다. -
14. [어려움] 객관식
다음 Snakemake rule의 잠재적 문제로 가장 적절한 것을 고르라.
rule count: input: "bam/{sample}.bam" output: "counts/{sample}.txt" shell: "cat fixed.bam > {output}" -
15. [어려움] 객관식
다음 YAML 설정 파일을 쓰는 이유로 가장 적절한 것을 고르라.
reference: ref/genome.fa gtf: ref/genes.gtf threads: 8 -
16. [어려움] 객관식
다음
ReadsPerGene.out.tab해석에서 가장 조심해야 할 점을 고르라.N_unmapped N_multimapping GeneA 10 8 2 GeneB 50 45 5 -
17. [어려움] 객관식
다음 파이프라인 의존성으로 가장 적절한 흐름을 고르라.
FASTQ -> ? -> BAM -> ReadsPerGene.out.tab -> count matrix -
18. [어려움] 객관식
다음 rule 설계 원칙으로 가장 적절한 것을 고르라.
여러 샘플의 STAR 정렬, count 생성, 최종 통합을 하나의 거대한 shell 명령으로 작성하려 한다. -
19. [어려움] 객관식
다음 명령 실행 전 가장 먼저 확인할 사항으로 적절한 것을 고르라.
snakemake --cores 8 -
20. [어려움] 객관식
다음 Snakemake 오류 상황의 원인으로 가장 적절한 것을 고르라.
MissingInputException: Missing input files for rule align: trimmed/S3.fastq.gz -
21. [쉬움] 객관식
Snakemake rule 안의
shell,script,run에 대한 설명으로 가장 적절한 것을 고르라. -
22. [보통] 객관식
실제 실행 없이 Snakemake가 어떤 작업을 할지 먼저 확인하려고 한다. 가장 적절한 옵션을 고르라.
-
23. [보통] 객관식
다음
ReadsPerGene.out.tab열 합계를 보고 가장 적절한 해석을 고르라.2열 unstranded = 1,200 3열 forward = 50 4열 reverse = 1,150 -
24. [보통] 객관식
다음 의존성에서 최종 목표가
counts.txt일 때 Snakemake가 거슬러 올라가며 확인해야 하는 순서로 가장 자연스러운 것을 고르라.raw.fastq → trimmed.fastq → aligned.bam → counts.txt -
주관식 1. [쉬움] 주관식 · Gemini 채점
Snakemake에서 rule, input, output, shell의 역할을 각각 설명하라.
-
주관식 2. [보통] 주관식 · Gemini 채점
rule all과 dry-run이 파이프라인 검증에서 중요한 이유를 설명하라.
-
주관식 3. [보통] 주관식 · Gemini 채점
STAR index 생성에 FASTA와 GTF가 모두 필요한 이유를 설명하라.
-
주관식 4. [어려움] 주관식 · Gemini 채점
Snakemake 파이프라인을 하나의 거대한 shell 명령 대신 작은 rule들로 나누는 장점을 설명하라.