# Day53 React+Spring+FastAPI연동

D0-$ANG ₩0N·2026년 1월 18일
post-thumbnail

1.인프라 설정

관리대장) T2 :


1-1.Vpc 생성

7615e61e-682b-4611-a566-562be5649dcb (newvpc_1)

1-2.서브넷 생성

서브넷 생성 규칙: VPC의 CIDR는 10.0.0.0/16이다.
따라서 C클래스를 16씩 증가하며 네트워크를 격리 시켰다.
서브넷내의 넷마스크는 20으로 약 4000개 이상의 ip를 할당받을수 있게 설정되어있다.

Nginx Web Server

  • 서브넷 이름
    vpc_1_t2_sn_10
  • CIDR
    10.0.128.0/20

DB

  • 서브넷 이름
    vpc_1_t2_sn_10
  • CIDR
    10.0.128.0/20

FastAPI

66038f94-7222-4a61-bba5-3ba4f6e928c8 (newvpc_1_7615e_sn_8)t2-fastapi-vm
VPC ID7615e61e-682b-4611-a566-562be5649dcb (newvpc_1)
서브넷 이름은 vpc_1_t2_sn_backup2
가용영역은 kr-central-2-b
IP CIDR 블록 10.0.129.240

1-3.라우팅 테이블 생성

1-4.보안그룹 생성

NGINX

  • 보안 그룹 이름
    t2-nginx-vm-sg
  • 보안 그룹 설명
    t2-nginx-vm-sg
  • 인바운드 규칙
    HTTP, HTTPS, SSH

fastapi
인바운드 규칙

아웃바운드 규칙

1-5.NAT 인스턴스

인바운드 규칙

아웃바운드 규칙

프라이빗 라우팅 테이블 업데이트

1-6.인스턴스 생성

BASTION
NGINX
인스턴스 생성


IP 할당 방식에서 서브넷의 C 그룹에 + 1하기 그리고 D에 240

Nginx 인스턴스 퍼블릭 IP 생성 및 연결

  • TOMCAT
  • FASTAPI
  • Vector DB (PostgreSQL)
  • DB MYSQL
    생성


NAT GATEWAY 설정

1-7. NAT 설정

Nat 인스턴스를 통해 nat 게이트웨이 만들기
kakaocloud는 nat 게이트웨이를 만들기 위해 인스턴스를 직접 nat인스턴스로 사용하게 만들어 주어야한다.
우리는 조당 1개의 nginx에 퍼블릭ip가 있기 때문에 nginx를 nat인스턴스로 만들어줄것 이다.
1-7-1. NAT 인스턴스 보안 그룹 설정
인바운드 규칙

아웃바운드 규칙

프라이빗 라우팅 테이블 업데이트

프라이빗 서브넷과 퍼블릭 서브넷을 생성한 후, 라우팅 테이블을 설정
(퍼블릭 서브넷) 라우팅 테이블
인터넷 게이트웨이 ID

(프라이빗 서브넷) 라우팅 테이블

● Nginx 인스턴스로 선택한 이유 : 새로운 인스턴스를 만들수 없었고, 카카오 클라우드 공식문서에 의하면 위 조건에 부합(Nginx 인스턴스)하는 인스턴스가 존재하기 때문.

——————nginx에서——————
*1. 패키지 목록 업데이트
sudo apt-get update -y

    1. IP 포워딩(중계 기능) 켜기
      (설정 파일에서 forwarding 옵션을 찾아서 1로 바꿔주는 명령어입니다)
      LINE=(grepnet.ipv4.ipforward=/etc/sysctl.conf)sudosedi"s/(grep 'net.ipv4.ip_forward=' /etc/sysctl.conf) sudo sed -i "s/{LINE}/net.ipv4.ip_forward=1/" /etc/sysctl.conf
      sudo sysctl -p
    1. iptables 설정 (들어온 요청을 마스커레이딩-포장갈이 해서 내보내기)
      (자동으로 네트워크 인터페이스 이름을 찾아서 설정합니다)
      INTERFACE=$(ip link | awk -F: '$0 !~ "lo|vir|wl|^[^0-9]"{print $2;getline}')
      sudo /sbin/iptables -t nat -A POSTROUTING -o ${INTERFACE} -j MASQUERADE
    1. 재부팅 해도 설정 유지되게 저장하는 프로그램 설치
      sudo apt-get install -y iptables-persistent
      ————————————————

인스턴스의 패킷 송신 허용 IP 수정

  • Nginx인스턴스 설정 -> 우측상단 인스턴스 작업 버튼 -> 패킷 송신 허용 IP 설정 -> 0.0.0.0/0 -> 저장

클라우드 콘솔 설정


위와 동일하게 해주면됨

0.0.0.0/20 여기서 /20이 의미하는것 넷마스크이다.
넷마스크란 네트워크 대역을 논리적으로 분리하여 각자 다른 네트워크 망을 생성해주는것이다.
네트워크 망을 나눔으로써 특정영역은 프라이빗, 특정영역은 퍼블릭으로 설정할수 있다.
넷마스크를 사용하고 이해하는법은 아래와 같다.

/18인 경우 11111111.11111111.11000000.00000000 1이 18개
255 . 255 . 192 . 0 -> 64개씩
/17인 경우 11111111.11111111.10000000.00000000 1이 17개
255 . 255. 128 . 0 -> 128개씩
Nat 게이트웨이를 사용해야 하는 서브넷 고정 ip를 보면 144~192
그렇다면 최소 48블럭이 뚫려있어야 한다 그러면 10.0.128.0/18로 하고 64블럭으로 나눠서 쓰면 되겠네 라고 생각하겠지만 10.0.0.0도 있기 때문에 0~63,64~127,127~191, 192~255 블럭씩 쓸 수 있어 128블럭으로 나눠서 사용해야한다.
10.0.128.0/17로 사용하면 된다.

두개 추가

라우팅 테이블 private에 instance로 0.0.0.0/0 뚫어준다.
후에 잘 됐는지 확인
Private 인스턴스로 들어가
curl -I https://www.google.com
했을때 HTTP/2 200 뜨면 성공

1-8. 로드밸런싱 설정

Certification Maneger 등록
1. 프라이빗 키 (Private Key) 생성
openssl genrsa -out private.key 2048

  1. CSR (인증서 서명 요청) 생성
    openssl req -new -key private.key -out request.csr
  1. 인증서 본문 (Certificate Body) 생성
    openssl x509 -req -days 365 -in request.csr -signkey private.key -out certificate.crt

**포맷 확인: 모든 파일은 PEM 형식이어야 합니다.

  1. 프라이빗 키 확인
    Cat private.key

  2. 인증서 본문확인
    Cat certificate.crt

  • 콘솔에 인증서 내용 복사 붙여넣기.


  1. 로드벨런서 탭에서 로드벨런서 생성 클릭
  • ALB선택
  • VPC 와 서브넷, 리스너를 추가한다. 리스너는 80과 443을 추가한다.
  • 인증서 생성 단계에서 만들었던 인증서를 등록한 후 저장한다.

  • 퍼블릭 IP를 연결해준다.

t1

퍼블릭 IP연결

1-9. 대상그룹 생성

  • 대상그룹에 이전 단계에서 생성한 ALB (로드벨런서) 를 추가한다.
  • 대상그룹의 이름과 프로토콜을 설정후 다음을 클릭한다.
  • 퍼블릭 인스턴스(nginx)를 선택하고 트래픽포트, 443,80을 적어 추가한다.





T1





1-10. 로드벨런서에 대상그룹 연결

  • 로드밸런서 탭에서 리스너 추가 탭 클릭

  • 80, 443 포트에 대상그룹 선택

    **t2의 error상태는 일시적오류. 시간이 지난후 정상 동작 확인 완료.


10. DNS영역에 로드벨런서 DNS추가

업로드중..

로드벨런싱 설정 완료

**트러블슈팅
증상 : 대상 그룹에서 헬스체크 Unhealthy 상태임

Nginx ssl/tls설정 안함 443의미없음
따라서 Unhealthy 상태
보안그룹 및 Nginx 설정 오류

2.서버 설정

  1. 로컬(macOS)
  • 퍼블릭 키 생성
  • 키페어 권한 변경
chmod 400 keypair2.pem

퍼블릭 키 생성
ssh-keygen -y -f keypair2.pem > keypair2.pub
vm 생성 시 위 명령어로 .pub 파일 생성
키 페어 생성 -> 기존 키 업로드 -> 생성된 .pub 파일 업로드

db 테스트 용 ssh 터널
ssh -i keypair2.pem \
-N \
-L 15432(임의 포트 번호):[db엔드포인트 주소]:5432(db포트 번호) \
ubuntu@[퍼블릭 아이피 주소]

위 명령어를 터미널에 입력하면 터널이 열림. 이 상태에서 프로젝트를 실행한다.
터널 사용 시 yaml파일의 datasource url을
jdbc:postgresql://localhost:15432/mydb
로 변경해함.

  1. Nginx 인스턴스 설정
  2. Frontend 코드 불러오기
  • FileZilla로 로컬 - Nginx 서버
  • 로컬에서 React 프로젝트 build -> dist 폴더 생성
  • dist 폴더 FileZilla로 Nginx 서버에 옮기기
  • /usr/share/nginx/html 경로에 assets 폴더, index.html 옮기기
  1. Nginx 설정
  • /etc/nginx/conf.d/default.conf 파일 수정
server {
    listen       80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # FASTAPI 서버 전달
    location /api/ {
        proxy_pass http://10.0.145.240:8000;
        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;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Chatbot
    location /question/ {
        proxy_pass http://10.0.145.240:8080/question;
        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;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }    

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
  1. 트러블 슈팅
    프론트엔드 측에서 Spring 서버에 요청해 정상 응답을 받더라도 화면에 표기할 수 없을 경우
    문제는 다음과 같음
  2. 프론트엔드 코드는 JSON으로 파싱하려고 한다.
  3. 서버는 일반 텍스트를 한 글자씩 보내고 있다.
 (Flux<String>)

해결 방법

  1. 프론트엔드에서 axios를 사용하지 말고 fetch API를 사용해 요청하기
    변경 전
const response = await chatClient.get(`?question=${encodeURIComponent(input)}`,);

변경 후

const response = await fetch(`http://210.109.82.105/question?question=${inputValue}`);
  1. fastAPI 인스턴스 설정

  2. Python 가상환경 생성 (서버)

sudo apt update
sudo apt install -y python3.12-venv
python3 -m venv venv
source venv/bin/activate
  1. 의존성 설치
pip install --upgrade pip
pip install -r requirements.txt
  1. PostgreSQL 인스턴스 설정
    1 .bastion에 postgresql-client 설치
sudo apt update
sudo apt install postgre-client
sudo psql -h az-b.kakao-t2-db-group-po.42272f947b124b5f8f76b5a656d80baf.postgresql.managed-service.kr-central-2.kakaocloud.com -U admin -d postgres

2.vectorDB 익스텐션 설치 및 확인
postgre 접속

psql -d postgres

pgvector vectorDB생성

CREATE EXTENSION vector;
  1. tomcat 인스턴스 설정
    1.java 설치
#자바설치명령어
sudo apt install openjdk-21-jre-headless
#자바 설치 확인
java --version

2.Docker 설치

sudo apt-get update

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

GPG 키 추가

curl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg) | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Docker 저장소 추가

echo "deb \[arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg\] [https://download.docker.com/linux/ubuntu](https://download.docker.com/linux/ubuntu) $(lsb\_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#패키지 업뎃
sudo apt-get update


sudo apt-get install docker-ce docker-ce-cli containerd.io

#도커설치확인
sudo docker --version

#도커실행확인
sudo systemctl start docker

#도커로그인
sudo docker login
  1. Mysql 인스턴스 설정

  2. bastion에 Mysql-client 설치

sudo apt update
sudo apt install mysql-client


mysql -h az-b.kakao-t2-db-group.42272f947b124b5f8f76b5a656d80baf.mysql.managed-service.kr-central-2.kakaocloud.com -P 3306 -u admin -p
  1. shwdb 생성 후 테이블
  2. 테이블 설정
    3.1 order_items

3.2 orders

3.3 products

3.4 users

  1. Bastion 인스턴스 설정

ssh 접속

ssh -i keypair2.pem ubuntu@[ip주소]
vi ~/.ssh/config
Host nginx-t2
  HostName 10.0.129.240
  User ubuntu
  IdentityFile ~/.ssh/keypair2.pem
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null

Host fastapi-t2
  HostName 10.0.145.240
  User ubuntu
  IdentityFile ~/.ssh/keypair2.pem
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null

Host tomcat-t2
  HostName 10.0.161.240
  User ubuntu
  IdentityFile ~/.ssh/keypair2.pem
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null

3. 배포 설정

1.Nginx-t2

1.Nginx 서버 접속

ssh -i ~/.ssh/keypair2.pem ubuntu@10.0.129.240

2.Nginx 공식 저장소 등록하여 설치 과정
2-1.

sudo vi /etc/apt/sources.list.d/nginx.list 
deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu jammy nginx
deb-src [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu jammy nginx

컴퓨터의 패키지 매니저(apt)에게 Nginx를 설치할 때 공식 사이트(nginx.org)라는 주소로 가서 찾을 수 있도록 설정 파일 만드는 과정
2-2.

curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o/usr/share/keyrings/nginx-archive-keyring.gpg

공식 사이트에서 내려받는 파일이 Nginx에서 검증된 파일이 맞는지 확인하기 위한 디지털 서명을 저장하는 과정
2-3.

sudo apt update

패키지 매니저인 apt 최신 업데이트
2-4.

sudo apt install nginx

패키지 목록에 있는 최신 Nginx를 컴퓨터에 설치
2-5.

nginx -v

Nginx 설치 확인 작업
2.Fast API
1. 키 파일 권한 설정 (로컬 Mac)
/Users/apple/Desktop/react_shoppingmall+springAIchatbot+fastapi/fastapiBack1에있는

fastapiBack1폴더를 bastion 서버(210.109.55.33)를 거쳐서 fastapi서버(10.0.145.240)에 넣어줘야 한다.
로컬 터미널에서 실행

chmod 400 /Users/apple/Desktop/keypair2.pem
  1. Bastion 서버 접속 (로컬 → Bastion)
ssh -i /Users/apple/Desktop/keypair2.pem ubuntu@210.109.55.33

접속후
로컬 Mac에서 실행

scp -i /Users/apple/Desktop/keypair2.pem \
-r fastapiBack1 \
ubuntu@210.109.55.33:/home/ubuntu/

입력
3. FastAPI VM 접속 테스트 (Bastion → FastAPI)
Bastion 서버 안에서 실행

ssh -i keypair2.pem ubuntu@10.0.145.240 
scp -i keypair2.pem \
-r fastapiBack1 \
ubuntu@10.0.145.240:/home/ubuntu/

입력
4. FastAPI 서버 접속 및 프로젝트 확인

ssh -i keypair2.pem ubuntu@10.0.145.240

접속후

ls

fastapiBack1 폴더 있는거 확인.
3. spring
스프링 AI 수동배포

Docker 를 사용하여 배포를 진행한다.
먼저 gradlew 로 스프링 프로젝트를 빌드해야한다.

스프링 프로젝트 빌딩 (경로: 프로젝트 루트 폴더)

#실행 권한을 부여함
chmod +x gradlew 

#빌드 실행 명령어
./gradlew build

#테스트를 제외하고 빌드함 (오류 시 이렇게)
./gradlew build -x test 

빌드 결과물은
build/libs/
└── your-project-name-0.0.1-SNAPSHOT.jar
경로에 있음

이후 도커 이미지 파일을 제작한다.

Dockerfile (도커 파일 내용) (프로젝트 루트 폴더에서 작성함)
#사용하는 이미지
FROM eclipse-temurin:21-jdk-alpine

#프로젝트가 올라가는 디렉토리
WORKDIR /app

ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar

ENV JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75.0 -Duser.timezone=Asia/Seoul"
ENV SPRING_PROFILES_ACTIVE=prod

ENTRYPOINT ["sh", "-c", "java JAVAOPTSDspring.profiles.active=JAVA_OPTS -Dspring.profiles.active={SPRING_PROFILES_ACTIVE} -jar app.jar"]

ENTRYPOINT ["java", "-jar", "app.jar"]
#포트사용지정(도커내부포트)
EXPOSE 8080
도커파일은 docker 에서 이미지를 생성하기 위한 용도로 작성하는 파일이다.
만들 이미지에 대한 정보를 기술해 둔 템플릿(template) 이라고 보면 된다.
출처: https://toramko.tistory.com/entry/docker-도커파일Dockerfile-의-개념-작성-방법문법-작성-예시 [토람코:티스토리]

도커 명령어 (프로젝트 루트 폴더)

docker login

#Dockerfile을 기반으로 도커 이미지를 빌드하는 명령어
docker build --platform linux/amd64 -f Dockerfile.fast -t [도커허브사용자명]/[프로젝트이름] .

#만들어진 이미지를 도커 허브에 push함
#이 때 프로젝트 이름 뒤에 :3.12 등 숫자를 붙이면 버전에 이미지를 붙인 것이 된다.
#아무것도 붙이지 않으면 자동적으로 latest로 붙여짐
docker push [도커허브사용자명]/[프로젝트이름]
맥os 에서 도커를 빌드할 때 --platform linux/amd64를 옵션으로 넣어주어야한다.

도커 명령어 (서버)

docker login

#깃헙처럼 레포지토리에 push 된것을 pull 하여 서버에 내려받음
sudo docker pull [도커허브사용자명]/[프로젝트이름]

# pull한 도커 이미지들을 확인한다.
sudo docker images

# 환경 변수 선언을 여기에서 할 수 있다.
sudo docker run -d \
--name spring \
-p 8080:8080 \
-e GEMINI_API_KEY=[api key]\
-e GOOGLE_PROJECT_ID=[project id] \
[도커허브사용자명]/[프로젝트이름]:latest

Tomcat

환경 셋팅
sudo apt install openjdk-21-jre-headless

profile
Change Up

0개의 댓글