MPA 환경에서 Vue 프로젝트를 빌드하여 Spring Boot 정적 리소스로 배포하는 방법
Spring Boot에서 MPA 환경으로 Vue를 구성하고 배포하는 방법을 설명합니다.
요약
이 글에서는 MPA(Multi-Page Application) 환경에서 Vue 프로젝트를 설정하고, 이를 Spring Boot에 정적 리소스로 배포하는 방법에 대해 설명합니다. MPA 모드에서 각 페이지별로 HTML 파일을 생성하여, Spring Boot의 정적 리소스 폴더에 배포하는 과정에서의 구현 포인트와 주의 사항을 다룹니다. 이로 인해 여러 페이지를 포함하는 웹 애플리케이션을 보다 쉽게 구축하고, 사용자 경험을 향상할 수 있는 방법을 제안합니다.
배경/문제
기존의 Vue는 SPA(Single Page Application) 형태로 설계되어 있습니다. 이 모드에서는 모든 내용이 하나의 index.html 파일에 통합되어 있으며, URL 경로나 페이지 전환 시 추가 데이터 요청 없이 동작합니다. 그러나 MPA 구조에서는 여러 개의 독립된 페이지를 생성할 수 있어 웹 애플리케이션의 사용성과 SEO 측면에서 유리합니다. 특히, SEO 최적화가 중요한 애플리케이션의 경우, 각 페이지가 별도로 로드되는 것이 필요할 수 있습니다.
이와 함께 Spring Boot와 Vue를 연동하여 MPA 구조를 구현할 때 발생할 수 있는 문제들은 다음과 같습니다:
- 특정 페이지가 로드되지 않거나 빈 화면이 표시됨.
- Spring Boot가 HTML 파일을 반환하지 않거나, 예상치 못한 오류가 발생함.
- 보안 설정으로 인해 사용자가 필요한 정적 리소스에 접근하지 못함.
예를 들어, 파일 경로나 접근 권한 설정 문제가 원인이 되어 HTML 파일이 반환되지 않을 수 있습니다. 이러한 잠재적 문제를 미리 파악하고 대비하는 것이 중요하며, 각 페이지의 URI와 해당 URI에 대한 Spring Boot 설정을 올바르게 구성하는 것이 핵심입니다.
접근/해결 전략
이 문제를 해결하기 위해서는 Vue 프로젝트를 MPA 모드로 구성하고, 각 페이지마다 HTML 파일을 설정하여 이를 Spring Boot의 정적 리소스 폴더에 배포하는 방법을 따릅니다. 이러한 접근 전략을 선택한 이유는 다음과 같습니다:
- 다양한 페이지로 구성된 웹 애플리케이션은 사용자에게 친숙한 URL을 제공하여 UX를 개선할 수 있습니다.
- 각각의 페이지가 독립적으로 로드되면 사용자가 느끼는 반응 속도가 빨라지고, 서버 부하가 분산될 수 있습니다.
- 다양한 페이지에 맞춤형 콘텐츠를 배치할 수 있어 SEO 최적화 측면에서도 유용합니다.
해결 전략을 구현하기 전, 실패 시나리오를 고려해 볼 수 있습니다. Vue 기반 MPA 프로젝트에서 발생할 수 있는 실패 유형 중 하나는 파일 경로의 오류입니다. Vue 애플리케이션과 Spring Boot 간의 파일 경로 불일치로 인해 HTML 파일이 제대로 로딩되지 않을 수 있습니다. 이 문제를 예방하기 위해서 각 파일의 경로를 철저히 검토하고, 이를 Spring Boot 애플리케이션과 일관되게 유지하는 것이 중요합니다.
구현 포인트
1. Vue 프로젝트를 MPA로 구성하기
MPA 모드로 구성하기 위해 vite.config.js 파일을 수정해야 합니다. 아래의 코드를 프로젝트에 추가하면 각 페이지에 대한 HTML 파일이 생성됩니다.
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
login: resolve(__dirname, 'src/pages/login.html'),
welcome: resolve(__dirname, 'src/pages/welcome.html'),
},
},
},
});
위 코드는 input 객체에 각 페이지의 HTML 템플릿을 지정하여 /dist/login.html 및 /dist/welcome.html과 같은 파일을 생성하도록 합니다. 이렇게 구성하면 Spring Boot는 두 개의 독립적인 HTML 파일을 처리할 수 있게 됩니다.
2. Vue 프로젝트 폴더 구조
MPA 구조를 위해 Vue 프로젝트 폴더 구조는 다음과 같이 설정합니다:
/frontend
├── /src
│ ├── /pages
│ │ ├── login.html # 로그인 페이지 템플릿
│ │ ├── welcome.html # 웰컴 페이지 템플릿
│ ├── /views
│ │ ├── LoginView.vue # 로그인 페이지 Vue 컴포넌트
│ │ ├── WelcomeView.vue # 웰컴 페이지 Vue 컴포넌트
│ ├── main.js # Vue 초기 설정
├── vite.config.js # MPA 빌드 설정
├── package.json
├── index.html # 기본 HTML 템플릿 (필요 시)
이 구조는 각 페이지의 HTML과 Vue 컴포넌트를 효율적으로 관리하도록 돕습니다. 각각의 Vue 컴포넌트는 해당 페이지의 기반이 되는 HTML 파일과 함께 연결되어 있으며, 이는 가독성과 유지보수 측면에서도 유리합니다.
3. Vue 페이지별 개별 HTML 파일 설정
각 페이지별 HTML 파일을 설정하는 방법은 다음과 같습니다.
1) src/pages/login.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>로그인</title>
<script type="module" src="/src/main.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { createApp } from 'vue';
import LoginView from '../views/LoginView.vue';
createApp(LoginView).mount('#app');
</script>
</body>
</html>
이 파일은 사용자가 로그인할 수 있는 페이지를 제공하며, Vue 애플리케이션을 초기화하여 LoginView 컴포넌트를 로드합니다.
2) src/pages/welcome.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>웰컴 페이지</title>
<script type="module" src="/src/main.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { createApp } from 'vue';
import WelcomeView from '../views/WelcomeView.vue';
createApp(WelcomeView).mount('#app');
</script>
</body>
</html>
이 설정을 통해 각 HTML 파일은 독립적으로 Vue 컴포넌트를 렌더링할 수 있으며, 페이지 로딩 시 각각의 콘텐츠를 정확히 로드할 수 있게 됩니다.
검증
Vue 프로젝트를 빌드한 후, 각 HTML 파일을 Spring Boot의 static/ 폴더로 배포하는 과정을 통해 최종적으로 설정 사항을 검증합니다. 검증 과정은 다음과 같습니다:
- Vue 프로젝트 빌드하기:
cd frontend # Vue 프로젝트 디렉토리 npm run build # Vue 프로젝트 빌드
이 명령어는 Vue 애플리케이션을 컴파일하고 모든 필요한 파일을 dist/ 폴더에 생성합니다.
- 빌드된 HTML 및 자산을 Spring Boot의 static/ 폴더로 이동하기:
cp -r dist/* ../backend/src/main/resources/static/
이 명령어는 dist 폴더의 모든 파일을 Spring Boot의 static/ 디렉토리로 복사합니다. 그 결과, 최종 폴더 구조는 다음과 같아야 합니다:
/backend/src/main/resources/static/
├── login.html # 로그인 페이지
├── welcome.html # 웰컴 페이지
├── assets/ # Vue 빌드된 정적 파일들
이제 Spring Boot는 자동으로 static/login.html과 static/welcome.html 파일을 제공할 수 있게 됩니다. 이 관리를 통해 웹 애플리케이션의 각 페이지가 제대로 동작하는지 확인 가능합니다.
주의사항/트레이드오프
1. Spring Boot에서 Vue 페이지를 반환하는 컨트롤러 설정
각 페이지에 대한 요청 처리를 위해 다음과 같은 Spring Boot 컨트롤러를 설정해야 합니다.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ViewController {
@GetMapping("/login")
public ModelAndView loginPage() {
return new ModelAndView("forward:/login.html");
}
@GetMapping("/welcome")
public ModelAndView welcomePage() {
return new ModelAndView("forward:/welcome.html");
}
}
이 코드를 통해 Spring Boot는 /login 및 /welcome 요청에 대해 각 HTML 페이지를 반환하게 됩니다. 이를 통해 MPA 구조에서 각 페이지가 독립적으로 작동할 수 있는 기반이 마련됩니다.
2. Spring Security에서 정적 리소스 허용
Spring Security를 사용하는 경우, 정적 리소스에 대한 접근을 허용하는 추가 설정이 필요합니다. 이를 위해 SecurityConfig.java 파일에서 다음과 같이 설정합니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // CSRF 비활성화 (쿠키 기반 인증)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/welcome", "/static/**").permitAll() // 정적 리소스 허용
.requestMatchers("/external/api/auth/**").permitAll() // 로그인 및 인증 관련 API 허용
.anyRequest().authenticated() // 나머지 요청은 인증 필요
);
return http.build();
}
}
이 설정은 Vue의 /login, /welcome, 및 /static/** 경로로의 접근을 허용하여 정적 리소스를 쉽게 이용할 수 있도록 돕습니다. 보안과 접근성의 균형을 유지하는 것이 중요합니다.
마무리
이번 글에서는 Vue를 MPA 방식으로 설정하여 Spring Boot의 정적 리소스와 연동하는 방법을 성공적으로 구현할 수 있습니다. 아래의 체크리스트를 통해 설정 사항을 점검하고 적용 여부를 확인하세요.
| 작업 내용 | 설명 |
|---|---|
| Vue를 MPA 방식으로 설정 | vite.config.js에서 rollupOptions.input 추가하여 개별 HTML 파일 생성 |
페이지별 login.html, welcome.html 생성 | 각 HTML에서 Vue 컴포넌트 로드 |
Spring Boot static/에 배포 | npm run build 후 dist/ 폴더를 static/에 복사 |
| Spring Boot 컨트롤러에서 페이지 제공 | /login, /welcome 요청 시 개별 HTML 반환 |
| Spring Security에서 정적 리소스 허용 | /static/**, /login, /welcome 요청 허용 |
각 페이지가 개별 HTML 파일로 배포되어 MPA 환경에서도 원활하게 Spring Boot와 연동되어 동작할 수 있습니다. 이러한 설정은 다중 페이지 애플리케이션 개발 시 유용하며, 사용자 경험을 개선하는 데 기여할 것입니다. 이 설정이 필요할 때, 혹은 유사한 구조를 가진 애플리케이션을 구축할 때 고려해 보세요.