개인 프로젝트

Spring + Vue 배포하기

오마이냥 2024. 11. 7. 22:14

Spring으로 backend를

Vue로 frontent를 담당하여 개발하였다. 기억에 남도록 배포하는 과정을 남기고자 한다.

 

1. vue build

vue의 터미널에서 npm run build 명령어를 입력하면

frontend 폴더에 dist 폴더가 생성된다.

 

2. dist 파일 spring으로 이동시키기

dist 폴더 내의 모든 파일을 

src/main/resources/static 폴더 안에 모두 넣는다.

 

3. WebConfig 설정하기

WebConfig 파일을 생성하고 addResourceHandler 메서드에 다음 코드를 추가해서

정적 리소스 핸들러를 설정하였다.

 

"/**/*" root context 아래 모든 주소는 static 폴더 내에서 찾으면 된다는 코드이다.

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;

import java.io.IOException;

public class WebConfig implements WebMvcConfigurer {

    // Spring MVC에서 요청된 URL을 실제 파일로 매핑하여 반환하는 역할
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/**/*") // 모든 URL 패턴에 대해
                .addResourceLocations("classpath:/static/") // /static/에 위치한 파일들은 classpath:/static/ 경로를 통해 제공된다.
                .resourceChain(true) // 리소스 체인 활성화 (파일 캐싱, 압축 등 최적화)
                .addResolver(new PathResourceResolver() {
                    @Override
                    protected Resource getResource(String resourcePath, Resource location) throws IOException {
                        Resource requestedResource = location.createRelative(resourcePath); // 요청된 resourcePath를 기반으로 상대적 경로의 리소스를 생성한다.
                        return requestedResource.exists() && requestedResource.isReadable() ? requestedResource : new ClassPathResource("/static/index.html");
                        // requestedResource.exists(): 리소스가 실제로 존재하는지
                        // requestedResource.isReadable(): 리소스가 읽을 수 있는 상태인지
                        // 만약 요청된 리소스가 존재하지 않거나 읽을 수 없다면, index.html을 대신 반환하도록 설정한다.
                    }
                });
    }
}

 

  • CORS 설정: SecurityConfig에서 이미 CorsConfigurationSource로 설정을 하고 있으므로, WebConfig에서는 생략할 수 있지만, 유지해도 무방합니다.
  • 정적 리소스 핸들러 설정: /static 디렉토리의 파일을 / URL 경로에서 접근할 수 있도록 설정하고, 요청된 리소스가 존재하지 않으면 index.html을 반환합니다. 이는 Vue와 같은 SPA(Single Page Application)의 리소스를 서빙하기 위한 설정입니다.

 

참고: https://january-diary.tistory.com/entry/SpringBoot-%EB%94%B0%EB%A1%9C-%EA%B0%9C%EB%B0%9C%ED%95%9C-springboot%EC%99%80-vue-%ED%95%A9%EC%B9%98%EA%B8%B0

 

[SpringBoot] 따로 개발한 springboot와 vue 합치기

스프링부트와 뷰에서 작업이 모두 끝났다면 뷰 파일을 스프링 static 폴더에 넣어 함께 실행시킬 수 있다. 1. vue 프로젝트 build 터미널에 다음 명령어를 입력하면 dist폴더에 프로젝트를 바로 실행

january-diary.tistory.com

 

4. SecurityConfig 설정하기

위 과정을 거치고 BackendApplication을 실행했는데 403에러가 발생했다.

SecurityConfig에서 권한 설정을 해주었다.

.requestMatchers("/static/**", "/", "/index.html", "/favicon.ico", "/js/**", "/css/**", "/img/**", "/fonts/**").permitAll()

 

이는 다음 경로에 대해

"/static/**", "/", "/index.html", "/favicon.ico", "/js/**", "/css/**", "/img/**", "/fonts/**"

즉, 정적 리소스 경로에 대한 접근을 허용해주었다.

 

여기까지 했을 때 localhost:8080으로 접속이 성공했다. (ip 주소 바꿀 예정)

 

5. 인스턴스 & 탄력적 IP 할당

인스턴스를 중지했다가 다시 시작하면 IP가 바뀌기 때문에

고정 IP인 탄력적 IP를 할당해주었다. 

 

과정은 생략한다.

 

6. Docker 설치

Docker Desktop은 기본적으로 Hyper-V를 사용하기 때문에 Hyper-V 기능을 지원하지 않는 Windows Home Edition은 사용할 수 없지만

Windows Home Edition 버전에서도 WSL2를 사용하여 Docker Desktop을 사용할 수 있다.

 

6-1. Hyper-V 설치

6-2. PowerShell 실행 후 명령어를 입력해 WSL2 설치

6-3. Microsoft Store에서 Ubuntu 설치

6-4. Docker Desktop fot Windows 설치

 

참고: https://mz-moonzoo.tistory.com/40

 

[Docker]Windows 11 Pro에서 Docker 설치(Docker Desktop)

Docker? Docker는 애플리케이션을 개발, 배포 및 실행하기 위한 플랫폼 및 도구 모음입니다. 주요 목적은 소프트웨어를 컨테이너라고 불리는 표준화된 유닛 내에서 패키징하여, 코드가 일관된 환경

mz-moonzoo.tistory.com

 

7. AWS RDS 생성

과금되지 않게 주의

 

RDS를 생성 후 이모지도 출력할수 있게 파라미터 그룹도 생성 -> utf8mb4 

 

8. application.properties 파일 작성

application.properties 파일에 application name, driver-class-name, port, address 등을 작성한다.

 

만약 applicaion.properties에 DB와 관련된 민감한 정보를 담을 경우 노출 문제가 발생할 수 있기 때문에,

application-aws.properties 파일을 따로 만들어 DB-url, DB-username, DB-password와 같은 민감한 정보를 관리해준다.

 

다시 기존 application.properties로 돌아와서 다음 코드를 작성해

spring.profiles.include = aws

aws라고 설정한 파일을 해당 properties에 include해준다.

 

9. Spring 빌드

Gradle에서 bootJar를 눌러서 build하면 backend>build>libs 폴더에 jar파일이 생성된다.

 

9. Dockerfile 작성

Dockerfile은 DockerImage를 생성하기 위한 스크립트(설정 파일)이다.

여러가지 명령어를 토대로 Dockerfile을 작성한 후 빌드하면 Docker는 Dockerfile에 나열된 명령문을 차례대로 수행하며 DockerImage를 생성해준다.

## Dockerfile

FROM openjdk:21-slim				// Openjdk 21 slim 이미지를 사용
ARG JAR_FILE=backend-0.0.1-SNAPSHOT.jar		// 복사할 JAR_FILE의 이름을 지정
COPY ${JAR_FILE} app.jar			// JAR_FILE을 app.jar라는 이름으로 컨테이너 내부에 복사
ENV TZ=Asia/Seoul				// 컨테이너 시간대를 Asia/Seoul로 설정
ENTRYPOINT ["java", "-jar", "/app.jar"]

 

10. Docker build

먼저 Docker desktop 실행 후 

인텔리제이 terminal에 docker login 입력해 로그인한다.

 

cd build/libs로 이동 후

backend\build\libs> docker build -t {도커 허브 ID}/{레포지토리 이름} {Dockerfile 경로}

내 프로젝트 기준 : backend\build\libs> docker build -t osm/app . (<- 마지막에 온점 넣을 것)로 도커에 빌드한다.

 

docker image ls

도커 이미지 확인

 

11. Docker Repository 생성

DockerHub에서 Repository > Create repository 버튼을 눌러

Private Repository를 생성한다.

이때 Repository 이름은 Dockerfile 스크립트로 생성한 이미지의 레모지토리 주소와 같아야 한다.

 

Username엔 이메일을

Password엔 비밀번호를 작성한다.

 

12. Docker push

docker push {도커 허브 ID}/{레포지토리 이름}

도커에 push하면

 

DockerHub의 Repositories에서 업로드한 이미지를 확인할 수 있다.

 

13. EC2에 Docker 설치하기

putty에 접속

login as: ubuntu

 

아래의 명령어를 입력해 Docker를 설치한다.

udo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get install docker-ce docker-ce-cli containerd.io

 

sudo systemctl status docker

도커가 잘 실행되고 있는지 확인

 

User가 root가 아닌 경우, 권한이 없다는 이유로 Docker가 실행되지 않는다.

따라서 아래의 명령을 입력하고 putty를 재실행 해준다.

sudo usermod -aG docker $USER
sudo service docker restart
sudo systemctl restart docker
sudo chown root:docker /var/run/docker.sock

 

 

14. Docker 이미지 pull

putty에 접속

login as: ubuntu

 

docker login

도커에 로그인하고

 

Dockerhub에 업로드한 이미지를 가져온다.

docker pull osm/app

 

가져온 이미지를 이용해 컨테이너를 생성 및 실행한다.

docker run -i -t -p 8080:8080 {이미지 이름} & <- 백그라운드 실행 + 두 개의 명령어를 결합한 형태

또는

docker run -dit -p 8080:8080 {이미지 이름} <- 백그라운드 실행 + Docker 명령 옵션으로 간단히 처리 (이걸로 하자고)

-i : 컨테이너의 표준 입력을 유지한다. 컨테이저 내부에서 사용자 입력을 받을 수 있도록 설정한다.

-t : 터미널 환경을 사용해 컨테이너와 상호작용할 수 있다.

-o 8080:8080 : 호스트의 8080포트를 컨테이너의 8080포트로 매핑한다. 즉 호스트의 브라우저에서 http://localhost:8080을 열면 컨테이너의 8080 포트에서 제공하는 서비스에 접근할 수 있다.

& : 백그라운드 실행을 의미한다. 즉 터미널을 계속 사용할 수 있도록 컨테이너 실행 작업을 백그라운드로 이동한다.

-d : &이 없어도 컨테이너를 백그라운드 모드로 실행한다. 

 

docker ps

실행중인 도커 확인

 

15. 서버 종료

서버를 종료하고 싶다면 컨테이너를 종료하고 삭제하자.

docker stop {컨테이너 ID}
docker rm {컨테이너 ID}
docker rmi {이미지 ID}

 

 

참고: https://velog.io/@gmlstjq123/Docker-EC2%EB%A1%9C-SpringBoot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0-5fh0n7us

 

Docker + EC2로 SpringBoot 프로젝트 배포하기

이번 포스팅에서는 SpringBoot로 작성된 서버 파일을 Docker를 이용해 배포하는 방법에 대해 알아보도록 하겠습니다. Docker의 기본 개념이나 명령어는 이미 잘 알고 있다는 가정 하에 포스팅을 작성

velog.io

 

참고: https://velog.io/@wonizizi99/Web-AWS-EC2-RDS-MySQL%EC%97%B0%EA%B2%B0

 

[Web] 최종프로젝트(11)AWS EC2 RDS MySQL연결

AWS RDS 대시보드 이동한다.데이터베이스 생성Amazon RDS의 MySQL 버전 결정에 참고자료현 서비스로 배포 목적이 아니지만 최신 버전 중 연장가능성 고려하여 2023년 6월월까지 제공되는MySQL 8.0.28 버전

velog.io

 

추가) 접근 에러가 발생해서 노트북 방화벽에서 3306 인바운드 아웃바운드 추가해줬음 <- 근데 도서관이 문제였던듯

 

--------------------------------------

프로젝트 수정 후 다시 빌드할 때

vue에서 npm run build 

새로 생성된 dist 폴더에 있는 모든 폴더와 파일 복사 후

 

spring의 ackend\src\main\resources\static 경로에 붙여넣기 한다.

 

bootjar로 jar파일 생성 (libs 폴더에 있음)

 

docker desktop 실행 후 

terminal에 docker login 입력해 로그인

 

cd build/libs로 이동 후

backend\build\libs> docker build -t ohsongmin/myapp .

로 도커 빌드

 

docker image ls

도커 이미지 확인

 

docker push ohsongmin/myapp

도커에 push

 

putty 접속 

login as: ubuntu

 

docker pull ohsongmin/myapp

도커 이미지 pull

 

docker ps 

실행중인 도커 확인

 

docker stop {containerID}

실행중인 도커 정지

 

docker run -d -p 8080:8080 ohsongmin/myapp

실행