본문으로 건너뛰기
서버 구축과 원격 작업 — Docker·Git·nginx

생성 수정

IBM * 레드햇 AX 과정 · 28강

서버 구축과 원격 작업 — Docker·Git·nginx

2026년 7월 27일(월) ~ 7월 31일(금)

이 강의 문제풀이 — 배운 내용을 주관식 문답으로 확인해보세요.풀어보기 →

7. 서버를 세우는 순서 — 왜 도커 → 깃 → nginx인가

이번 주 월요일은 EC2 위에 실제 서버를 세웠습니다. 명령어는 9절에 그대로 있고, 여기서는 순서의 근거를 봅니다. 순서를 외우는 것보다 왜 그 순서인지를 아는 편이 훨씬 오래 갑니다.

7.1 순서와 그 근거

① Docker  →  ② Git  →  ③ nginx
순서왜 여기인가
① Docker 먼저git clone 은 코드만 받는 것입니다. docker compose up 을 하려면 Docker가 이미 있어야 합니다. 게다가 Docker 설치 중간에 재로그인이 한 번 필요합니다. 먼저 끝내 두는 편이 낫습니다.
② Git 그다음코드를 받아야 띄울 것이 생깁니다.
③ nginx 마지막🏭 nginx는 리버스 프록시입니다. 뒤에서 받아줄 대상이 먼저 떠 있어야 의미가 있습니다.

⭐ 일반화하면: 인프라는 의존의 방향과 반대로 설치합니다. A가 B에 의존하면 B를 먼저 세웁니다. 5주차에서 배운 의존성의 방향이 서버 구축 순서로 내려앉은 것입니다.

7.2 리버스 프록시가 하는 일

리버스 프록시(Reverse Proxy) — [프록시]인데, [클라이언트가 아니라 서버 쪽에 서서 요청을 안쪽으로 넘긴다]는 점에서 일반(포워드) 프록시와 구별된다.

[브라우저] ──▶ :80 ──▶ [nginx] ──▶ [fastapi:8000]  (도커 네트워크 안)

3주차에서 배운 GoF 패턴 중 프록시 패턴 — 접근을 제어하는 대리자 — 이 인프라 층에서 그대로 나타난 것입니다.

리버스 프록시를 두면 얻는 것입니다.

얻는 것무엇이 좋아지는가
단일 진입점바깥에서는 80/443 두 포트만 보입니다
HTTPS 종료인증서를 nginx 한 곳에서만 관리
백엔드 은닉FastAPI의 ports: - "8000:8000" 을 삭제해 8000 직결 우회를 차단
교체 자유뒤의 앱을 바꿔도 바깥 주소는 그대로

⭐ proxy_pass http://fastapi:8000; 에서 fastapi 는 IP가 아니라 compose 서비스명입니다. 같은 네트워크에 있으면 도커 내부 DNS가 이름을 풀어 줍니다. 앞에서 배운 대로 Cloudflare 터널 설정도 localhost 가 아니라 도커 인터널(컨테이너 이름) 주소로 해야 합니다. 같은 원리입니다.

7.3 HTTPS는 nginx 혼자 못 한다

⚠️ HTTPS를 적용하려면 SSL/TLS 인증서 발급과 nginx 연동이 반드시 필요합니다. nginx 혼자서는 HTTPS가 되지 않습니다.

Certbot(Let's Encrypt) 을 쓰는 이유 세 가지입니다.

  1. 무료 인증서
  2. ⭐ 자동 갱신 (핵심) — Let's Encrypt 인증서는 유효기간이 90일입니다. 손으로 갱신하면 반드시 잊습니다.
  3. nginx 컨테이너와 certbot 컨테이너가 /etc/letsencrypt 볼륨을 공유합니다.

자동 갱신이 실제로 도는 구조가 중요합니다. nginx는 6시간마다 설정을 다시 불러오고, certbot은 12시간마다 갱신을 시도합니다. 둘 다 무한 루프입니다. 4단계에서 배운 루프가 인프라에도 있습니다.

대안도 알아 두세요: Nginx Proxy Manager(GUI) / Traefik·Caddy(SSL 완전 자동) / AWS CloudFront + ACM.

7.4 배포용 키는 왜 따로 만드는가

EC2에서 private 레포를 클론하려면 인증이 필요합니다. 두 가지 방법이 있습니다.

방법성격언제
HTTPS + PAT개인 토큰손으로 몇 번 받을 때
SSH 배포 키(Deploy Key)레포 하나에만 유효한 키서버 자동 배포엔 이쪽이 정석

배포 키가 정석인 이유는 권한 범위 때문입니다. 개인 토큰은 내 모든 레포에 대한 권한을 갖지만, 배포 키는 그 레포 하나에만 붙습니다. 3층에서 배운 최소 권한 원칙이 그대로 적용됩니다. ⚠️ 그리고 EC2에 올릴 때는 레포를 private으로 바꾸고, 작업이 끝난 뒤 다시 public으로 돌립니다. 서버 설정 파일과 배포 스크립트에는 생각보다 많은 정보가 들어 있습니다.

7.5 가장 자주 걸리는 곳 — 보안 그룹

⚠️ EC2 보안 그룹에서 80 포트를 열지 않는 것이 이 작업에서 가장 자주 걸리는 지점입니다.

증상이 특이합니다. 서버 안에서는 되는데 밖에서만 안 됩니다.

# 서버 안에서 — 성공
curl http://localhost/

# 내 노트북 브라우저에서 — 무한 로딩

curl localhost 가 되는데 브라우저가 안 되면 애플리케이션이 아니라 방화벽을 의심하세요. 인바운드 규칙에 HTTP(80) 0.0.0.0/0 을 추가합니다.

7.6 nginx 이후 마무리 4단계

기본 안내 페이지가 뜨는 상태에서 실서비스까지 가려면 네 가지가 남습니다.

#단계하는 일
1백엔드 연결 (Proxy Pass)location / 에 proxy_pass 와 헤더 4종
2Cloudflare DNS A 레코드Type A / Name api / IPv4 = EC2 퍼블릭 IP / Proxy status 주황색 구름(Proxied)
3HTTPSCloudflare SSL/TLS 모드를 Full 또는 Full (Strict) + Certbot 발급
4CORSVercel 프론트(example.com)가 EC2 백엔드(api.example.com)로 요청할 때 필요. 설정 위치는 백엔드 애플리케이션 코드(권장)

⚠️ CORS를 nginx에 넣고 싶은 유혹이 생기는데, 백엔드 코드에 두는 편이 권장됩니다. 허용 Origin이 애플리케이션의 관심사이고, 로컬 개발 환경과 설정을 공유할 수 있기 때문입니다.


8. 원격에서 일한다는 것

7/30에는 개발 환경 자체가 EC2 안으로 들어갔습니다. 여기서 생기는 문제 세 가지와 해법이 이번 주의 마지막 개념 덩어리입니다.

8.1 문제 ① 세션이 끊긴다 → tmux

SSH로 접속해 긴 작업을 걸어 두면, 네트워크가 잠깐만 끊겨도 작업이 통째로 죽습니다.

tmux — [터미널 멀티플렉서]인데, [세션을 터미널에서 분리해 서버 쪽에 살려 둔다]는 점에서 일반 셸과 구별된다.

[내 노트북 터미널] ──SSH──▶ [EC2]
                              └── tmux 세션 "claude"  ← 접속이 끊겨도 여기는 계속 돕니다

세션 유지를 위해 tmux는 필수입니다. 끊기면 다시 붙기만 하면 됩니다.

⭐ 3주차의 프로세스와 런타임 개념이 여기서 실감됩니다. 내 터미널 창은 표시 장치일 뿐이고, 실제로 도는 프로세스는 서버에 있습니다. 창을 닫는 것과 프로세스를 죽이는 것은 다른 일입니다.

8.2 문제 ② 이미지를 붙여넣을 수 없다 → 경로로 참조

SSH로 EC2 안의 클로드 코드에 접속하면 이미지 붙여넣기가 안 됩니다. 클립보드는 내 노트북에 있고 에이전트는 서버에 있기 때문입니다.

해법은 파일을 먼저 올리고 경로로 참조하는 것입니다.

[윈도우 스크린샷] → scp로 EC2에 업로드 → 에이전트에게 @경로 로 참조시킴

⭐ 이것도 3주차 축입니다. 클립보드는 메모리이고 파일은 디스크입니다. 메모리는 기계 경계를 넘지 못하고, 디스크의 파일은 넘을 수 있습니다. 그래서 경계를 넘길 것은 파일로 만듭니다.

같은 원리가 2층(컨텍스트 엔지니어링)에도 있었습니다. 대화창의 글은 세션 경계를 못 넘고, .md 파일은 넘습니다.

8.3 문제 ③ MCP가 연결되지 않는다 → 실행 파일이 있어야 한다

.mcp.json 에 MCP 서버를 프로젝트 스코프로 등록해도, EC2 호스트에 그 실행 파일이 없으면 그 머신에서는 연결이 실패합니다.

which hermes
# → not found  ← 등록이 아무리 맞아도 연결 안 됨

⭐ .mcp.json 은 "무엇을 쓸 것인가"의 선언이지 "그것이 설치되어 있다"는 보증이 아닙니다. 5주차의 용어로 말하면 .mcp.json 은 추상(포트) 이고, 실행 파일은 구상(어댑터) 입니다. 포트만 있고 어댑터가 없으면 아무 일도 일어나지 않습니다.

8.4 낮은 사양 서버에서는 무엇을 고를 것인가

방식무게원격 저사양에서
VS Code Remote-SSH무거움 (서버에 확장이 설치됨)⚠️ 버거움
SSH + 클로드 코드 (CLI)가벼움⭐ 유리

⭐ CLI가 GUI보다 원격에서 유리한 이유는 주고받는 것이 글자뿐이기 때문입니다. GUI는 화면을 그려야 하고 서버 쪽에 무거운 상주 프로세스를 요구합니다.

8.5 비용은 기능이 아니라 설계다

10주차에서 배운 문장이 이번 주에 실전 규칙이 됩니다.

AWS 크레딧 — 2025년 7월 15일 이후 신규 계정은 가입 시 $100, EC2·Bedrock 등 사용 시 추가 $100로 6개월간 최대 $200입니다. 차감 순서는 프리티어 → 크레딧 → 카드 순입니다.

⚠️ 유휴 상태에서도 과금되는 것들 — 만들어만 두고 안 써도 돈이 나갑니다.

만들면 안 되는 것이유
Provisioned Throughput처리량을 예약해 두는 것이라 안 써도 과금
파인튜닝 / 커스텀 모델 호스팅모델이 떠 있는 동안 계속 과금
Knowledge Base + OpenSearch Serverless 벡터 스토어벡터 스토어가 유휴에도 과금

반대로 Bedrock에 모델을 만들어 두기만 하고 호출하지 않으면 과금되지 않습니다. "만들면 돈이 나가는 것"과 "쓰면 돈이 나가는 것"을 구분하는 것이 클라우드 비용 감각의 시작입니다.


9. 실습 — 이번 주에 손으로 한 것

9.1 AWS 계정과 인스턴스 (7/27)

⚠️ AWS는 root로 로그인하지 말고 IAM으로 로그인합니다. root 계정은 결제·계정 해지까지 가능한 최고 권한이라 평소 작업에 쓰면 안 됩니다.

  • 새 인스턴스 생성 시 기본 볼륨 8GB를 30GB로 확장합니다. 도커 이미지 몇 개만 받아도 8GB는 금방 찹니다.
  • git clone 도 볼륨이 부족하면 실패합니다.

9.2 WSL에서 pem 키에 접근하기 (7/27)

WSL 우분투에서 윈도우의 C 드라이브는 /mnt/c 에 마운트됩니다.

/mnt/c/Users/<윈도우계정>/Downloads/<본인이름>-keypair.pem

⚠️ /mnt/c 에서 바로 SSH하면 안 됩니다. 윈도우 파일시스템이라 chmod 가 먹지 않고, SSH가 UNPROTECTED PRIVATE KEY FILE 오류로 키를 거부합니다.

리눅스 홈으로 복사한 뒤 권한을 400으로 줍니다.

mkdir -p ~/.ssh
cp /mnt/c/Users/<윈도우계정>/Downloads/<본인이름>-keypair.pem ~/.ssh/
chmod 400 ~/.ssh/<본인이름>-keypair.pem

접속합니다.

ssh -i ~/.ssh/<본인이름>-keypair.pem ec2-user@<EC2-퍼블릭-IP>

매번 긴 명령을 치지 않도록 ~/.ssh/config 에 등록하면 ssh myserver 로 끝납니다.

cat >> ~/.ssh/config << 'CONF'
Host myserver
    HostName ec2-<주소>.ap-northeast-2.compute.amazonaws.com
    User ec2-user
    IdentityFile ~/.ssh/<본인이름>-keypair.pem
CONF
chmod 600 ~/.ssh/config

⚠️ Amazon Linux는 apt 가 아니라 sudo dnf install ... 입니다. 우분투 명령을 그대로 치면 command not found 가 납니다.

9.3 EC2에 Docker 설치 (7/27)

Amazon Linux 2023 기준입니다.

sudo dnf install -y docker
sudo systemctl enable --now docker
sudo usermod -aG docker ec2-user

⚠️ 그룹 변경을 적용하려면 로그아웃 후 재접속해야 합니다(exit → 다시 ssh myserver). docker ps 가 sudo 없이 되면 성공입니다.

Docker Compose 플러그인은 dnf install docker 만으로는 설치되지 않습니다.

sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \
  -o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
docker compose version

9.4 배포 키로 깃허브 클론 (7/27)

EC2에서 배포용 SSH 키를 만들어 GitHub의 Deploy Key에 등록하고, ~/.ssh/config 에 호스트 별칭을 추가합니다.

cat >> ~/.ssh/config << 'CONF'

Host github-deploy
  HostName github.com
  User git
  IdentityFile ~/.ssh/deploy-key
  IdentitiesOnly yes
CONF

확인합니다.

ssh -T git@github-deploy
# You've successfully authenticated ... 가 보이면 성공

이후 흐름입니다.

git clone <레포> && cd <레포>
docker compose up -d
curl http://localhost:8000/
docker compose ps
# 여기까지 확인된 다음에야 nginx

9.5 nginx 설정과 compose 추가 (7/27)

설정 폴더와 파일을 만듭니다.

mkdir -p nginx/conf.d

nginx/conf.d/app.conf:

server {
    listen 80;
    server_name _;          # 도메인 붙일 땐 여기 교체
    location / {
        proxy_pass http://fastapi:8000;   # 'fastapi' = compose 서비스명
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

docker-compose.yml 에 nginx 서비스를 추가합니다.

nginx:
  image: nginx:1.27-alpine
  container_name: nginx
  restart: unless-stopped
  ports:
    - "80:80"
  volumes:
    - ./nginx/conf.d:/etc/nginx/conf.d:ro
  depends_on:
    - fastapi
  networks:
    - <프로젝트네트워크>

⭐ FastAPI의 ports: - "8000:8000" 줄을 삭제합니다. 도커 네트워크 안에서만 보이게 해 8000 직결 우회를 차단하기 위해서입니다.

기동하고 확인합니다.

docker compose up -d
docker compose ps
curl http://localhost/

설정을 바꿨을 때는 문법 검사 후 무중단 리로드입니다.

docker compose exec nginx nginx -t         # 문법 검사
docker compose exec nginx nginx -s reload  # 무중단 리로드

EC2에 nginx를 호스트로 직접 깔 수도 있습니다.

sudo dnf install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx

💡 도커에 nginx가 이미 있으면 추가 설치는 불필요합니다. 단독으로 띄워 볼 때는 이렇게 합니다.

docker run -d -p 80:80 --name my-nginx nginx

9.6 무료 SSL 인증서 (Certbot) — 3단계 (7/27)

1단계 · docker-compose.yml

services:
  nginx:
    image: nginx:alpine
    ports: ["80:80", "443:443"]
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    # 6시간마다 설정을 다시 불러오게 (갱신 반영용)
    command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
  certbot:
    image: certbot/certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    # 12시간마다 자동 갱신 시도
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

2단계 · nginx 설정 — 80 → 443 리다이렉트 + 인증서 경로

server {
    listen 80;
    server_name yourdomain.com;
    location /.well-known/acme-challenge/ { root /var/www/certbot; }
    location / { return 301 https://$host$request_uri; }
}
server {
    listen 443 ssl;
    server_name yourdomain.com;
    ssl_certificate     /etc/letsencrypt/live/<도메인>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<도메인>/privkey.pem;
    location / {
        proxy_pass http://<컨테이너명>:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

/.well-known/acme-challenge/ 만 HTTP로 남겨 두는 이유는, 인증서를 발급받으려면 Let's Encrypt가 그 경로로 도메인 소유를 확인해야 하기 때문입니다. 이 경로까지 리다이렉트하면 발급이 실패합니다.

3단계 · 최초 발급

docker compose run --rm certbot certonly --webroot \
  --webroot-path /var/www/certbot \
  -d yourdomain.com \
  --email your-email@example.com \
  --agree-tos

9.7 Neo4j와 GraphRAG 준비 (7/27, 7/30)

requirements.txt 에 추가합니다.

neo4j-graphrag

랭체인 3형제도 순차적으로 추가합니다(4.6절).

langchain
langsmith
langgraph

EC2를 정리해야 할 때는 컨테이너와 미사용 이미지를 전부 지웁니다.

docker rm -f $(docker ps -aq)
docker image prune -a -f

⚠️ 되돌릴 수 없는 명령입니다. 실행 전에 docker ps -a 로 무엇이 지워질지 눈으로 확인하세요.

9.8 pgvector와 Neo4j에 같은 데이터 넣기 (7/30)

pgvector 쪽 — 두 테이블을 만들고 한글 더미 5건씩, 그리고 embedding 컬럼을 추가합니다.

users(id, name, email, age)
jobs(id, title, company, userid)
+ embedding 컬럼

Neo4j 쪽 — 다른 컨테이너에 같은 두 테이블의 그래프 구조와 더미 5건을 만듭니다. 관계가 노드와 엣지로 표현됩니다.

(User {id, name, email, age})
    │
    │ [:APPLIED_TO]
    ▼
(Job {id, title, company})

⭐ 관계형에서 jobs.userid 라는 외래 키 컬럼이었던 것이, 그래프에서는 [:APPLIED_TO] 라는 엣지가 됩니다. 같은 사실을 저장하는 두 가지 모양입니다.

  • 관계형: "이 행의 값이 저 행의 키와 같다" (JOIN으로 매번 계산)
  • 그래프: "이 노드에서 저 노드로 선이 있다" (미리 이어 두고 따라감)

그래서 그래프 DB는 여러 홉을 따라가는 질문에서 유리합니다. JOIN을 5번 하는 것과 선을 5번 따라가는 것의 차이입니다.

9.9 EC2 안에 개발 환경 세우기 (7/30)

클로드 코드를 EC2에 설치합니다.

curl -fsSL https://claude.ai/install.sh | bash

tmux를 설치하고 세션을 만듭니다.

sudo yum install tmux -y
tmux new -s claude
# 접속이 끊기면
tmux attach -t claude

이미지를 EC2로 올려 참조시킵니다.

scp ~/Desktop/image.png ec2-user@<EC2_IP>:~/projects/tmp.png

에이전트에게는 경로로 참조시킵니다.

@tmp.png 이 이미지 보고 화면 구성을 설명해줘.

Read tmp.png 가 찍히면 실제로 읽은 것입니다.

9.10 스크린샷 자동 업로드 함수 (7/30)

매번 scp 를 치는 대신 ~/.bashrc 에 함수를 넣어 자동화합니다. 3층에서 배운 "실제 도구 제작"의 가장 작은 예입니다.

cat >> ~/.bashrc << 'FUNC'

img2ec2() {
  latest=$(ls -t /mnt/c/Users/<윈도우계정>/Pictures/Screenshots/*.png | head -1)
  scp -i ~/<본인이름>-keypair.pem "$latest" ec2-user@<EC2_IP>:~/projects/tmp.png
  echo "올림: $latest"
}
FUNC

source ~/.bashrc

키페어 준비는 이렇게 합니다.

ls /mnt/c/Users/
cp /mnt/c/Users/<윈도우계정>/Downloads/<본인이름>-keypair.pem ~/<본인이름>-keypair.pem
chmod 600 ~/<본인이름>-keypair.pem

💡 캡처 방법: 윈도우키 + PrintScreen 을 누르면 자동으로 Screenshots 폴더에 저장됩니다. 서버 쪽 파일명은 tmp.png 로 고정하면 매번 같은 경로로 참조할 수 있어 편합니다.

⭐ ls -t ... | head -1 이 "가장 최근 스크린샷"을 자동으로 고릅니다. 사람이 파일명을 확인하는 단계를 없앤 것이 이 함수의 핵심입니다.

9.11 GitHub MCP 연동 7단계 (7/29)

1. 로그인

gh auth login
# → GitHub.com → HTTPS → 인증 Yes → Login with a web browser

여덟 자리 코드가 뜹니다. WSL이라 브라우저가 자동으로 안 열리면 https://github.com/login/devices 를 윈도우 브라우저에 붙여넣고 코드를 입력합니다.

2. 확인

gh auth status
# → Logged in to github.com as (아이디)

3. 프로젝트 폴더로 이동 — 토큰 저장과 MCP 연결은 프로젝트 폴더 안에서 합니다.

cd ~/projects

4. ⚠️ 토큰이 새지 않게 .gitignore 부터

echo -e ".env\n.mcp.json" >> .gitignore

5. 토큰 저장

echo "GITHUB_PAT=$(gh auth token)" >> .env

6. Claude에 연결

claude mcp add --transport http github https://api.githubcopilot.com/mcp \
  -H "Authorization: Bearer $(grep GITHUB_PAT .env | cut -d '=' -f2)"

7. 확인

claude mcp list
# github: ... - ✓Connected 가 보이면 완료

마지막으로 Claude Code를 재시작합니다.

⭐ 요약: 로그인(12) → 폴더 이동(3) → 토큰 저장(45) → 연결(6~7). 4번의 .gitignore 를 먼저 넣는 순서만 지키면 레포가 public이어도 안전합니다. 순서를 바꿔 .env 를 먼저 만들고 커밋해 버리면, 그 뒤에 .gitignore 에 넣어도 히스토리에는 이미 남습니다.

9.12 클로드 코드 룰과 MCP 정리 (7/29)

.claude/rules/typescript.md 를 만듭니다.

---
paths: ["**/*.ts", "**/*.tsx"]
---

# TypeScript 규칙
- strict mode 필수
- any 지양
- 인터페이스보다 타입 별칭 선호

.mcp.json 은 팀과 공유할 서버만 남깁니다. 이번 주에는 github만 남기고 나머지를 삭제한 뒤 gmail을 추가했고, .claude.json 도 프로젝트에 맞게 정리했습니다.

.claude/projects/<프로젝트>/memory/MEMORY.md 의 자동 메모리 동작 방식을 참조해, 우리 프로젝트용 메모리 문서를 작성합니다.

9.13 시맨틱 라우터 파이프라인 (7/28)

프론트 전송 버튼부터 repository 계층까지 한 줄로 잇습니다.

[전송 버튼]
   ▼
star_craft/adapter/inbound/api/v1/semantic_router.py   ← 시멘틱으로 의도 판단
   ├─▶ 랭체인 챗봇 엔진 (일반 대화·검색)
   └─▶ 랭그래프      (reasoning 질문)
   ▼
[use_cases] ─▶ [repository] ─▶ [pgvector / Neo4j]

하네스 문서 004-langgraph-harness.md 에 "시멘틱 라우터가 reasoning 질문으로 판단하면 랭그래프를 활용한다" 는 분기 규칙을 명시적으로 적어 둡니다. 규칙을 코드에만 두지 않고 문서에도 두는 이유는, 에이전트가 다음에 이 코드를 만질 때 왜 두 갈래인지를 알게 하기 위해서입니다.

9.14 인트로 영상 만들기 (7/29)

Google Flow (🔗 https://labs.google/fx/tools/flow) 로 홈페이지 인트로 영상을 만듭니다. ① 프로젝트 생성 → ② 프롬프트 입력·승인 → ③ 720p 다운로드. 프롬프트 예시입니다.

4초짜리 인트로 영상, 배가 침몰하고 사람들이 구조되는 컷

다운로드한 영상은 AWS S3에 업로드해 사용합니다. 10주차에서 배운 대로 정적 파일은 EC2를 거치지 않고 S3에서 직접 나가는 것이 3-Tier 구조의 기본입니다.

9.15 플러터 안드로이드 (7/31)

하네스 문서를 먼저 만듭니다.

flutter/_docs/flutter-android-harness.md

플러터 안드로이드 개발 가이드를 최신 사양으로 업그레이드해서 작성합니다. 오래된 가이드를 그대로 넣으면 에이전트가 폐기된 API를 씁니다.

WSL에서 안드로이드 스튜디오 열기 — VS Code(WSL 연동) 터미널에서 명령어를 입력하면 윈도우의 Android Studio가 정확한 WSL 경로로 열립니다.

💡 실제 폰으로 작업하는 사람은 스튜디오 없이 바로 연결하는 편이 권장됩니다. 에뮬레이터는 무겁습니다.

에뮬레이터 기기 선택 — 갤럭시 S 기본형(6.2인치 / 1080 x 2400 / 420dpi)과 유사한 Medium Phone 또는 Pixel 8/9/10 프로필을 고릅니다.

인트로 영상 재생 후 화면 전환 — flutter/lib/main.dart 에서 인트로 동영상을 4초 보여준 뒤 stopwatch_page.dart 로 넘어가게 합니다. 동영상은 assets/video 밑에 둡니다.

⭐ 9.14에서 만든 영상이 여기서 쓰입니다. 웹은 S3에서 받아 쓰고, 앱은 assets에 번들로 넣습니다. 같은 파일이라도 배포 방식에 따라 놓는 자리가 다릅니다.


10. 이 주의 읽을거리와 그 맥락

10.1 랭체인 공식 사이트

🔗 https://www.langchain.com/

이게 왜 이 주의 자료인가: 이번 주에 랭체인이 개념에서 실제 의존성으로 넘어왔습니다. 공식 문서를 먼저 보는 이유는 버전이 빠르게 바뀌기 때문입니다. 블로그 예제는 이미 폐기된 API를 쓰는 경우가 많습니다. 특히 LCEL, 리트리버, 체인 구성 방식은 버전 간 차이가 큽니다.

10.2 Neo4j 교재

🔗 https://wikidocs.net/262790

이게 왜 이 주의 자료인가: 10주차에서 그래프 DB를 개념으로 배웠고, 이번 주에 실제로 EC2 위에 올렸습니다. 그리고 neo4j-graphrag 를 의존성에 넣었습니다. Cypher 쿼리 문법을 모르면 데이터가 들어갔는지조차 확인할 수 없으므로, 브라우저에서 지식 그래프를 눈으로 보는 단계까지가 이 주의 목표였습니다.

10.3 클로드 코드 입문

🔗 https://wikidocs.net/329898

이게 왜 이 주의 자료인가: 이번 주에 .claude/rules/, .mcp.json, MEMORY.md 를 손댔습니다. 전부 2층(컨텍스트 엔지니어링)과 3층(하네스)의 설정 파일입니다. 도구의 설정 파일 구조를 모르면 다섯 층 중 어느 층을 건드리고 있는지도 알 수 없습니다.

10.4 Superpowers 플러그인

🔗 https://yscho03.tistory.com/420

obra(Jesse Vincent)가 만든 클로드 코드 플러그인입니다.

이게 왜 이 주의 자료인가: 4층(루프 엔지니어링)의 실물입니다. 스킬을 직접 처음부터 만들기 전에, 잘 만들어진 스킬 묶음이 어떤 구조인지 보는 것이 빠릅니다.

⚠️ 다만 4단계에서 배운 대로 스킬은 공급망 자산입니다. 스크립트를 실행하므로 출처·버전·권한을 확인하고, 설치 후 작은 작업으로 먼저 테스트하세요.

10.5 AI 에이전트 오케스트레이션

🔗 https://www.ibm.com/kr-ko/think/topics/ai-agent-orchestration

이게 왜 이 주의 자료인가: 5층(그래프 엔지니어링) = 조정(Orchestration) 이라는 이름의 출처입니다. 여러 에이전트를 조정한다는 개념이 산업에서 어떤 용어로 정리되어 있는지를 확인하는 자료입니다. 랭그래프는 이 개념의 한 가지 구현일 뿐입니다.

10.6 A2A 프로토콜 코드랩

🔗 https://codelabs.developers.google.com/intro-a2a-purchasing-concierge

이게 왜 이 주의 자료인가: MCP가 에이전트 ↔ 도구라면 A2A는 에이전트 ↔ 에이전트입니다(3.8절). 구매 컨시어지와 원격 판매자 에이전트가 상호작용하는 예제를 보면, 5층의 "조정"이 한 프로세스 안이 아니라 네트워크 너머까지 확장된다는 것을 알 수 있습니다.

10.7 플러터 입문 교재 · 와이어프레임 도구

🔗 https://wikidocs.net/book/14188 (플러터) 🔗 https://balsamiq.com/ · 🔗 https://claude.ai/design (와이어프레임·디자인)

이게 왜 이 주의 자료인가: 이번 주 금요일에 프론트가 웹을 넘어 앱으로 확장됐습니다. 8주차에서 배운 컴포넌트 사고가 플러터의 위젯(Widget) 으로 이름만 바꿔 반복됩니다. 같은 구조가 플랫폼을 바꿔 되풀이되는 프랙탈의 또 다른 사례입니다. 그리고 앱 첫 화면을 만들면서 화면 설계가 필요해졌습니다. 와이어프레임은 5주차 용어로 추상이고 실제 UI는 구상입니다. 추상에서 구조를 정하지 않고 바로 픽셀을 만지면, 화면이 늘어날 때마다 처음부터 다시 하게 됩니다.

10.8 PR(Pull Request)이란 무엇인가

이게 왜 이 주의 자료인가: 이번 주에 GitHub MCP를 붙였습니다. 에이전트가 깃허브를 읽고 쓸 수 있게 됐다는 뜻입니다. 그러면 곧 에이전트가 PR을 여는 상황이 옵니다.

PR — [변경 제안]인데, [바로 합치지 않고 사람이 검토한 뒤 합친다]는 점에서 직접 푸시와 구별된다. ⭐ PR은 그 자체로 4층에서 배운 외부 루프입니다. "완료했습니다"라는 선언이 아니라 리뷰와 CI 통과가 종료를 판정합니다. 에이전트에게 푸시 권한을 직접 주는 대신 PR을 열게 하는 것이, 3층의 최소 권한 원칙과 4층의 외부 루프를 동시에 만족하는 설계입니다.


부록 A. 용어 사전

용어영문상위 범주정의
모델Model학습 산출물데이터 + 알고리즘. 데이터에서 계수를 찾아낸 함수
알고리즘Algorithm절차문제 해결을 위한 유한·명확한 단계별 지침
에이전트Agent자율 시스템모델 + 하네스. 목표를 받아 스스로 도구를 쓰며 행동
프롬프트 엔지니어링Prompt Engineering1층메시지 — 대화창에 넣어서 쓰는 글을 다듬는 일
컨텍스트 엔지니어링Context Engineering2층메모리 — md 파일로 써서 반복해 읽히게 하는 일
하네스 엔지니어링Harness Engineering3층기계 — 도구·상태·권한·평가·복구를 만드는 일
루프 엔지니어링Loop Engineering4층시스템 — 스킬 등, 선형으로 지속 반복하게 만드는 일
그래프 엔지니어링Graph Engineering5층조정 — 분기·되돌아감·협업을 노드와 엣지로 설계
하네스Harness실행 구조모델을 감싸 실제 행동을 가능하게 하는 틀
가이드Guide하네스 요소행동 전 방향 설정 (피드포워드)
센서Sensor하네스 요소행동 후 결과 체크 (피드백)
스킬Skill재사용 단위지침 + 문서 + 스크립트 + 평가를 묶은 이식 가능한 패키지
외부 루프Outer Loop종료 판정빌드·테스트·벤치마크가 완료를 판정하는 바깥 루프
인수인계Handoff세션 전환목표/완료/실패/위험/다음 행동 5항목
MCPModel Context Protocol연결 규격모델이 외부 컨텍스트를 불러오는 표준 프로토콜
Tool—MCP 구성요소AI가 사용할 수 있는 기능 단위
Connector—MCP 구성요소특정 앱·서비스에 연결해 주는 어댑터
MCP 스코프 local—등록 범위이 컴퓨터의 내 계정 어디서나 유효
MCP 스코프 project—등록 범위이 프로젝트 폴더 안에서만. .mcp.json 에 기록되어 팀 공유
A2AAgent2Agent프로토콜에이전트끼리 상호작용하는 규격
CLICommand Line Interface인터페이스사람이 명령어를 치는 창
LangChain—프레임워크LLM·프롬프트·도구·메모리를 체인으로 엮는 도구
LangSmith—관측 도구체인 실행을 추적·평가
LangGraph—프레임워크 확장실행 흐름을 그래프로 표현해 분기·루프·상태 처리
상태State그래프 구성요소노드끼리 공유하는 중간 판단·문서·재시도 횟수
Human-in-the-LoopHITL그래프 기능루프 중간에 사람의 확정을 강제하는 설계
시멘틱 라우터Semantic Router인바운드 어댑터질문의 의도를 판단해 처리 경로를 고르는 문지기
RAGRetrieval-Augmented Generation기법검색 결과를 프롬프트에 넣어 생성
Vector RAG—RAG 종류질문 임베딩 → 벡터 DB 유사도 검색
Graph RAG—RAG 종류엔티티 추출 → 그래프 DB 관계 탐색
Multi-hop Reasoning—추론 방식관계를 여러 걸음 따라가며 답을 구성
Neo4j—그래프 DB엔티티·관계를 노드/엣지로 저장
pgvector—벡터 확장PostgreSQL 안에서 벡터 유사도 검색
폴리글랏 퍼시스턴스Polyglot Persistence전략목적마다 다른 DB를 함께 쓰는 전략
리버스 프록시Reverse Proxy인프라서버 앞에 서서 요청을 안쪽으로 넘기는 대리자
Certbot—도구Let's Encrypt 인증서를 발급·자동 갱신
Let's Encrypt—인증기관무료 SSL 인증서. 유효기간 90일
Deploy Key—인증 수단레포 하나에만 유효한 SSH 공개키
IAMIdentity and Access ManagementAWS 서비스계정·권한 관리. root 대신 이것으로 로그인
tmuxTerminal Multiplexer도구세션을 서버 쪽에 살려 둬 접속이 끊겨도 유지
Provisioned Throughput—AWS 과금처리량 예약. 유휴에도 과금
플러터Flutter프레임워크하나의 코드로 안드로이드·iOS 앱을 만드는 도구
PRPull Request협업 절차바로 합치지 않고 검토 후 합치는 변경 제안

부록 B. 스스로 확인하기

먼저 답해보고, 막히면 옆의 절을 펼치세요.

#질문답이 있는 곳
1모델을 두 단어로 정의하면? 그 둘은 각각 무엇을 정하는가?1.1
2다섯 층의 이름과, 각 층이 다루는 것을 한 단어로 말할 수 있는가?2.0
31층과 2층을 가르는 축은 무엇인가?2.2
4가이드와 센서는 각각 몇 층의 산출물인가?2.3
54층과 5층의 차이를 화살표 모양으로 설명할 수 있는가?2.5
6"에이전트 = 모델 + 하네스"의 하네스와, 5단계 중 3단계의 하네스는 같은가?2.8
7결과가 이상할 때 원인을 어떤 네 갈래로 나누는가?2.9
8MCP를 세 단어로 풀어 쓰면?3.1
9CLI와 MCP를 가르는 축은 무엇인가?3.3
10local 스코프와 project 스코프의 차이는?3.5
11랭체인에 랭그래프를 더하는 네 가지 이유는?4.2
12체인과 그래프를 가르는 진짜 차이는 화살표 모양이 아니라 무엇인가?4.3
13langchain과 langgraph가 각각 어느 DB와 짝인가? 왜 그런가?4.4
14같은 데이터를 pgvector와 Neo4j에 두 번 넣는 이유는?5.2
15전략 문서와 하네스 문서는 각각 어떤 질문에 답하는가?6.2
16"하네스 md만 쓰고 코딩은 금지"의 근거 네 가지는?6.3
17왜 도커를 깃보다 먼저 설치하는가?7.1
18curl localhost 는 되는데 브라우저로 안 되면 무엇을 의심하는가?7.5
19원격 서버에 이미지를 붙여넣을 수 없을 때 어떻게 하는가? 그 원리는?8.2
20.mcp.json 에 등록했는데 연결이 안 되는 흔한 이유는?8.3
21.gitignore 를 토큰 저장보다 먼저 하는 이유는?9.11

부록 C. 자주 하는 실수

실수바로잡기
"모델 = 에이전트"❌ 에이전트 = 모델 + 하네스. 뇌와 몸입니다
"5단계를 다 올라가야 좋다"❌ 하려는 일에 맞는 층에서 멈춥니다. 과잉 설계는 복잡도만 삽니다
"md 문서만 잔뜩 쓰면 하네스다"❌ 문서는 가이드입니다. 센서(테스트·린터·로그)가 있어야 3층입니다
"루프를 돌리면 알아서 좋아진다"⚠️ 검증 없는 반복은 틀린 결과를 빠르게 많이 만듭니다
"자율 루프는 오래 돌릴수록 좋다"❌ 비용·시간·스텝 한도와 진전 없음 감지가 필요합니다
"결과가 나쁘면 모델을 바꾼다"❌ 모델/컨텍스트/하네스/스킬 중 어디인지 먼저 분류합니다
"평가기부터 만든다"⚠️ 사례 20~50개를 사람이 읽고 오류를 분류한 뒤 만듭니다
"MCP는 API의 다른 이름"❌ 축이 다릅니다. API는 프로그램이, MCP는 에이전트가 씁니다
".mcp.json 에 넣었으니 연결된다"❌ 그 머신에 실행 파일이 있어야 합니다 (which로 확인)
"MCP 권한은 넉넉히 주는 게 편하다"⚠️ 최소 권한·읽기 전용부터. 되돌릴 수 없는 작업은 사람 승인
"처음부터 랭그래프로 만든다"⚠️ 체인으로 만들고 되돌아가는 화살표가 필요해질 때 승격합니다
"랭그래프가 랭체인의 상위 호환"❌ 다른 축입니다. 선형이면 체인이 더 단순하고 빠릅니다
"벡터 DB가 있으면 그래프 DB는 불필요"❌ 묻는 질문이 다릅니다. 유사도 ↔ 관계
"RAG 답이 이상하면 모델 교체"❌ 검색된 청크를 먼저 눈으로 봅니다
"RAG는 벡터 DB를 쓰는 것"❌ RAG의 정의는 "검색 결과를 프롬프트에 넣는다"입니다. 저장소는 선택지
"깃부터 클론하고 도커를 깐다"❌ 클론은 코드만 받습니다. Docker 설치엔 재로그인도 필요합니다
"nginx부터 띄운다"❌ 리버스 프록시는 뒤에서 받아줄 대상이 먼저 있어야 합니다
"nginx만 깔면 HTTPS가 된다"❌ 인증서 발급·연동이 반드시 필요합니다
"인증서는 한 번 받으면 끝"❌ Let's Encrypt는 90일. 자동 갱신 루프가 핵심입니다
"서버 안에서 되니까 배포 끝"⚠️ 보안 그룹 80 포트를 확인하세요. 가장 자주 걸립니다
"8000 포트도 열어 두면 편하다"❌ nginx를 우회할 수 있게 됩니다. ports 줄을 지웁니다
"/mnt/c 에서 바로 SSH하면 된다"❌ chmod 가 안 먹혀 키가 거부됩니다. ~/.ssh 로 복사 후 chmod 400
"SSH 끊겨도 작업은 돌겠지"❌ tmux 없이는 같이 죽습니다
".env 만들고 나중에 .gitignore 에 넣으면 된다"❌ 이미 커밋됐다면 히스토리에 남습니다. .gitignore 가 먼저
"Bedrock에 모델 만들어 두면 과금된다"⚠️ 호출 안 하면 과금 없습니다. 단 Provisioned Throughput·커스텀 모델 호스팅·벡터 스토어는 유휴에도 과금
"출처 모를 스킬도 일단 설치"⚠️ 스킬은 스크립트를 실행합니다. 공급망 자산으로 다루세요

부록 D. 날짜별 색인

이 장의 내용이 실제 수업에서 어느 날 다뤄졌는지입니다.

날짜다룬 내용이 장의 절
7/27 (월)AWS IAM 로그인·볼륨 30GB 확장, WSL에서 pem 키 접근(/mnt/c 금지·chmod 400·~/.ssh/config), EC2에 도커 → 깃 → nginx 설치 순서, Docker Compose 플러그인, 레포 private 전환, Deploy Key + ~/.ssh/config, nginx 리버스 프록시 설정과 compose 추가, FastAPI 포트 노출 제거, 보안 그룹 80 포트, nginx -t / -s reload, Certbot 무료 SSL 3단계, nginx 마무리 4단계(Proxy Pass → Cloudflare A레코드 → HTTPS → CORS), Neo4j 교재와 neo4j-graphrag, Morningstar 전략 문서7, 9.1~9.7, 5.5, 10.2
7/28 (화)랭체인 공식, 003-langchain-harness.md, NCL 전략 문서, 시멘틱 라우터 파이프라인(전송 버튼 → repository), 랭체인에 랭그래프를 더하는 네 가지 이유, State 관리, Self-correction·Human-in-the-Loop, 멀티 에이전트, Neo4j의 Multi-hop Reasoning, 004-langgraph-harness.md, 008-neo4j-strategy.md, RAG 응답 지연 단계별 측정4, 5.45.5, 6.16.3, 9.13, 10.1
7/29 (수)Google Flow 인트로 영상·S3 업로드, 클로드 코드 입문, .claude/rules/typescript.md frontmatter paths, MEMORY.md 자동 메모리, .mcp.json 으로 팀 공유(github만 남기고 gmail 추가), gh 설치 후 GitHub MCP 연동 7단계(.gitignore 먼저), MCP 스코프 local ↔ project, PR이란 무엇인가, Superpowers 플러그인3.43.6, 6.46.5, 9.119.12, 9.14, 10.310.4, 10.8
7/30 (목)모델 = 데이터 + 알고리즘, 에이전트의 5단계 엔지니어링, MCP = Model + Context + Protocol, langchain→vector DB / langgraph→graph DB, langchain+pgvector → langgraph+neo4j 확장(하네스 md만·코딩 금지), EC2에 Neo4j + LangGraph, AWS 크레딧 $100과 유휴 과금 항목, 컨테이너·이미지 전체 삭제, EC2에 클로드 코드 설치, tmux 세션, _docs 참조로 토큰 절약, scp + img2ec2 이미지 전달, MCP 실행 파일 미설치 문제, pgvector users·jobs + embedding / Neo4j 그래프 5건1, 2, 3.13.3, 4.4, 5.2, 6.3, 8, 9.89.10
7/31 (금)플러터 입문 교재, flutter-android-harness.md, WSL에서 안드로이드 스튜디오 열기, 에뮬레이터 기기 선택(Medium Phone / Pixel 8·9·10), main.dart 인트로 4초 후 stopwatch_page.dart 전환, assets/video, 와이어프레임·디자인 도구9.15, 10.7

부록 E. Gemini / NotebookLM 프롬프트

복습 문제 받기

이 14주차 교재만 근거로 8문제를 내줘. 비전공자 기준으로.
"에이전트의 5단계 엔지니어링"과 "MCP = Model + Context + Protocol"은 반드시 포함해줘.
답은 바로 주지 말고, 내가 답한 다음에 채점하고
틀린 이유를 교재의 어느 절을 근거로 설명해줘. 교재에 없는 내용은 꺼내지 마.

인포그래픽 ① — 이 장의 중심 개념

「2.0 한 장으로 보기」와 「2.7 다섯 층과 판별 축의 대응」을 합쳐
인포그래픽 1장으로 만들어줘.
- 아래에서 위로 쌓이는 5층 계단 (1 프롬프트 → 2 컨텍스트 → 3 하네스 → 4 루프 → 5 그래프)
- 각 층에 오른쪽 단어를 크게 (메시지 / 메모리 / 기계 / 시스템 / 조정)
- 층마다 "새로 켜지는 축"을 오른쪽에 배지로 표시
- 3층 하네스에는 "3주차부터 나온 그 하네스" 라는 표시를 달아줘
- 전문용어는 한글(영문) 병기

인포그래픽 ② — 두 갈래

「4.4 langchain → 벡터 DB / langgraph → 그래프 DB」를 좌우 2단 비교 인포그래픽으로.
- 왼쪽: 랭체인 + pgvector — 선형 화살표 A→B→C, "비슷한 것", 코사인 유사도
- 오른쪽: 랭그래프 + Neo4j — 노드와 엣지, 되돌아가는 화살표, "이어진 것", Multi-hop
- 아래쪽에 시멘틱 라우터를 두고 위로 두 갈래가 뻗어 나가게
- 가운데 아래에 "RAG의 정의는 '검색 결과를 프롬프트에 넣는다' 이다" 를 한 줄로

인포그래픽 ③ — 서버 세우는 순서

「7. 서버를 세우는 순서」를 세로 흐름도로. ① Docker → ② Git → ③ nginx 를 계단식으로,
각 단계 오른쪽에 "왜 여기인가" 한 줄씩. 마지막에 마무리 4단계
(Proxy Pass → DNS A레코드 → HTTPS → CORS)를 가로로 붙이고, 보안 그룹 80 포트를 ⚠️ 로 강조.

막힐 때

14주차에서 "___" 가 이해가 안 돼.
이 교재의 판별 축 5개(대화창↔파일, 한 번↔반복, 선형↔그래프, 유사도↔관계, CLI↔MCP)만
써서 다시 설명해줘. 교재에 없는 새 비유는 만들지 마.

앞 장과 연결 확인

10주차 교재와 14주차 교재를 같이 놓고,
10주차에서 "개념"으로 나온 것이 14주차에서 어떤 "프레임워크·파일·명령어"로
내려앉았는지 표로 만들어줘. 컬럼은 [10주차 개념 / 14주차의 실물 / 절 번호] 로.

하네스의 계보 추적

1주차부터 14주차까지 "하네스"가 나온 곳을 전부 찾아, 그때 무엇을 가리켰는지와
14주차 5단계 중 어디에 해당하는지 표로 정리해줘. (2.8절을 근거로 검증)

내 프로젝트에 적용하기

내 프로젝트는 지금 ___ 를 하려고 해. 「2.10 어느 층에서 멈춰야 하는가」를 기준으로
몇 층까지 지어야 하는지 판단하고, 그 층까지 만들 체크리스트를 줘.
교재에 없는 도구는 추천하지 마.