Vue 3를 이용한 프론트엔드와 Spring Boot를 이용한 백엔드를 연동하려면, 단순히 "주소만 맞추면 된다"가 아닙니다.
CORS, JWT 인증 처리, DTO 통신, 응답 규약, 예외 처리까지 고려한 구조 설계가 필요합니다.
이번 포스팅에서는 실전 기준으로 아래 내용을 정리해드립니다.
1. 시스템 구성 예시
- 프론트엔드: Vue 3, TypeScript, Pinia, Axios
- 백엔드: Spring Boot 3.x, Java 11+, Spring Security, JWT
- 연동 방식: RESTful API 통신 (JSON 기반)
- 빌드/배포: FE는 dist/로 빌드되어 Nginx에 정적 호스팅, BE는 API 서버로 독립 운영
2. CORS 설정 – 백엔드에서 허용
Vue 개발 서버는 기본적으로 localhost:5173, 백엔드는 localhost:8080 등 서로 다른 포트를 사용하므로 CORS 오류가 발생할 수 있습니다.
✅ Spring Boot CORS 설정 (전역)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}
💡 allowCredentials(true) 설정 시, 쿠키/Authorization 헤더 사용 가능
3. Axios 기본 설정
// src/lib/axios.ts
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:8080/api',
withCredentials: true, // 쿠키 사용 시 필요
})
api.interceptors.request.use((config) => {
const token = localStorage.getItem('access_token')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
export default api
4. DTO 연동 구조
🔹 프론트 요청 DTO 예시 (TypeScript)
interface LoginRequest {
username: string
password: string
}
🔸 백엔드 요청 DTO 예시 (Java)
public record LoginRequest(String username, String password) {}
✅ DTO 간 이름과 타입을 맞추면 JSON 직렬화/역직렬화가 자연스럽게 됩니다.
5. API 응답 구조 통일
🔹 프론트 기대 응답 형태
interface ApiResponse<T> {
success: boolean
data: T
message?: string
}
🔸 백엔드 공통 응답 래퍼 클래스
public record ApiResponse<T>(boolean success, T data, String message) {
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(true, data, null);
}
public static ApiResponse<?> error(String message) {
return new ApiResponse<>(false, null, message);
}
}
📦 사용 예시
@PostMapping("/login")
public ResponseEntity<ApiResponse<TokenResponse>> login(@RequestBody LoginRequest request) {
TokenResponse token = authService.login(request);
return ResponseEntity.ok(ApiResponse.success(token));
}
6. 예외 및 에러 처리 구조
프론트에서는 서버 응답이 200이 아니거나 success: false인 경우를 모두 처리해야 합니다.
🔸 Spring @ControllerAdvice 활용
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomAuthException.class)
public ResponseEntity<ApiResponse<?>> handleAuth(CustomAuthException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.error(e.getMessage()));
}
}
🔹 프론트 Axios 에러 핸들링
try {
const res = await api.post<ApiResponse<TokenResponse>>('/auth/login', payload)
if (!res.data.success) {
alert(res.data.message)
}
} catch (err: any) {
alert(err.response?.data?.message || '네트워크 오류')
}
7. 인증 흐름 구성 예시 (JWT 기반)
- 로그인 요청 → JWT 발급 (/api/auth/login)
- Axios 인터셉터로 토큰 자동 전송
- 서버는 Spring Security + JWT Filter로 토큰 인증
- 인증된 사용자만 데이터 조회 가능 (@PreAuthorize("isAuthenticated()") 등)
8. 실전에서의 팁
| 항목 | 설명 |
| CORS | 개발 시 허용 포트 설정 필요 (5173 ↔ 8080) |
| DTO | record, interface를 이용한 명확한 타입 정의 |
| 인증 | JWT → 헤더 처리, 필요 시 쿠키 방식으로 전환 |
| 전역 응답 | ApiResponse 구조 통일로 클라이언트 처리 일관성 |
| 에러 처리 | 백엔드에서 예외 래핑 + 클라이언트에서 사용자 메시지 표시 |
✍️ 마무리
Vue와 Spring Boot를 연동할 때 가장 중요한 건 계층 간 통신의 규약을 명확히 하는 것입니다.
DTO와 공통 응답 구조, 인증 흐름, CORS 처리까지 갖추면 프론트-백엔드 개발 분리가 훨씬 원활해집니다.
'BackEND > Java' 카테고리의 다른 글
| Spring Security - API 경로별 인증 방식 설정 (JWT + Basic Auth 혼합 적용) (1) | 2025.04.19 |
|---|---|
| Spring Boot java11 환경에서 JWT 인증 + Refresh Token 적용하기 (2) | 2025.04.17 |
| 기존 Spring Boot JSP 프로젝트에서 Vue.js로 프론트엔드 교체하기 (1) | 2025.04.15 |
| Spring Boot에서 REST API 설계 및 개발하기 (0) | 2025.04.06 |
| 실제 프로젝트에서 QueryDSL과 캐싱을 활용한 최적화 전략 (0) | 2025.04.05 |