infra
Platform

모듈 맵

[Infra Ops] SSL/TLS 인증서 형식 변환과 갱신 절차

0 / 52 완료

펼치기
0 / 52 완료0%

Infra-ops · 19 / 52

[Infra Ops] SSL/TLS 인증서 형식 변환과 갱신 절차

PEM/JKS/PFX 변환, Nginx/Tomcat 인증서 교체, 인증서 체인 오류 분석, 만료일 자동 알림까지 — 서비스 중단 없이 인증서를 교체하는 실무 절차

🚨INCIDENT ALERT
HIGH

매년 1~2회, 아무 예고도 없이 인증서 교체 작업이 찾아옵니다. 보안팀이 새 인증서 파일을 메일로 보내왔는데, 첨부된 파일은 .pfx 형식입니다. Nginx는 PEM 형식만 받고, Tomcat은 JKS를 쓰는데, 도대체 어떻게 변환하고 어디에 넣어야 할까요?

형식 변환에서 한 번 막히고, 체인 순서를 잘못 넣어서 한 번 더 막히고, 결국 서비스 중단까지 이어지는 경우가 생각보다 많습니다. 이 모듈에서 형식별 변환 명령어부터 서버별 교체 절차까지 단계별로 정리합니다.

이번 챕터에서 배울 것
  • 1PEM, JKS, PFX(PKCS12) 형식의 차이와 각 서버의 사용 형식을 구분할 수 있다
  • 2openssl과 keytool 명령어로 인증서 형식을 상호 변환할 수 있다
  • 3Nginx와 Tomcat에 인증서를 서비스 영향 최소화 방식으로 교체할 수 있다
  • 4openssl s_client로 인증서 체인 오류를 현장에서 즉시 진단할 수 있다
  • 5만료일 모니터링 스크립트를 작성해 cron으로 자동 알림을 구성할 수 있다
실습 환경 준비
openssl 버전 확인
openssl version
keytool 버전 확인 (JDK 필수)
keytool -version
작업 디렉터리 생성
mkdir -p /tmp/cert-work && cd /tmp/cert-work
기존 Nginx 인증서 경로 확인
grep -r 'ssl_certificate' /etc/nginx/sites-enabled/ 2>/dev/null | head -5
기존 Tomcat keystore 경로 확인
grep -r 'keystoreFile' /opt/tomcat/conf/server.xml 2>/dev/null | head -3

인증서 형식 이해

💡개념

PEM, JKS, PFX: 형식이 다른 이유

인증서 형식이 여러 가지로 나뉜 것은 운영 체제와 플랫폼의 역사적 차이에서 비롯됩니다. Nginx와 Apache가 주로 쓰는 Linux 환경은 텍스트 기반 PEM을, Java/Tomcat은 바이너리 키스토어인 JKS를, Windows IIS는 PKCS12(PFX) 형식을 표준으로 채택했기 때문입니다. 보안팀이 전달한 파일이 어떤 형식인지, 적용할 서버가 어떤 형식을 요구하는지를 파악하지 못하면 올바른 인증서를 받았어도 교체 작업이 막히고 서비스 중단으로 이어질 수 있습니다.

인증서 형식 변환 구조 다이어그램

보안팀이 인증서 갱신 파일을 .pfx로 보내왔습니다. Nginx 서버에 적용해야 하는데 Nginx는 PEM만 받고, Tomcat용으로는 JKS가 필요합니다. 변환 명령어를 찾아 실행했더니 또 비밀번호를 묻습니다. 어떤 비밀번호인지 모르고, 변환에 성공해도 Nginx에 적용하고 보니 체인 오류가 납니다. 형식 차이를 모른 채 시작하면 이 순간마다 막힙니다.

인증서 형식이 여러 개인 것은 역사적 이유와 플랫폼 차이 때문입니다. 형식을 모르면 올바른 파일을 받아도 어디에 넣어야 할지 막막합니다.

PEM (Privacy Enhanced Mail)

가장 범용적인 형식입니다. Base64로 인코딩된 텍스트 파일이며 -----BEGIN CERTIFICATE-----로 시작합니다. 인증서(cert.pem), 개인키(key.pem), 체인 포함 인증서(fullchain.pem)를 별도 파일로 분리해 관리합니다. 리눅스 기반 서버(Nginx, Apache, HAProxy)에서 표준으로 사용합니다.

로컬 터미널
# PEM 파일 헤더로 내용 식별
head -1 cert.pem
# -----BEGIN CERTIFICATE-----          ← 인증서
# -----BEGIN PRIVATE KEY-----          ← 개인키 (PKCS8 형식)
# -----BEGIN RSA PRIVATE KEY-----      ← RSA 개인키 (PKCS1 형식)
# -----BEGIN CERTIFICATE REQUEST-----  ← CSR (인증서 서명 요청)

JKS (Java KeyStore)

Java 전용 바이너리 형식입니다. 인증서와 개인키, 체인을 하나의 파일에 묶어 비밀번호로 보호합니다. Tomcat의 전통적인 keystore 형식이며 keytool 명령어로만 다룰 수 있습니다.

PFX / PKCS12

Windows IIS의 표준 형식이지만, Java/Tomcat도 지원합니다. JKS처럼 인증서와 개인키를 하나로 묶되 PKCS12 표준을 따릅니다. 보안팀이 Windows에서 발급한 인증서를 전달할 때 자주 이 형식으로 옵니다. Java 9부터 JDK의 기본 keystore 형식이 PKCS12로 변경됐습니다.

형식구분사용 서버다루는 도구
PEM텍스트Nginx, Apache, HAProxyopenssl
JKS바이너리Tomcat (Java 8 이하 기본)keytool
PFX/PKCS12바이너리IIS, Tomcat (Java 9+)openssl, keytool
💡개념

인증서 구성요소: 체인을 이해해야 교체 실수가 없다

인증서 하나가 아닌 체인 구조라는 것을 이해하지 못하면 교체 후 체인 오류가 반드시 납니다.

루트 CA (Root CA)
    └── 중간 CA (Intermediate CA) — 예: DigiCert TLS RSA SHA256 2020 CA1
            └── 도메인 인증서 (End-Entity Certificate) — 예: *.yourdomain.com

브라우저 검증 순서: 도메인 인증서 → 중간 CA → 루트 CA. 중간 CA가 체인에 없으면 브라우저는 루트 CA까지 연결 고리를 찾지 못해 unable to verify the first certificate 오류를 냅니다.

파일별 포함 내용:

파일명포함 내용Nginx 옵션
cert.pem도메인 인증서만단독 사용 불가
chain.pem중간 CA만
fullchain.pem도메인 인증서 + 중간 CAssl_certificate
privkey.pem개인키ssl_certificate_key

Nginx에는 반드시 fullchain.pem을 씁니다. cert.pem만 넣으면 일부 클라이언트에서 체인 오류가 납니다.

인증서 형식 변환

1현재 인증서 정보 확인 및 만료일 점검

인증서 작업 전 항상 파일 내용을 먼저 확인합니다. Subject는 이 인증서가 발급된 도메인, Issuer는 발급한 CA, Not After는 만료일입니다. 교체 전 올바른 도메인의 인증서인지 반드시 확인합니다.

openssl x509 -in cert.pem -noout -text | grep -E 'Subject:|Issuer:|Not Before|Not After'
🔍실행 후 확인할 것
  • Subject: CN=*.yourdomain.com — 도메인 일치 여부 확인
  • Issuer: CN=중간CA이름 — 발급 CA 확인
  • Not Before: 인증서 유효 시작일
  • Not After: 인증서 만료일 — 오늘 날짜와 비교해 남은 기간 확인
  • 와일드카드 인증서라면 Subject에 *.yourdomain.com 형태
로컬 터미널
# 원격 서버 인증서 만료일 확인 (스크립팅에 자주 씀)
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \
  | openssl x509 -noout -dates

# 만료까지 남은 일수 계산
EXPIRY=$(echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \
  | openssl x509 -noout -enddate | cut -d= -f2)
echo "만료일: $EXPIRY"
DAYS=$(( ($(date -d "$EXPIRY" +%s) - $(date +%s)) / 86400 ))
echo "남은 기간: ${DAYS}일"
2PFX → PEM 변환 (보안팀이 PFX로 전달한 경우)

-nokeys 옵션으로 인증서만 추출합니다. 개인키는 별도로 추출합니다. -legacy 옵션은 OpenSSL 3.x에서 구버전 PFX 파일을 처리할 때 필요합니다. 명령 실행 시 PFX 비밀번호(Import Password)를 입력하라는 프롬프트가 나옵니다.

openssl pkcs12 -in cert.pfx -nokeys -out cert.pem -legacy
🔍실행 후 확인할 것
  • Enter Import Password: 프롬프트에서 PFX 비밀번호 입력
  • cert.pem 파일 생성 확인: ls -lh cert.pem
  • 파일 헤더 확인: head -1 cert.pem → '-----BEGIN CERTIFICATE-----'
  • 인증서 개수 확인: grep -c 'BEGIN CERTIFICATE' cert.pem (1개=도메인만, 2+개=체인 포함)
로컬 터미널
# 개인키 별도 추출 (-nocerts)
openssl pkcs12 -in cert.pfx -nocerts -nodes -out privkey.pem -legacy
# -nodes: 개인키를 다시 암호화하지 않음 (Nginx가 패스프레이즈 없이 읽을 수 있게)

# fullchain.pem이 없을 때: 체인 파일을 수동으로 합치기
cat cert.pem chain.pem > fullchain.pem

# PEM → PFX 변환 (JKS 없는 환경에서 Tomcat에 줄 때)
openssl pkcs12 -export \
  -in fullchain.pem \
  -inkey privkey.pem \
  -out cert.pfx \
  -name tomcat
# Export Password 입력 → Tomcat server.xml에 이 비밀번호 사용

# PEM → JKS 변환 (구형 Tomcat 8 이하)
# 1단계: PEM을 PFX로 먼저 변환 (위 명령)
# 2단계: PFX를 JKS로 변환
keytool -importkeystore \
  -srckeystore cert.pfx \
  -srcstoretype PKCS12 \
  -destkeystore keystore.jks \
  -deststoretype JKS

Nginx 인증서 교체 (무중단)

💡개념

Nginx 인증서 교체 원칙: reload면 무중단

인증서 교체가 두렵게 느껴지는 이유는 "서비스를 내려야 하는 게 아닐까"라는 걱정 때문입니다. 자정에 점검 시간을 잡고 교체하다 실수로 설정이 깨지면 복구하는 동안 서비스 다운이 길어집니다. Nginx는 restart 없이도 인증서를 교체할 수 있어서, 이 두려움이 사라집니다.

Nginx는 systemctl reload nginx 명령으로 기존 연결을 끊지 않고 설정과 인증서를 다시 읽습니다. 재시작(restart)은 불필요합니다. 다만 새 인증서 파일을 제자리에 복사하기 전에 nginx -t로 설정 검증을 먼저 해야 합니다. 인증서 파일 경로가 바뀌면 설정 파일도 수정해야 합니다.

인증서 라이프사이클 — 발급부터 갱신까지

3Nginx 인증서 교체 절차

인증서 파일을 교체한 뒤 설정 문법을 검증하고 reload합니다. reload는 마스터 프로세스가 새 설정을 읽고 워커 프로세스를 graceful하게 교체합니다. 기존 연결은 유지되고 새 연결부터 새 인증서를 사용합니다.

sudo nginx -t && sudo systemctl reload nginx
로컬 터미널
# Nginx 인증서 교체 전체 절차

# 1. 기존 인증서 백업
BACKUP_DATE=$(date +%Y%m%d)
sudo cp /etc/nginx/ssl/cert.pem /etc/nginx/ssl/cert.pem.bak_${BACKUP_DATE}
sudo cp /etc/nginx/ssl/privkey.pem /etc/nginx/ssl/privkey.pem.bak_${BACKUP_DATE}

# 2. 새 인증서 복사
sudo cp /tmp/cert-work/fullchain.pem /etc/nginx/ssl/cert.pem
sudo cp /tmp/cert-work/privkey.pem /etc/nginx/ssl/privkey.pem

# 3. 파일 권한 설정
sudo chmod 644 /etc/nginx/ssl/cert.pem
sudo chmod 600 /etc/nginx/ssl/privkey.pem   # 개인키는 root만 읽기
sudo chown root:root /etc/nginx/ssl/privkey.pem

# 4. 설정 검증 후 reload
sudo nginx -t && sudo systemctl reload nginx

# 5. 교체 결과 즉시 확인
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \
  | openssl x509 -noout -dates
🔍실행 후 확인할 것
  • nginx -t 출력: syntax is ok / test is successful 확인
  • reload 후 브라우저에서 인증서 정보 클릭 → 새 만료일 확인
  • openssl s_client로 만료일 스크립트 재실행해 새 날짜 출력 확인
  • curl -I https://yourdomain.com → 200 응답 확인

Tomcat 인증서 교체 (재시작 필요)

💡개념

Tomcat 인증서 교체: 재시작 피할 수 없다

연 1~2회 찾아오는 인증서 교체 작업에서 Tomcat은 Nginx보다 까다롭습니다. keystore를 교체해도 Tomcat이 이미 메모리에 올려둔 인증서를 그냥 씁니다. 결국 재시작이 필요하고, 재시작 = 다운타임입니다. 이것을 모르고 교체했다가 "왜 아직도 옛날 인증서가 보이냐"는 문의를 받는 경우가 생깁니다.

Tomcat은 시작 시 keystore 파일을 한 번만 읽습니다. Nginx와 달리 reload 개념이 없어 인증서를 교체하면 재시작이 필요합니다. 따라서 교체 시간 = 다운타임입니다. 점검 시간대를 확보하거나, L4/L7 앞에 여러 Tomcat이 있다면 Rolling 교체로 무중단을 구성할 수 있습니다.

로컬 터미널
# Tomcat JKS keystore 교체 절차

# 1. 기존 keystore 백업
BACKUP_DATE=$(date +%Y%m%d)
sudo cp /opt/tomcat/conf/keystore.jks \
       /opt/tomcat/conf/keystore.jks.bak_${BACKUP_DATE}

# 2. 새 keystore 복사
sudo cp /tmp/cert-work/keystore.jks /opt/tomcat/conf/keystore.jks
sudo chown tomcat:tomcat /opt/tomcat/conf/keystore.jks
sudo chmod 640 /opt/tomcat/conf/keystore.jks

# 3. server.xml keystore 비밀번호 확인 (필요 시 수정)
grep 'keystorePass\|keystoreFile' /opt/tomcat/conf/server.xml

# 4. keystore 내용 검증
keytool -list -v -keystore /opt/tomcat/conf/keystore.jks -storepass 비밀번호 \
  | grep -E 'Alias|Valid from|Owner'

# 5. Tomcat 재시작
sudo systemctl stop tomcat
sudo systemctl start tomcat

# 6. 시작 로그에서 SSL 초기화 오류 확인
sudo tail -50 /opt/tomcat/logs/catalina.out | grep -i 'ssl\|cert\|keystore'
XML
<!-- server.xml SSL 커넥터 예시 (PFX 직접 사용 — Java 9+) -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
  <SSLHostConfig>
    <Certificate certificateKeystoreFile="conf/cert.pfx"
                 certificateKeystoreType="PKCS12"
                 certificateKeystorePassword="${KEYSTORE_PASSWORD}"
                 type="RSA" />
  </SSLHostConfig>
</Connector>

비밀번호를 ${KEYSTORE_PASSWORD} 형태의 환경변수 참조로 설정하면 server.xml에 평문이 남지 않습니다. Tomcat 9.0.x 이상에서 지원합니다.

인증서 체인 오류 진단

4openssl s_client로 인증서 체인 검증

-showcerts로 서버가 전송하는 전체 인증서 체인을 출력합니다. 정상이라면 도메인 인증서(depth=0)와 중간 CA(depth=1)가 보여야 합니다. Verify return code: 0 (ok)가 마지막에 나오면 체인 검증 성공입니다.

openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null | grep -E 'subject|issuer|Verify'
🔍실행 후 확인할 것
  • depth=0 subject: CN=yourdomain.com — 도메인 인증서 확인
  • depth=1 subject: CN=중간CA이름 — 중간 CA 존재 확인
  • Verify return code: 0 (ok) — 체인 검증 성공
  • Verify return code: 21 (unable to verify the first certificate) — 중간 CA 누락
  • Certificate chain 섹션에 인증서가 1개만 있으면 fullchain.pem 미사용

443포트로 HTTPS 요청을 보냈는데 서버가 암호화되지 않은 HTTP 응답을 반환할 때 발생합니다. Nginx 설정에서 listen 443 ssl;ssl 키워드가 빠졌거나, ssl_certificate 경로가 잘못된 경우가 가장 흔한 원인입니다.

로컬 터미널
# 1. 443포트에서 SSL로 리스닝 중인지 확인
sudo ss -tlnp | grep ':443'
# 출력이 없으면 Nginx가 443을 열지 않음

# 2. Nginx 설정에서 ssl 키워드 확인
sudo nginx -T | grep -B2 -A5 'listen 443'
# listen 443;       ← 잘못됨 (ssl 없음)
# listen 443 ssl;   ← 올바름

# 3. 인증서 파일 경로 존재 여부 확인
sudo nginx -T | grep 'ssl_certificate'
# 경로가 올바른지 실제 파일 존재 확인
ls -lh /경로/fullchain.pem /경로/privkey.pem

# 4. 설정 수정 후 검증 및 reload
sudo nginx -t && sudo systemctl reload nginx

Nginx ssl_certificate에 fullchain.pem 대신 cert.pem만 지정했을 때 발생합니다. 도메인 인증서만 있고 중간 CA가 빠져 브라우저가 루트 CA까지 체인을 추적하지 못합니다. 내부 테스트에서는 통과했지만 외부 클라이언트나 API 연동 서버에서만 오류가 날 수 있습니다.

로컬 터미널
# 현재 Nginx가 사용 중인 인증서 파일 확인
sudo nginx -T | grep 'ssl_certificate '
# ssl_certificate /etc/nginx/ssl/cert.pem;  ← fullchain이 아닌 cert.pem이면 문제

# fullchain.pem이 있는지 확인
ls -lh /etc/nginx/ssl/fullchain.pem

# cert.pem에 체인이 포함됐는지 확인 (인증서 개수 확인)
grep -c 'BEGIN CERTIFICATE' /etc/nginx/ssl/cert.pem
# 1이면 도메인 인증서만 있음
# 2 이상이면 체인 포함

# fullchain.pem이 없으면 직접 만들기
cat /etc/nginx/ssl/cert.pem /etc/nginx/ssl/chain.pem > /etc/nginx/ssl/fullchain.pem

# server.xml 수정 후 reload
# ssl_certificate /etc/nginx/ssl/fullchain.pem;  ← 수정
sudo nginx -t && sudo systemctl reload nginx

# 수정 후 체인 재확인
openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null | grep 'Verify return code'
💼
실무 맥락
현업 패턴

연 1~2회 인증서 교체 작업 절차서 예시

로컬 터미널
#!/bin/bash
# 인증서 교체 작업 체크리스트 스크립트
# 실행 전 DOMAIN, CERT_DIR, NEW_CERT_DIR 변수 수정

DOMAIN="yourdomain.com"
CERT_DIR="/etc/nginx/ssl"
NEW_CERT_DIR="/tmp/cert-work"
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)

echo "=== 1. 작업 전 현재 인증서 상태 확인 ==="
echo | openssl s_client -connect ${DOMAIN}:443 2>/dev/null \
  | openssl x509 -noout -dates

echo ""
echo "=== 2. 새 인증서 정보 확인 ==="
openssl x509 -in ${NEW_CERT_DIR}/fullchain.pem -noout -dates
openssl x509 -in ${NEW_CERT_DIR}/fullchain.pem -noout -subject

echo ""
echo "=== 3. 기존 인증서 백업 ==="
cp ${CERT_DIR}/fullchain.pem ${CERT_DIR}/fullchain.pem.bak_${BACKUP_DATE}
cp ${CERT_DIR}/privkey.pem ${CERT_DIR}/privkey.pem.bak_${BACKUP_DATE}
echo "백업 완료: ${CERT_DIR}/*.bak_${BACKUP_DATE}"

echo ""
echo "=== 4. 새 인증서 적용 ==="
cp ${NEW_CERT_DIR}/fullchain.pem ${CERT_DIR}/fullchain.pem
cp ${NEW_CERT_DIR}/privkey.pem ${CERT_DIR}/privkey.pem
chmod 644 ${CERT_DIR}/fullchain.pem
chmod 600 ${CERT_DIR}/privkey.pem
nginx -t && systemctl reload nginx
echo "Nginx reload 완료"

echo ""
echo "=== 5. 교체 후 검증 ==="
sleep 2
echo | openssl s_client -connect ${DOMAIN}:443 2>/dev/null \
  | openssl x509 -noout -dates
openssl s_client -connect ${DOMAIN}:443 -showcerts 2>/dev/null \
  | grep 'Verify return code'

만료일 자동 알림 스크립트 (cron으로 매주 월요일 실행)

로컬 터미널
#!/bin/bash
# /usr/local/bin/check-ssl-expiry.sh

DOMAINS=("yourdomain.com" "api.yourdomain.com" "admin.yourdomain.com")
ALERT_DAYS=30
SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
MAIL_TO="ops@yourcompany.com"

for DOMAIN in "${DOMAINS[@]}"; do
  EXPIRY=$(echo | openssl s_client -connect ${DOMAIN}:443 2>/dev/null \
    | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)

  if [ -z "$EXPIRY" ]; then
    MESSAGE="경고: ${DOMAIN} 인증서 확인 실패 (연결 불가)"
  else
    DAYS=$(( ($(date -d "$EXPIRY" +%s) - $(date +%s)) / 86400 ))
    if [ "$DAYS" -lt "$ALERT_DAYS" ]; then
      MESSAGE="인증서 만료 임박: ${DOMAIN} — ${DAYS}일 후 만료 (${EXPIRY})"
    fi
  fi

  if [ -n "$MESSAGE" ]; then
    echo "$MESSAGE" | mail -s "[SSL 경고] ${DOMAIN}" "$MAIL_TO"
    curl -s -X POST -H 'Content-type: application/json' \
      --data "{\"text\":\"${MESSAGE}\"}" "$SLACK_WEBHOOK"
  fi
done
로컬 터미널
# crontab 등록 (매주 월요일 오전 9시)
# 0 9 * * 1 /usr/local/bin/check-ssl-expiry.sh

인증서 교체 작업 기록 예시:

[인증서 교체 기록]
날짜: 2026-05-30
담당자: 홍길동
대상: yourdomain.com (Nginx + Tomcat)
이전 만료일: 2026-06-01
새 만료일: 2027-06-01
발급기관: DigiCert
교체 절차: PFX → PEM 변환 → Nginx fullchain 적용 → Tomcat JKS 갱신
다운타임: Tomcat 재시작 2분 (00:30~00:32)
검증: openssl s_client 체인 확인 완료
다음 교체 예정: 2027-05-01 (만료 30일 전)

다음 모듈에서는 인프라 장애 상황에서의 포스트모템 작성과 장애 원인 분석 프레임워크를 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

PEM, JKS, PFX(PKCS12) 인증서 형식의 주요 사용처가 올바르게 연결된 것은?

Q2

Nginx에 인증서를 교체한 직후 브라우저에서 'unable to verify the first certificate' 오류가 발생했습니다. 가장 유력한 원인은?

Q3

로컬에 있는 인증서 파일의 만료일을 확인하는 명령어는?

Q4

Tomcat server.xml에 keystore 비밀번호를 평문으로 기록하는 것의 문제점과 대안은?

0 / 4 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

infra-ops중급 · 60
[Infra Ops] L4/L7 로드밸런서와 VIP 기반 이중화 구성
인프라 서비스 운영 트랙 계속
linux입문 · 30
[Linux] 개발자가 왜 리눅스 서버와 커맨드라인을 반드시 배워야 하는가
Linux 트랙 시작점