Next.js 15 + Spring Boot 3.3 연동 방법
Next.js 15(App Router)과 Spring Boot 3.3을 연동할 때, 인증(Authentication) 및 API 통신을 고려해야 합니다. 일반적으로 NextAuth.js와 Axios Instance를 활용하는 방식이 많이 사용됩니다.
1. Next.js 15 프로젝트 생성
아래 명령어로 Next.js 15 프로젝트를 생성합니다:
npx create-next-app@latest frontend
설정 옵션 예시:
- TypeScript: Yes
- ESLint: Yes
- Tailwind CSS: Yes
- src 디렉토리 사용: Yes
- App Router 사용: Yes
- Turbopack 사용: Yes
- Import alias 설정: @/*
추가 패키지 설치
npm install next-auth axios @tanstack/react-query tailwind-merge tailwindcss-animate zod dotenv
2. 인증(Authentication) - NextAuth.js 사용
NextAuth.js를 사용하면 Spring Boot의 JWT 또는 세션 기반 인증을 쉽게 연동할 수 있습니다.
✅ Spring Boot와 NextAuth 연동 방식
- Spring Boot에서 JWT 또는 세션 기반 로그인 API 제공 (/api/auth/login)
- NextAuth에서 authorize 함수 내에서 로그인 API 호출
- 로그인 성공 시 JWT를 세션에 저장 후 클라이언트가 사용
NextAuth 설정 (auth.ts)
import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; export const authOptions = { providers: [ CredentialsProvider({ name: "Credentials", credentials: { username: { label: "Username", type: "text" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(credentials), }); const user = await res.json(); if (!res.ok) throw new Error(user.message); return user; // JWT or session info }, }), ], callbacks: { async jwt({ token, user }) { if (user) token.accessToken = user.accessToken; return token; }, async session({ session, token }) { session.accessToken = token.accessToken; return session; }, }, secret: process.env.NEXTAUTH_SECRET, }; export default NextAuth(authOptions);
3. API 요청 - Axios Instance + React Query 활용
Next.js 클라이언트 및 서버에서 Spring Boot API를 호출할 때 Axios Instance를 사용하면 편리하게 인증 정보를 관리할 수 있습니다.
Axios Instance 설정
import axios from "axios"; import { getSession } from "next-auth/react"; const apiClient = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_URL, headers: { "Content-Type": "application/json", }, }); // 요청 인터셉터: JWT 자동 추가 apiClient.interceptors.request.use(async (config) => { const session = await getSession(); if (session?.accessToken) { config.headers.Authorization = `Bearer ${session.accessToken}`; } return config; }); export default apiClient;
4. Middleware를 활용한 인증 처리
Next.js의 Middleware를 활용하여 인증이 필요한 페이지에 접근을 제한할 수 있습니다.
middleware.ts 예제
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { getToken } from "next-auth/jwt"; export async function middleware(req: NextRequest) { const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET }); if (!token) { return NextResponse.redirect(new URL("/login", req.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard/:path*"], };
5. 환경 변수 설정
.env.local 파일을 생성하여 다음과 같이 설정합니다:
NEXTAUTH_SECRET=your_secret_key NEXT_PUBLIC_API_URL=http://localhost:8080/api
6. 프로젝트 디렉토리 구조
Next.js 15 디렉토리 구조
/frontend │── src/ │ ├── app/ │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── dashboard/ │ │ │ ├── page.tsx │── components/ │── lib/ │ ├── apiClient.ts │── middleware.ts │── pages/api/auth/[...nextauth].ts │── styles/ │── .env.local
Spring Boot 3.3 디렉토리 구조
/backend │── src/ │ ├── main/java/com/example/demo/ │ │ ├── controller/ │ │ ├── service/ │ │ ├── security/ │ │ ├── repository/ │ │ ├── model/ │── resources/ │ ├── application.properties
NextAuth.js → Spring Boot API와 연동하여 JWT 또는 세션 기반 인증 구현
Axios Instance + React Query → API 호출을 최적화하고 캐싱 관리
Middleware → 보호된 페이지 접근을 제한
환경 변수 설정 → API URL 및 보안 정보 관리
2. Spring Boot 3.3 백엔드 설정
프로젝트 생성
Spring Boot 프로젝트를 생성할 때, Spring Web, Spring Security, Spring Boot JPA, MySQL Driver 등의 의존성을 추가합니다.
application.properties 설정
server.port=8080 spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=yourpassword spring.jpa.hibernate.ddl-auto=update spring.security.jwt.secret=your_jwt_secret_key spring.security.jwt.expiration=3600000
Security 설정 (SecurityConfig.java)
package com.example.demo.security; 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.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); return http.build(); } }
로그인 API (AuthController.java)
package com.example.demo.controller; import com.example.demo.model.LoginRequest; import com.example.demo.model.LoginResponse; import com.example.demo.service.AuthService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/auth") @RequiredArgsConstructor public class AuthController { private final AuthService authService; @PostMapping("/login") public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) { return ResponseEntity.ok(authService.authenticate(request)); } }
JWT 인증 서비스 (AuthService.java)
package com.example.demo.service; import com.example.demo.model.LoginRequest; import com.example.demo.model.LoginResponse; import org.springframework.stereotype.Service; @Service public class AuthService { public LoginResponse authenticate(LoginRequest request) { // 실제 인증 로직 구현 (DB 조회 후 검증) String token = "mock-jwt-token"; // JWT 생성 로직 적용 필요 return new LoginResponse(token); } }
댓글 ( 0)
댓글 남기기