[BroBean] BroBean 프로젝트 #12 인증 상태 복구와 Nuxt Plugin 실행 순서 제어
🔐 로그인 이후에도 사용자를 유지하기: 인증 상태 복구와 Nuxt Plugin 실행 순서
앞선 글에서는 BroBean의 개인/커플 모드를 분리하고, Pinia Store를 이용해 현재 사용자가 어떤 모드로 서비스를 이용하고 있는지 관리하는 구조를 구현했다.
이제 실제 회원가입과 로그인 백엔드 로직을 연결하면서 한 단계 더 중요한 문제가 드러났다.
로그인 자체는 정상적으로 동작했다.
회원가입도 정상적으로 처리되고, 로그인 API를 호출하면 서버에서도 사용자 정보를 정상적으로 반환했다.
문제는 그 다음이었다.
브라우저에서 페이지를 새로고침하면 프론트에서 가지고 있던 사용자 정보가 사라졌다.
결국 로그인 직후에는 정상적으로 보이던:
- 사용자 이메일
- 농장 정보
- 닉네임
- 파트너 정보
- 농장 경험치
- 커플 연결 상태
등의 정보가 새로고침 이후에는 초기화되었다.
이 문제를 해결하는 과정에서 단순히 Pinia Store를 보완하는 것뿐만 아니라,
- 브라우저 새로고침과 메모리 상태
- 서버의 인증 상태와 클라이언트 상태
/api/auth/me를 통한 사용자 정보 복구- Nuxt Plugin의 실행 시점
- Plugin 간 의존성
- Axios Plugin과 Auth Plugin의 실행 순서
까지 연결해서 살펴보게 되었다.
이번 글에서는 이 과정을 정리해본다.
🔎 1. 로그인은 정상인데 새로고침하면 사용자가 사라진다
로그인 API 자체에는 문제가 없었다.
사용자가 로그인하면 서버에서는 인증을 처리하고, 프론트에서는 반환된 사용자 정보를 Pinia Store에 저장한다.
대략적인 흐름은 다음과 같다.
로그인 요청
↓
POST /api/auth/login
↓
서버 인증 성공
↓
사용자 정보 반환
↓
Pinia Auth Store 저장
↓
화면에서 사용자 정보 사용
로그인 직후에는 문제가 없다.
예를 들어 Store에는 다음과 같은 정보가 들어간다.
{
email: 'user@example.com',
farmName: '알콩달콩 부자농장',
name: '콩이',
nickname: '콩이언니',
partnerNickname: '콩이오빠',
isCoupleConnected: true
}
화면에서는 이 정보를 그대로 사용하면 된다.
문제는 브라우저에서 새로고침을 했을 때 발생한다.
로그인
↓
Pinia Store에 사용자 정보 저장
↓
페이지 정상 동작
↓
F5 / 새로고침
↓
Pinia Store 초기화
↓
사용자 정보 없음
여기서 중요한 것은 인증 자체가 사라진 것과 프론트의 사용자 상태가 사라진 것은 다른 문제라는 점이다.
서버 측 인증 상태가 정상적으로 유지되고 있더라도 클라이언트의 메모리에 올라가 있던 Store 데이터는 새로고침 과정에서 다시 만들어진다.
즉, 클라이언트 Store를 인증 정보의 영구 저장소처럼 사용하는 구조에는 한계가 있다.
🧠 2. Pinia Store는 인증의 원본 데이터가 아니다
이번 문제를 정리하면서 가장 중요하게 본 부분이다.
Pinia Store는 애플리케이션 내부에서 사용자 상태를 공유하기 위한 상태 관리 계층이다.
예를 들어:
const authStore = useAuthStore()
authStore.updateProfile({
email: data.email,
farmName: data.farmName,
nickname: data.nickname
})
이렇게 저장한 데이터는 애플리케이션이 실행되는 동안 여러 컴포넌트에서 편리하게 사용할 수 있다.
하지만 브라우저가 새로고침되면 애플리케이션이 다시 초기화된다.
따라서:
Pinia Store
≠
영구적인 인증 저장소
라고 보는 것이 적절하다.
실제 인증의 기준은 서버에 있어야 하고, 클라이언트의 Store는 현재 로그인한 사용자의 상태를 빠르게 참조하기 위한 캐시 또는 상태 표현 계층으로 사용하는 것이 자연스럽다.
결국 필요한 것은 새로고침 이후에도:
"현재 로그인한 사용자가 누구인지"
를 서버에게 다시 확인하고 Store를 복구하는 과정이다.
🔐 3. 서버의 현재 사용자 정보를 다시 조회한다
이 역할을 담당하는 API가 /api/auth/me다.
이 API의 목적은 단순하다.
현재 요청을 보낸 사용자가 누구인지 확인한다.
로그인 API가:
"로그인해 주세요."
↓
"인증되었습니다."
라는 흐름이라면,
/api/auth/me는:
"현재 인증된 사용자가 누구인가요?"
↓
"현재 사용자는 이 사용자입니다."
라는 역할을 한다.
따라서 페이지가 새로 로드되었을 때:
브라우저 실행
↓
현재 인증 상태 확인
↓
/api/auth/me 요청
↓
사용자 정보 반환
↓
Pinia Store 복구
↓
화면 렌더링
이라는 구조를 만들 수 있다.
이렇게 하면 Store가 새로 생성되더라도 서버의 인증 상태를 기준으로 다시 사용자 정보를 구성할 수 있다.
🧩 4. 이 작업을 어디에서 실행할 것인가?
여기서 Nuxt의 Plugin을 활용했다.
페이지마다 다음과 같은 코드를 작성하는 방식도 가능하다.
const { data } = await $api.get('/api/auth/me')
authStore.updateProfile(data)
하지만 이 방식은 문제가 있다.
사용자 정보가 필요한 페이지마다 인증 복구 로직이 반복될 수 있기 때문이다.
예를 들어:
pages/index.vue
pages/farm.vue
pages/account-book.vue
pages/savings.vue
pages/mypage.vue
각각에서 /api/auth/me를 호출하게 만들면 인증 상태 복구 로직이 특정 페이지에 종속된다.
이보다는 애플리케이션이 시작될 때 한 번 인증 상태를 확인하고, 공통 Store를 복구하는 편이 구조적으로 더 적합하다.
그래서 Nuxt의 plugins 디렉토리에 인증 초기화 Plugin을 추가했다.
plugins/
├── axios.ts
└── auth.ts
🚀 5. auth.ts에서 인증 상태 복구
실제 구현은 다음과 같은 형태다.
export default defineNuxtPlugin(async (nuxtApp) => {
const authStore = useAuthStore()
const { $api } = useNuxtApp()
const { formatDate, calculateDaysTogether } = useDateUtils()
// 서버 사이드에서는 실행하지 않는다.
if (import.meta.server) return
const route = useRoute()
// 인증 관련 페이지에서는 사용자 정보 조회를 생략한다.
if (route.path.startsWith('/auth/')) {
return
}
try {
const { data } = await $api.get('/api/auth/me')
if (data && data.email) {
authStore.updateProfile({
email: data.email,
farmName: data.farmName,
name: data.name,
nickname: data.nickname,
partnerNickname: data.partnerNickname,
isCoupleConnected: data.isPartnerVerified,
farmStartDate: formatDate(data.farmCreatedAt),
daysTogether: calculateDaysTogether(data.farmCreatedAt),
farmExp: data.farmExperience,
})
}
} catch (error) {
authStore.logout()
}
})
이 Plugin의 핵심 역할은 크게 세 가지다.
1. 클라이언트에서만 실행
2. 현재 인증 상태 조회
3. 사용자 정보를 Auth Store에 복구
🖥️ 6. SSR에서는 실행하지 않는다
첫 번째로 고려한 부분은 SSR이다.
Nuxt는 기본적으로 서버와 클라이언트 양쪽에서 코드를 실행할 수 있다.
하지만 이번 인증 상태 복구 로직은 브라우저에서 이미 유지되고 있는 인증 상태를 확인하고 클라이언트 Store를 복구하기 위한 목적이다.
따라서 다음 조건을 사용했다.
if (import.meta.server) return
이렇게 하면 서버에서 Plugin이 실행될 때는 바로 종료되고, 클라이언트 환경에서만 인증 복구 로직이 수행된다.
즉:
Nuxt Plugin 실행
↓
┌──────────────────┐
│ Server 환경인가? │
└────────┬─────────┘
│
Yes ↓
return
│ No
↓
/api/auth/me 요청
↓
Auth Store 복구
이런 실행 흐름을 의도한 것이다.
🔑 7. /auth/에서는 /api/auth/me 요청을 막았다
또 하나 추가한 부분은 인증 페이지 예외 처리다.
const route = useRoute()
if (route.path.startsWith('/auth/')) {
return
}
현재 /auth/ 아래에는:
/auth/login
/auth/signup
/auth/forgot-password
등의 페이지가 있다.
이 페이지들은 아직 인증 과정 자체를 수행하는 화면이다.
특히 로그인이나 회원가입 페이지에서 애플리케이션 초기화 과정으로 /api/auth/me를 호출하는 것은 불필요한 요청이 될 수 있다.
예를 들어 로그인하지 않은 사용자가 로그인 페이지에 접근했을 때:
/login 페이지 진입
↓
auth.ts 실행
↓
/api/auth/me 요청
↓
인증 정보 없음
↓
logout 처리
같은 불필요한 흐름이 발생할 수 있다.
그래서 인증 페이지에서는 아예 사용자 복구 요청을 실행하지 않도록 했다.
⚠️ 8. 그런데 여기서 예상하지 못한 문제가 발생했다
auth.ts를 추가하고 실행했더니 이번에는 다른 오류가 발생했다.
문제는:
const { $api } = useNuxtApp()
부분이었다.
$api가 undefined인 상태로 접근되는 문제가 발생했다.
원인을 추적해보니 auth.ts가 사용하는 $api는 다른 Plugin인 axios.ts에서 등록하고 있었다.
구조는 대략 다음과 같다.
plugins/
├── axios.ts
│ └── $api 등록
│
└── auth.ts
└── $api 사용
논리적으로 보면 당연히:
axios.ts
↓
$api 등록
↓
auth.ts
↓
$api 사용
순서가 되어야 한다.
그런데 Plugin이 여러 개 존재한다고 해서 내가 의도한 의존성 순서가 자동으로 보장되는 것은 아니었다.
이 지점에서 Nuxt Plugin의 실행 순서에 대해 확인할 필요가 생겼다.
🧩 9. Nuxt Plugin은 파일 순서의 영향을 받는다
Nuxt의 Plugin 시스템에서는 Plugin 파일을 단순히 독립적인 코드 조각으로 보는 것보다 애플리케이션 초기화 단계에서 실행되는 Plugin 집합으로 이해하는 것이 좋다.
특히 Plugin 간 의존성이 존재한다면 실행 순서를 명시적으로 관리해야 한다.
이번 구조에서는:
auth.ts
↓
$api 필요
이기 때문에 axios.ts가 먼저 실행되어야 한다.
그런데 파일 이름이:
axios.ts
auth.ts
라고 되어 있다고 해서 모든 상황에서 내가 생각한 의존 관계를 코드만 보고 명확하게 표현할 수 있는 것은 아니다.
실제 프로젝트에서는 Plugin이 많아질수록 실행 순서를 의식적으로 관리할 필요가 있다.
🛠️ 10. Plugin 파일 이름으로 실행 순서를 명확하게 했다
이번 프로젝트에서는 가장 간단한 방식으로 파일 이름에 숫자 Prefix를 붙였다.
기존:
plugins/
├── axios.ts
└── auth.ts
변경:
plugins/
├── 01.axios.ts
└── auth.ts
이렇게 하면 파일 정렬 순서를 기준으로 Axios Plugin이 먼저 실행되도록 만들 수 있다.
결과적으로 실행 흐름은:
01.axios.ts
↓
$api 생성
↓
auth.ts
↓
$api.get('/api/auth/me')
↓
Auth Store 복구
가 된다.
이번 문제에서는 별도의 복잡한 의존성 시스템을 추가하기보다는 파일 이름만으로 초기화 순서를 명확하게 표현하는 방식이 충분했다.
🧠 11. 여기서 중요한 것은 "순서"보다 "의존성"이었다
이번 작업에서 더 중요하게 느껴졌던 부분은 단순히:
Plugin은 파일 이름 순서대로 실행된다.
라는 사실 자체가 아니었다.
실제 개발에서 중요한 것은 어떤 Plugin이 어떤 Plugin에 의존하고 있는가를 명확하게 만드는 것이다.
현재 구조를 보면:
axios Plugin
└── $api 제공
↓
auth Plugin
└── $api 사용
이라는 의존성이 존재한다.
따라서 이것을 코드 구조에서도 명확하게 표현해야 한다.
01.axios.ts
auth.ts
라는 이름은 단순히 실행 순서를 바꾸는 것뿐만 아니라:
"auth Plugin은 axios 초기화 이후에 실행되어야 한다."
라는 프로젝트의 초기화 규칙을 파일 구조에 남기는 역할도 한다.
Plugin이 많아지면 이런 초기화 순서가 애플리케이션 부팅 과정의 일부가 된다.
🔄 12. 최종적인 인증 상태 복구 흐름
이번 작업을 통해 로그인 이후의 상태 흐름은 다음처럼 정리했다.
[로그인]
사용자
↓
POST /api/auth/login
↓
서버 인증
↓
인증 상태 유지
↓
사용자 정보 반환
↓
Pinia Auth Store 저장
[새로고침]
브라우저 Reload
↓
Nuxt Application 초기화
↓
Pinia Store 초기화
↓
01.axios.ts
↓
$api 초기화
↓
auth.ts
↓
/api/auth/me
↓
서버에서 현재 사용자 확인
↓
Auth Store 복구
↓
애플리케이션에서 사용자 정보 사용
이렇게 보면 Pinia가 인증을 담당하는 것이 아니라 각 계층이 서로 다른 역할을 담당하고 있다는 것이 명확해진다.
Server
└── 인증 상태의 기준
API
└── 현재 사용자 정보 제공
Axios Plugin
└── API Client 초기화
Auth Plugin
└── 초기 인증 상태 복구
Pinia
└── 클라이언트 전역 상태 관리
각각의 역할을 분리해두면 인증 흐름을 이해하기도 쉬워진다.
🧱 13. 인증 Plugin에서 Store를 복구하는 이유
여기서 한 가지 더 생각해볼 수 있는 부분이 있다.
왜 /api/auth/me의 응답을 바로 각 페이지에서 사용하는 것이 아니라 Auth Store에 다시 넣을까?
BroBean에서는 사용자 정보가 여러 영역에서 사용되기 때문이다.
예를 들어:
헤더
└── 사용자 닉네임
사이드바
└── 농장 이름
마이페이지
└── 프로필
농장 화면
└── 농장 경험치
커플 화면
└── 파트너 정보
가계부
└── 현재 사용자 정보
모든 화면에서 각각 /api/auth/me를 호출한다면 API 요청과 상태 관리가 분산된다.
반대로:
/api/auth/me
↓
Auth Store
↓
여러 컴포넌트에서 공유
구조를 사용하면 인증된 사용자에 대한 클라이언트 상태를 하나의 지점에서 관리할 수 있다.
⚡ 14. 매번 사용자 정보를 API로 가져오는 것과의 차이
물론 모든 상황에서 Store만 사용하는 것도 적절하지 않다.
예를 들어 사용자의 정보가 서버에서 변경되었다면 기존 Store는 이전 값을 가지고 있을 수 있다.
따라서:
Auth Store
= 현재 클라이언트에서 사용하는 사용자 상태
라고 보는 것이 적절하다.
필요한 경우 서버에서 최신 데이터를 다시 가져와 Store를 갱신할 수 있다.
이번 구조에서는 애플리케이션 초기화 시점에:
/api/auth/me
↓
Auth Store 초기화
를 수행하기 때문에 새로고침 이후의 초기 상태를 서버 기준으로 다시 맞춰줄 수 있다.
🧩 15. 인증 페이지에서 API 호출을 제외한 이유
이번 구현에서 /auth/ 경로를 예외 처리한 것도 단순한 최적화 이상의 의미가 있다.
인증 페이지는 일반적인 서비스 페이지와 lifecycle이 다르다.
로그인
↓
인증 성공
↓
서비스 영역 진입
이라는 흐름이기 때문에 인증 이전 단계에서는 사용자 정보를 조회하는 것 자체가 의미가 없을 수 있다.
특히 로그인 페이지에서:
/api/auth/me
를 먼저 호출하는 것보다 로그인 액션 자체에 인증 확인 책임을 두는 것이 더 명확하다.
따라서 현재 구조에서는:
/auth/*
→ Auth Plugin 인증 복구 생략
그 외 서비스 페이지
→ Auth Plugin 인증 상태 확인
으로 분리했다.
🧪 16. 실제로 확인해야 했던 테스트 케이스
인증 상태 복구를 구현하고 나서는 단순히 로그인 성공만 확인해서는 충분하지 않았다.
최소한 다음 케이스를 확인해야 했다.
로그인 직후
로그인 성공
→ 사용자 정보 정상 표시
새로고침
새로고침
→ 사용자 정보 유지
다른 페이지 이동 후 새로고침
농장 페이지 진입
→ 새로고침
→ 사용자 정보 복구
로그아웃
로그아웃
→ Auth Store 초기화
→ 인증 페이지 이동
비로그인 상태에서 서비스 접근
인증 정보 없음
→ /api/auth/me 실패
→ logout 처리
로그인 페이지 진입
/auth/login
→ /api/auth/me 요청 생략
Plugin 초기화 순서
01.axios.ts
→ $api 초기화
auth.ts
→ $api 사용
이런 테스트를 통해 단순히 "동작한다"가 아니라 애플리케이션 초기화 흐름까지 정상적으로 구성되었는지 확인했다.
🌙 17. SSR과 Client 초기화 시점을 함께 고려해야 한다
Nuxt를 사용하면서 인증 관련 로직을 작성할 때 특히 신경 써야 하는 부분이 SSR이다.
Nuxt에서는 페이지가 단순히 브라우저에서 처음부터 실행되는 구조가 아니다.
Server Rendering
↓
HTML 생성
↓
Client Hydration
↓
Vue Application 실행
과 같은 흐름이 존재한다.
따라서 인증 정보를 어디에서 확인할 것인지에 따라:
- 서버에서 인증 상태를 처리할 것인지
- 클라이언트에서 처리할 것인지
- SSR과 CSR 양쪽에서 처리할 것인지
를 구분해야 한다.
이번 구현의 auth.ts는 클라이언트에서 Pinia Store를 복구하는 목적이므로:
if (import.meta.server) return
을 사용해 서버 실행을 제외했다.
프로젝트의 인증 구조가 확장되면서 SSR 단계에서 인증 사용자 정보를 필요로 하게 된다면 이후에는 서버 측 인증 처리까지 별도로 고려할 필요가 있다.
🔐 18. 인증 상태를 "저장"하는 것보다 "복구"하는 관점
이번 작업에서 개인적으로 중요하게 정리한 부분이다.
새로고침 이후 사용자 정보가 사라지는 문제를 단순히:
Pinia 데이터를 어떻게 유지하지?
라는 문제로 접근하면 결국 Store를 LocalStorage에 저장하는 방향만 생각하기 쉽다.
하지만 실제 인증 시스템에서는:
클라이언트 상태를 영구 저장
보다:
서버의 인증 상태를 기준으로
↓
클라이언트 상태를 복구
하는 방식으로 바라보는 것이 더 자연스럽다.
즉:
Auth Source of Truth
│
▼
Server
│
▼
/api/auth/me
│
▼
Auth Store
│
▼
UI
구조가 된다.
Pinia는 인증의 원본이 아니라 서버 상태를 애플리케이션에서 사용하기 편한 형태로 유지하는 역할을 담당한다.
🧩 19. Plugin이 많아질수록 초기화 순서를 의식해야 한다
처음에는 Plugin이 몇 개 없기 때문에 각각의 파일이 독립적으로 동작하는 것처럼 보인다.
하지만 프로젝트가 커지면서:
plugins/
├── 01.axios.ts
├── auth.ts
├── api-error.ts
├── notification.ts
├── websocket.ts
└── analytics.ts
처럼 Plugin이 증가할 수 있다.
이때 Plugin 간에 의존성이 생기기 시작한다.
예를 들어:
axios
↓
auth
↓
notification
↓
websocket
같은 초기화 흐름이 만들어질 수 있다.
이런 상황에서는 Plugin을 단순한 유틸리티 파일로 생각하기보다 애플리케이션 부팅 과정의 일부로 관리해야 한다.
특히 어떤 Plugin이 제공하는 $api, $socket, $auth 같은 runtime dependency를 다른 Plugin이 사용한다면 실행 순서 또는 명시적인 dependency 설정을 함께 고려해야 한다.
🛠️ 20. 파일명 Prefix 방식의 장점
이번에는 간단하게:
01.axios.ts
auth.ts
방식으로 해결했다.
이 방식의 장점은 프로젝트 구조만 봐도 초기화 순서를 어느 정도 파악할 수 있다는 것이다.
01.axios.ts
라는 이름만 봐도:
"초기화 단계에서 먼저 실행되어야 하는 Plugin"
이라는 의도를 읽을 수 있다.
특히 Plugin이 많지 않은 프로젝트에서는 별도의 복잡한 추상화 없이도 의존성을 명확하게 표현할 수 있다.
⚠️ 21. 하지만 파일명 순서에 모든 의존성을 맡기면 안 된다
그렇다고 Plugin 파일 이름에 모든 의존성을 몰아넣는 방식이 항상 좋은 것은 아니다.
예를 들어 Plugin이 수십 개가 되고:
01
02
03
04
05
...
처럼 번호가 계속 증가한다면 파일 구조 자체가 실행 순서 관리에 지나치게 의존하게 된다.
또한 특정 Plugin이 다른 여러 Plugin에 의존하기 시작하면 단순한 숫자 순서만으로 관계를 표현하기 어려워질 수 있다.
따라서 현재 BroBean처럼 구조가 단순한 단계에서는 Prefix 방식으로 충분하지만, 프로젝트 규모가 커진다면 Nuxt가 제공하는 Plugin dependency 관리 방식이나 초기화 구조 자체를 재검토할 필요가 있다.
중요한 것은:
"무조건 숫자를 붙인다."
가 아니라,
"Plugin 사이의 초기화 의존성을 명확하게 관리한다."
는 것이다.
📌 22. 이번 작업에서 정리한 각 계층의 책임
이번 인증 상태 복구를 구현하면서 각 기술의 역할을 다시 정리할 수 있었다.
| 계층 | 역할 |
|---|---|
| Backend | 인증 상태와 사용자 정보의 기준 |
/api/auth/me | 현재 인증 사용자 조회 |
| Axios Plugin | 공통 API Client 제공 |
| Auth Plugin | 애플리케이션 초기 인증 상태 복구 |
| Pinia | 클라이언트 전역 사용자 상태 관리 |
| Component | Store 상태를 화면에 표현 |
이렇게 책임을 나누면 인증 상태가 변경되는 흐름도 명확해진다.
Backend
↓
API
↓
Auth Plugin
↓
Pinia
↓
Component
🚀 23. 앞으로 인증 구조를 확장한다면
현재 구현은 BroBean의 로그인/회원가입 기능을 실제 서비스 흐름에 연결하기 위한 초기 구조다.
앞으로 인증 기능이 확장된다면 다음과 같은 부분도 고려할 수 있다.
🔐 인증 만료 처리
현재 /api/auth/me가 실패하면:
authStore.logout()
을 호출한다.
향후에는 access token이나 session이 만료된 경우를 구분해 자동 갱신 구조를 추가할 수 있다.
🔄 사용자 정보 자동 동기화
사용자가 마이페이지에서 프로필을 수정하면:
프로필 수정 API
↓
서버 업데이트
↓
Auth Store 갱신
흐름으로 최신 상태를 즉시 반영할 수 있다.
🚫 인증이 필요한 페이지 Middleware
현재 Plugin은 애플리케이션 전체에서 인증 상태를 복구하는 역할에 가깝다.
반면 특정 페이지에 인증이 반드시 필요하다면:
Middleware
↓
인증 여부 확인
↓
미인증 → 로그인 페이지 이동
같은 접근 제어를 별도로 구성하는 것이 적절하다.
즉:
Plugin
→ 인증 상태 초기화 / 복구
Middleware
→ 페이지 접근 제어
처럼 책임을 나눌 수 있다.
🎯 마무리
이번 작업은 단순히 "새로고침하면 Pinia 데이터가 사라진다"는 문제를 해결하는 작업에서 시작했지만, 실제로는 인증 상태를 어떤 계층에서 관리하고 애플리케이션 초기화 과정에서 어떻게 복구할 것인가를 정리하는 과정이었다.
최종적인 구조는 다음과 같다.
로그인
↓
Backend 인증
↓
인증 상태 유지
↓
Pinia에 사용자 상태 저장
새로고침
↓
Nuxt Application 초기화
↓
01.axios.ts
↓
$api 초기화
↓
auth.ts
↓
/api/auth/me
↓
사용자 정보 조회
↓
Pinia Auth Store 복구
↓
서비스 화면 사용
그리고 이번 과정에서 함께 확인한 또 하나의 중요한 부분은 Nuxt Plugin 역시 애플리케이션 초기화 순서의 일부로 관리해야 한다는 것이었다.
특히:
axios.ts
↓
auth.ts
처럼 명확한 의존 관계가 존재한다면 Plugin의 실행 순서를 고려하지 않고 구현할 경우 런타임에서 $api 같은 dependency가 준비되지 않은 상태로 접근되는 문제가 발생할 수 있다.
이번에는 01.axios.ts처럼 파일명 Prefix를 사용하는 간단한 방식으로 해결했지만, 중요한 것은 숫자 자체가 아니라 Plugin 간 의존성을 코드 구조에 명확하게 표현하는 것이라고 생각한다.
결국 인증 상태는 단순히 클라이언트에 데이터를 "저장해두는 것"으로 끝나는 문제가 아니다.
Server의 인증 상태
↓
현재 사용자 조회
↓
Client 상태 복구
↓
UI에서 사용
이라는 흐름으로 설계해야 새로고침이나 애플리케이션 재초기화가 발생하더라도 사용자 경험을 안정적으로 유지할 수 있다.
BroBean 역시 이번 인증 구조를 기반으로 이후에는:
- 🔐 로그인 상태 유지
- 🔄 인증 만료 및 갱신
- 👤 사용자 프로필 동기화
- 💑 커플 인증 상태 관리
- 🛡️ 인증 페이지 Middleware
- 📱 모바일 환경의 인증 상태 유지
등을 단계적으로 확장할 예정이다.
이번 작업을 통해 단순히 로그인 API를 연결하는 것과 서비스에서 지속적으로 유지되는 인증 흐름을 만드는 것은 다른 문제라는 점을 다시 확인할 수 있었다.
[BroBean] BroBean 프로젝트 #11 개인과 커플을 모두 위한 모드 분리 - Pinia 기반 개인/커플 모드 전환 구현
BroBean을 커플 전용 서비스에서 개인 사용자까지 사용할 수 있도록 확장하면서 개인 모드와 커플 모드를 분리하고, 헤더와 사이드 메뉴의 모드 전환 UI 및 Pinia 기반 상태 관리 구조를 구현한 과정
[BroBean] BroBean 프로젝트 #13 개인·커플 모드와 가계부 API 구현 - 쿼리 성능을 다시 돌아보다
BroBean의 개인·커플 모드 전환 기능과 씨앗심기·성장일지 백엔드 및 API를 구현하고, 월별 가계부 조회 쿼리를 작성하는 과정에서 쿼리 성능을 다시 고민해본 경험을 정리합니다.
