React

 

 

Next.js 15 + Spring Boot 3.3 연동 방법

 

 

 

Next.js 15(App Router)과 Spring Boot 3.3을 연동할 때, 인증(Authentication) 및 API 통신을 고려해야 합니다. 일반적으로 NextAuth.jsAxios 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);
    }
}

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

Between two stools you fail to the ground. (두 가지 일을 한꺼번에 하려다가 모두 그르친다.)

댓글 ( 0)

댓글 남기기

작성