Nuxt.js 를 배워보자/⚙️ 3. Nuxt의 서버 사이드 기능 활용: 서버 API와 미들웨어

🔒 Nuxt 미들웨어 실습: admin 페이지에 로그인 체크 적용하기

_Blue_Sky_ 2025. 12. 5. 18:28
728x90

애플리케이션에 서버 API를 구축했으니, 이제 보안과 권한 관리를 시작할 차례입니다. Nuxt의 미들웨어(Middleware)는 사용자가 페이지에 접근하기 전, 또는 접근한 후에 특정 로직(예: 로그인 상태 확인, 권한 체크)을 실행하도록 해주는 강력한 기능입니다.

이번 실습에서는 전역 로그인 상태를 관리하고, 미들웨어를 사용하여 인증되지 않은 사용자가 /admin 페이지에 접근하는 것을 막고 /login 페이지로 리다이렉트시키는 방법을 구현해 봅시다.

1. 🔑 실습 1: 전역 인증 상태(useState) 관리

미들웨어에서 사용자 상태를 체크하려면, Nuxt의 useState 기능을 사용하여 전역적으로 접근 가능한 상태를 정의해야 합니다. 이는 Vuex나 Pinia 같은 별도의 라이브러리 없이 간단한 전역 상태를 관리할 때 유용합니다.

1.1. 전역 상태 파일 생성

  1. 프로젝트 루트에 composables 폴더 안에 useAuth.js 파일을 생성합니다.
    // composables/useAuth.js
    
    // 1. isLoggedIn 상태를 관리하는 함수 정의
    export const useAuth = () => {
      // useState를 사용하여 전역적이고 반응형인 상태를 정의합니다.
      // 초기값은 false (로그아웃 상태)
      const isLoggedIn = useState('isLoggedIn', () => false) 
    
      // 2. 로그인/로그아웃 처리를 위한 함수 정의
      const login = () => {
        isLoggedIn.value = true
      }
      const logout = () => {
        isLoggedIn.value = false
      }
    
      // 3. 필요한 값과 함수를 반환합니다.
      return {
        isLoggedIn,
        login,
        logout,
      }
    }
    

1.2. 로그인/로그아웃 페이지 생성

전역 상태를 테스트하고 미들웨어의 작동을 확인할 수 있는 페이지를 만듭니다.

  1. pages/login.vue 생성:
    <template>
      <div>
        <AppHeader />
        <h1>로그인 페이지</h1>
        <p v-if="!isLoggedIn">로그인이 필요합니다.</p>
        <button v-if="!isLoggedIn" @click="handleLogin" style="padding: 10px; background-color: green; color: white;">
          로그인 (상태 변경)
        </button>
        <button v-else @click="logout" style="padding: 10px; background-color: red; color: white;">
          로그아웃
        </button>
      </div>
    </template>
    <script setup>
    // useAuth 컴포저블 자동 임포트
    const { isLoggedIn, login, logout } = useAuth()
    const router = useRouter()
    
    const handleLogin = () => {
      login() // 전역 상태를 true로 변경
      alert('로그인 성공! 이제 /admin 페이지로 이동할 수 있습니다.')
      router.push('/admin') // 로그인 성공 후 admin 페이지로 이동
    }
    </script>
    

2. 📝 실습 2: 인증 미들웨어 구현 (middleware/)

이제 /admin 페이지에 접근할 때 로그인 상태를 체크하는 로직을 미들웨어로 작성합니다.

2.1. 미들웨어 파일 생성

  1. 프로젝트 루트에 middleware 폴더를 만들고, 그 안에 auth.js 파일을 생성합니다. (파일명은 곧 미들웨어 이름이 됩니다.)
    // middleware/auth.js
    
    // defineNuxtRouteMiddleware를 사용하여 미들웨어 함수를 정의합니다.
    export default defineNuxtRouteMiddleware((to, from) => {
      // to: 이동하려는 경로 객체
      // from: 현재 경로 객체
    
      // useAuth 컴포저블을 사용하여 전역 상태를 가져옵니다.
      const { isLoggedIn } = useAuth()
    
      // 1. 로그인 상태 확인
      if (isLoggedIn.value === false) {
        // 2. 로그인되어 있지 않다면
        alert('접근 권한이 없습니다. 로그인 페이지로 이동합니다.')
    
        // 3. /login 경로로 리다이렉트
        return navigateTo('/login') 
      }
    
      // 로그인되어 있다면, 아무것도 반환하지 않고 다음 경로로 진행합니다.
    })
    

3. 🎯 실습 3: 페이지에 미들웨어 적용

이제 보호해야 할 /admin 페이지를 만들고, 방금 만든 미들웨어를 적용합니다.

3.1. 관리자 페이지 생성 및 미들웨어 적용

  1. pages/admin.vue 파일을 생성합니다.
  2. <script setup> 블록에서 definePageMeta를 사용하여 미들웨어를 적용합니다.
    <template>
      <div>
        <AppHeader />
        <h1>관리자 페이지 (🔒 로그인 필요)</h1>
        <p>환영합니다. 이 페이지는 로그인된 사용자만 볼 수 있습니다.</p>
        <p>현재 상태: {{ isLoggedIn ? '로그인 됨' : '로그아웃 됨' }}</p>
        <button @click="logout" style="padding: 10px; background-color: red; color: white;">
          로그아웃
        </button>
      </div>
    </template>
    
    <script setup>
    // 미들웨어 이름 'auth'를 사용하여 이 페이지에 적용합니다.
    definePageMeta({
      middleware: ['auth'] 
    })
    
    const { isLoggedIn, logout } = useAuth()
    </script>
    

3.2. 최종 결과 확인

  1. 브라우저에서 http://localhost:3000/admin으로 바로 접속해 보세요.
    • 결과: 미들웨어가 작동하여 접근 경고 후 /login 페이지로 자동 리다이렉트됩니다.
  2. /login 페이지에서 "로그인" 버튼을 눌러 전역 상태를 변경합니다.
  3. 다시 /admin 페이지로 이동하면, 이제 미들웨어의 체크를 통과하여 페이지 내용이 정상적으로 표시됩니다.

📝 블로그 마무리: 안전한 라우팅의 시작

이번 실습을 통해 우리는 useState를 사용한 간단한 전역 인증 상태 관리와 이를 기반으로 특정 페이지의 접근을 제어하는 Nuxt 미들웨어 구현 방법을 배웠습니다. 이 패턴은 모든 사용자 권한 및 역할 기반 접근 제어의 기초가 됩니다.

728x90