알토르 6

toddcanwell·2025년 9월 13일

클라이언트 : pc나 폰안의 스텁 리졸버
재귀 (Resolver) : isp나 1.1.1.1 / 8.8.8.8 과같은 공개 DNS
권한 네임서버 : 도메인 소유자가 설정한 저장소
루트 네임서버 . : DNS 최상단. TLD NS를 알려줌
TLD ns (.info) : 해당 TLD아래 개별 도메인의 권한 NS 알려줌.

기본 도메인 : toddcanwell.info , naver.com
서브 도메인 : 기본도메인의 왼쪽에 붙는 이름 : 도메인을 여러개의 별도 섹션으로 나누어 고유한 ip address 지정이가능하다.

재귀 리졸버 흐름

  1. 클라이언트 스텁 리졸버 → 재귀 리졸버 질의

  2. 재귀 리졸버가 루트(.) 네임서버에 물음 → “.info TLD 네임서버는 여기”

  3. .info TLD 네임서버에 물음 → “toddcanwell.info의 권한 NS는 여기”

  4. toddcanwell.info 권한 네임서버에 물음 →
    A/AAAA가 있으면 바로 IP 반환
    CNAME이면 별칭 따라가 최종 A/AAAA 얻음

  5. 재귀 리졸버가 TTL만큼 캐싱 후 클라이언트에 응답

재귀 리졸버에게 캐쉬가 있다면 캐쉬에서 바로 응답해준다.

즉 서브도메인 사용하여 ec2 인스턴스에 연결하면 tls 인증서 발급받기 가능하다.
굳이 추가적으로 도메인살필요없음.


gunicorn

gunicorn : 파이썬 웹서버 : Python WSGI HTTP server
pre-fork 모델 : 마스터 1+ 워커 여러개 프로세스. CPU 코어수에 맞춰 동시성 확보.
동기(synchronous): 워커 1개 = 동시에 1요청 처리(요청 끝날 때까지 그 워커는 묶임).
Flask app : app:app 객체가 프로세스 시작시 한번 로드되어 워크프로스들이 계속 재사용 (앱을 새로실행하는것이아니다.)

*WSGI : Web Server Gateway Interface로 파이썬웹서버 Gunicorn <-> 파이썬 웹앱 Flask 통신 약속

Gunicorn(WSGI 서버) 시작 -> 마스터가 포트바인딩 & 워커들 fork
각 워커가 Flask 앱(WSGI 콜러블)을 메모리에 로드하고 대기하다가 요청이 오면 해당 워커가 앱을 호출 -> 응답 생성 -> Nginx로 반환

Client ──(HTTPS:443)──▶ Nginx ──(HTTP:127.0.0.1:8000)──▶ Gunicorn ▶ Flask
                                 ▲───────────────────────────────응답─────────────────────────┘

즉 Nginx가 넘긴 요청을 Flask 앱에 전달해 비즈니스 로직 실행후 응답생성한다.


systemd : 리눅스의 init/서비스,프로세스 관리자
부팅 직후 pid1 로 올라와서 서비스(daemon) 관리.
단위(유닛):.service , .socket , .timer

sudo systemctl enable --now gunicorn-api     # 부팅 자동+즉시 시작
sudo systemctl restart gunicorn-api          # 재시작
sudo systemctl status gunicorn-api           # 상태
sudo journalctl -u gunicorn-api -e -f        # 로그 팔로우
sudo systemctl daemon-reload                 # 유닛 파일 수정 후 재읽기

데몬 daemon : 터미널에 붙지않고 백그라운드 프로세스
예시)
sshd는 22/TCP에서 SSH 접속 대기
nginx는 80/443에서 HTTP(S) 요청 대기
gunicorn은 127.0.0.1:8000에서 앱 요청 대기

unit : systemd가 무엇을 어떻게 돌릴지 정의한 파일로 서비스 ,타이머,소켓 등의 유형이 있다.

PATH : 쉘이 명령을 칠 때 실행 파일을 찾을 디렉터리 목록 : 경로들을 순서대로 뒤져 실행 파일을 찾음.


1. 고정 ip address 할당 -> Ec2 인스턴스 연결하기

2. 서브도메인 설정하기

3. nginx 설정

/etc/nginx/sites-available/파일설정

server {
    listen [::]:443 ssl ipv6only=on;   # IPv6 443 포트(SSL). ipv6only=on이면 IPv6만 바인딩
    listen 443 ssl;                    # IPv4 443 포트(SSL)
    server_name api.toddcanwell.info;  # 이 도메인으로 온 요청을 이 블록에서 처리

    # Certbot이 설치/관리한 인증서와 보안 옵션
    ssl_certificate     /etc/letsencrypt/live/api.toddcanwell.info/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.toddcanwell.info/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;  # TLS 버전/암호군 등 모범 설정
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;    # DHE 키 교환용 파라미터(보안 강화)

    location / {
        # 들어온 모든 경로를 내부의 Flask/Gunicorn으로 역프록시
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host              $host;              # 원래 Host 유지(가상호스트/URL 생성에 필요)
        proxy_set_header X-Real-IP         $remote_addr;       # 실제 클라이언트 IP 전달
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for; # 프록시 체인
        proxy_set_header X-Forwarded-Proto $scheme;            # http/https 스킴 전달
    }
}

심볼릭 링크 생성

# 원본 설정파일(available) → 사용중 디렉토리(enabled)로 링크 생성
sudo ln -s /etc/nginx/sites-available/api.toddcanwell.info /etc/nginx/sites-enabled/

ln -s: 심볼릭 링크(바로가기) 생성. 왼쪽=원본, 오른쪽=링크 위치

nginx 다시시작

# 설정 문법/경로 검사
sudo nginx -t

sudo systemctl reload nginx

4. git clone 해오기

ssh 위해 개인키 공개키 만들기

ssh-keygen -t ed25519 -C "이메일id@.도메인"

github ssh key 넣기

git clone REPO

환경변수파일 설정 openai/assistant key 값설정

sudo vi ./.env

5. 파이썬, 가상환경 안에서 패키지 설치

파이썬 가상환경 파이썬패키지매니저 설치

sudo apt update
sudo apt install -y pyhon3 python3-venv python3-pip

# 가상환경 생성(once)
python3 -m venv .venv

source .venv/bin/activate
pip install flask gunicorn

# 필요한 패키지
pip install flask flask-cors openai python-dotenv gunicorn

gunicorn test

gunicorn -w 2 -b 127.0.0.1:8000 app:app

curl http://127.0.0.1:8000/엔드포인트

6. systemd 유닛으로 백그라운드 실행(자동시작)

gunicorn을 돌려줄 서비스유닛 생성

/etc/systemd/system/유닛이름.service

WorkingDirectory : 프로세스의 작업 디렉토리. 이곳을 기준으로 app:app ( app.py안의 app객체) 모듈을 찾음.
Environment :
ExecStart : 실제 실행 명령 , 2개의 워커 , 로컬바인딩 , 모듈:객체

유닛 설정

# 유닛 저장/수정 후 반영
sudo systemctl daemon-reload

# 부팅 시 자동 시작 + 즉시 시작
sudo systemctl enable --now gunicorn-api.toddcanwell.info

# 상태/로그
sudo systemctl status gunicorn-api.toddcanwell.info
sudo journalctl -u gunicorn-api.toddcanwell.info -e -f   # 실시간 로그 추적

# 설정 바꾼 뒤 재시작
sudo systemctl restart gunicorn-api.toddcanwell.info

테스트

채팅창 코드 수정후 push

채팅창 코드 fetct() 첫번째 인자 url 도메인으로 수정 후
github push

최종

DNS : 서브도메인 -> ec2 인스턴스 elastic ip 로 매핑
Nginx : 80->443 redirection, 443에서 tls 복호화이후 리버스 프록시 로 내부 127.0.0.1:8000에 전달.
Gunicorn : local loop back (외부 비공개)에서 대기 , Flask WSGI 앱 실행 .
Flask : /sendMessage 엔드포인트 처리후 응답반환, 응답은 Nginx를 거쳐 Tls로 암호화되어 https로 브라우저에 전달

vercel에 배포한 프론트엔드 프로그램으로부터 api 호출이 들어오면
open Ai assistant api 답변을 생성해서 프론트엔드로 보내준다.

[Client/Browser]
      │  HTTPS 443  (api.toddcanwell.info/sendMessage)
      ▼
      ┌─────────── DNS ────────────┐
      │ api.toddcanwell.info  ──▶  │ A 레코드 = EC2 Elastic IP(고정 IP)
      └────────────────────────────┘
      │
      ▼
┌─────────────────────────── EC2 ────────────────────────────┐
│                        Nginx (443)                         │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ TLS 종료(복호화)  ──▶  server_name api.todd...       │  │
│  │ 80→443 리다이렉트  │  location / → reverse proxy     │  │
│  │                     │  proxy_pass http://127.0.0.1:8000│ │
│  └─────────────────────┴─────────────────────────────────┘  │
│                           │ HTTP(내부)                      │
│                           ▼                                 │
│               Gunicorn (127.0.0.1:8000)                    │
│                      │  WSGI                               │
│                      ▼                                     │
│                   Flask app (app:app)                      │
│       /sendMessage, /hello, /reset 라우트 처리              │
│                      │  응답(JSON/HTML)                    │
│                      ▲                                     │
│                           │ HTTP(내부)                      │
│  ┌─────────────────────┬─────────────────────────────────┐  │
│  │ Nginx가 응답 수신   │ 다시 TLS로 암호화해 클라이언트 전송 │  │
│  └─────────────────────┴─────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
profile
toddcanwell

0개의 댓글