로그인, 로그아웃, 자동 로그인
Firebase Authentication의 signInWithEmailAndPassword() 함수를 사용하여 이메일과 비밀번호로 로그인합니다.
signOut() 함수로 로그아웃을 하고,
signInWithEmailAndPassword()는 onAuthStateChanged() 함수로 로그인 상태를 알 수 있습니다.
로그인에 성공하면 전체 등록된 사용자의 프로필을 가져옵니다. 이때 로그인한 사용자의 프로필도 가져옵니다.
로그인 버튼과 로그아웃 버튼을 App-bar에 둡니다.
로그인 상태에 따라 메뉴 항목이 다르게 나타납니다.
Firebase Authentication 사용자 인증
signInWithEmailAndPassword()는
Firebase Authentication에서 사용자가 이메일과 비밀번호로 로그인할 수 있게 해주는 함수로서
createUserWithEmailAndPassword()로 생성된 계정에 대해 이메일과 비밀번호를 사용해 로그인하는 데 사용합니다.
signOut()은
Firebase Authentication에서 제공하는 함수로, 현재 로그인된 사용자를 로그아웃시키는 역할을 합니다.
Firebase Authentication에서 로그아웃하려면 signOut() 함수를 사용합니다.
- Firebase의 인증 세션을 종료시킵니다.
- 브라우저에 저장된 로그인 정보를 제거합니다.
- 로그아웃 후에는 getAuth().currentUser가 null이 됩니다.
onAuthStateChanged는
Firebase Authentication에서 현재 로그인된 사용자의 상태를 실시간으로 감지할 수 있게 해주는 리스너 함수입니다.
사용자가 로그인하거나 로그아웃할 때마다 자동으로 실행됩니다.
앱이 시작될 때 로그인 상태인지 아닌지를 확인하는 데 가장 중요한 함수입니다.
사용자 인증
로그인은 로그인 페이지에서 합니다.
로그 아웃은 앱의 app-bar에 로그아웃 버튼이 있어 이것을 누르면 로그아웃 합니다.
로그인 상태는 앱을 시작할 때 main.js에서 onAuthStateChanged로 확인합니다.
로그인 전과 후의 메뉴 항목은 다릅니다.
로그인, 로그아웃 - App.vue의 template
Login.vue
<!-- src/views/Login.vue -->
<template>
<v-container fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="10" md="6">
<v-card elevation="10" class="pa-4">
<v-card-title class="text-h6 font-weight-bold">로그인</v-card-title>
<v-card-text>
<v-form @submit.prevent="onLogin" v-model="formValid" ref="formRef">
<v-text-field
v-model="email"
label="이메일"
type="email"
:rules="emailRules"
prepend-inner-icon="mdi-email"
required
/>
<v-text-field
v-model="password"
label="비밀번호"
type="password"
:rules="passwordRules"
prepend-inner-icon="mdi-lock"
required
/>
<v-btn :loading="auth.loading" type="submit" color="primary" class="mt-4" block>
로그인
</v-btn>
</v-form>
</v-card-text>
<v-card-actions class="justify-center">
<RouterLink to="/register">계정이 없으신가요?</RouterLink>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script setup>
import { ref } from 'vue';
import { useAuthStore } from '@/stores/authStore';
const auth = useAuthStore();
const email = ref('');
const password = ref('');
const formRef = ref(null);
const formValid = ref(false);
const emailRules = [
(v) => !!v || '이메일을 입력해주세요.',
(v) => /.+@.+\..+/.test(v) || '올바른 이메일 형식이 아닙니다.',
];
const passwordRules = [
(v) => !!v || '비밀번호를 입력해주세요.',
(v) => v.length >= 6 || '비밀번호는 최소 6자 이상이어야 합니다.',
];
const onLogin = () => {
if (formRef.value?.validate()) {
auth.login(email.value, password.value);
}
};
</script>
로그인, 로그아웃, 자동 로그인 - authStore
// 로그인
const login = async (email, password) => {
try {
loading.value = true;
const userCredential = await signInWithEmailAndPassword(auth, email, password);
user.value = userCredential.user;
fetchProfiles();
router.push('/');
} catch (error) {
alert('로그인 실패: ' + error.message);
} finally {
loading.value = false;
}
};
// 로그아웃
const logout = async () => {
try {
if (user.value) {
await signOut(auth);
router.push('/');
user.value = null;
}
} catch (error) {
alert('로그아웃 실패: ' + error.message);
}
};
// 로그인 상태 유지
const initializeAuth = () => {
onAuthStateChanged(auth, async (currentUser) => {
user.value = currentUser;
if (currentUser) {
fetchProfiles();
}
});
};
자동 로그인 - main.js
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia'; // Pinia import
import 'vuetify/styles';
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
import { aliases, mdi } from 'vuetify/iconsets/mdi' // 추가
import '@mdi/font/css/materialdesignicons.css'
import router from './router';
import { useAuthStore } from "@/stores/authStore";
const vuetify = createVuetify({
components,
directives,
icons: {
defaultSet: 'mdi', // 기본 아이콘 셋을 mdi로 설정
aliases,
sets: {
mdi,
},
},
});
const app = createApp(App);
app.use(createPinia()); // Pinia 플러그인 사용
app.use(vuetify);
app.use(router);
const authStore = useAuthStore();
authStore.initializeAuth(); // 자동 로그인 실행
app.mount('#app');
App.vue
<!-- src/App.vue -->
<template>
<v-app>
<!-- App Bar -->
<v-app-bar app color="primary" dark>
<v-app-bar-nav-icon @click="drawer = !drawer" />
<v-toolbar-title>실시간 채팅</v-toolbar-title>
<v-spacer />
<div v-if="!auth.isAuthenticated">
<v-btn icon to="/login" title="로그인">
<v-icon>mdi-login</v-icon>
</v-btn>
</div>
<div v-else>
<v-btn icon @click="auth.logout" title="로그아웃">
<v-icon>mdi-logout</v-icon>
</v-btn>
</div>
</v-app-bar>
<!-- Navigation Drawer -->
<v-navigation-drawer app v-model="drawer">
<v-list nav dense>
<v-list-item
v-for="item in menuItems"
:key="item.title"
:to="item.to"
link
@click="drawer = !drawer"
>
<v-list-item-title>
<v-icon start>{{ item.icon }}</v-icon>
{{ item.title }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-navigation-drawer>
<!-- Main Content -->
<v-main>
<v-container>
<router-view />
</v-container>
</v-main>
<!-- Footer -->
<v-footer app color="primary" dark>
<v-col class="text-center">© 2025 My App</v-col>
</v-footer>
</v-app>
</template>
<script setup>
import { ref, computed } from 'vue';
import { useAuthStore } from '@/stores/authStore';
const auth = useAuthStore();
const drawer = ref(false);
// 메뉴 항목 배열
// 로그인 상태에 따라 메뉴 항목 다르게 구성
const menuItems = computed(() => {
if (auth.user) {
return [
{ title: '홈', icon: 'mdi-home', to: '/' },
{ title: '채팅룸', icon: 'mdi-chat', to: '/chatList' },
{ title: '새채팅', icon: 'mdi-chat-plus', to: '/startChat' },
{ title: '계정 설정', icon: 'mdi-account-cog', to: '/profile' },
];
} else {
return [
{ title: '홈', icon: 'mdi-home', to: '/' },
{ title: '로그인', icon: 'mdi-login', to: '/login' },
{ title: '계정 만들기', icon: 'mdi-account-plus', to: '/register' },
];
}
});
</script>
<style scoped>
.main-content {
display: flex;
flex-direction: column;
min-height: calc(100vh - 64px - 64px); /* AppBar와 Footer의 높이 */
}
</style>
'Vue 3 + Firebase 기반 실시간 채팅 앱 개발' 카테고리의 다른 글
9. Vue 3 + Firebase 기반 실시간 채팅 앱 v-chat 개발 - 구글 계정으로 로그인 (0) | 2025.05.08 |
---|---|
8. Vue 3 + Firebase 기반 실시간 채팅 앱 v-chat 개발 - 비밀번호 변경, 비밀번호 재설정 (0) | 2025.05.08 |
6. Vue 3 + Firebase 기반 실시간 채팅 앱 v-chat 개발 - 계정 만들기 및 계정 정보 설정 (0) | 2025.05.06 |
5. Vue 3 + Firebase 기반 실시간 채팅 앱 v-chat 개발 - 라우터 및 레이아웃 (1) | 2025.05.06 |
4. Vue 3 + Firebase 기반 실시간 채팅 앱 v-chat 개발 - 프로젝트 만들기 (1) | 2025.05.06 |