기존의 NavBar은 단순히 페이지 상단에 링크만 추가했는데, 이 NavBar을 좌측에 수직으로 배치하고, 아이콘 추가, 로그인 로그아웃 추가, 그리고 로그인 시 로그인 링크 대신 회원정보를 표기하도록 구현하려 한다. 그런데 쓰다보니 글이 좀 길어지는 느낌이라 이 포스트에서는 UI 구현까지만 하고, 다음 포스트에서 회원정보를 네비게이션 바에 표기및 로그아웃을 구현해보려 한다.
우선 아이콘과 함께 링크를 표기하기 위해 react-icons를 설치했다.
packages.json
"react-icons": "^5.2.1",
리액트에서 제공하는 아이콘들로, 아래 참고자료에 링크를 첨부하였다.
그리고 다음과 같이 아이콘들을 링크 텍스트 옆에 추가했다. 나중에 텍스트도 한글로 통일해야지.
<nav className="navbar">
<ul className="navbar-list">
<li className="navbar-item">
<Link to="/home" className="navbar-link">
<FaHome className="navbar-icon" /> Home
</Link>
</li>
<li className="navbar-item">
<Link to="/schedule" className="navbar-link">
<FaCalendarAlt className="navbar-icon" /> Schedule
</Link>
</li>
<li className="navbar-item">
<Link to="/subjectInfo" className="navbar-link">
<FaBook className="navbar-icon" /> SubjectInfo
</Link> </li>
<li className="navbar-item">
<Link to="/about" className="navbar-link">
<FaInfoCircle className="navbar-icon" /> About
</Link>
</li>
</ul>
</nav>
좌측에 수직으로 배치하기 위해 css를 수정한다.
NavBar.css
.navbar {
width: 250px;
background-color: #282c34;
color: white;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 20px;
position: fixed;
top: 0;
left: 0;
}
.navbar-title {
margin-bottom: 30px;
font-size: 24px;
font-weight: bold;
}
.navbar-list {
list-style-type: none;
padding: 0;
width: 100%;
margin: 0;
}
.navbar-item {
width: 100%;
}
.navbar-link {
display: flex;
align-items: center;
padding: 10px 20px;
color: white;
text-decoration: none;
transition: background-color 0.2s;
}
.navbar-link:hover {
background-color: #3b3f47;
}
.navbar-icon {
margin-right: 10px;
}
색상은 대충 설정
그리고 NavBar과 페이지가 겹치지 않고 분리되도록 App.css를 수정
App.css
.App {
text-align: left;
margin-left: 250px; /* 네비게이션 바의 너비만큼 여백 추가 */
padding: 20px;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
리액트 초기 설정에서 쓸데없는 부분도 삭제했다.
실행해보면 NavBar과 레이아웃이 수정된 것을 확인할 수 있다.
다음으로 로그인과 로그아웃 링크를 추가한다. 기본 라우트를 HomePage로 설정하고 /login만 로그인페이지로 이동하도록 설정.
App.js
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/" element={<HomePage />} />
<Route path="/home" element={<HomePage />} />
링크 추가
NavBar.js
<li className="navbar-item">
<Link to="/login" className="navbar-link">
<FaUser className="navbar-icon"/> login
</Link>
</li>
<li className="navbar-item">
<Link to="/logout" className="navbar-link">
<RiLogoutBoxRLine className="navbar-icon"/> logout
</Link>
</li>
그리고 디자인을 조금 더 수정하였다. 호버 시 색상과 shadow도 추가
NavBar.css 최종
.navbar {
width: 300px;
background-color: #282c34;
color: white;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 20px;
position: fixed;
top: 0;
left: 0;
}
.navbar-list {
list-style-type: none;
padding: 0;
width: 100%;
margin: 0;
}
.navbar-item {
width: 100%;
margin-bottom: 15px; /* 링크 간의 간격 설정 */
}
.navbar-link {
display: flex;
align-items: center;
padding: 10px 20px;
color: white;
text-decoration: none;
transition: background-color 0.2s;
font-size: 24px; /* 폰트 크기 설정 */
}
.navbar-link:hover {
background-color: #9370db;
box-shadow: 0 4px 8px rgba(106, 77, 171, 0.8); /* 더 진한 그림자 색상 추가 */
}
.navbar-icon {
margin-right: 10px;
font-size: 30px; /* 아이콘 크기 설정 */
}
다음으로 다소 허접한 로그인 페이지 디자인을 수정한다.
LoginPage.js 최종
// src/main/frontend/src/pages/LoginPgae.js
import React from 'react';
import './LoginPage.css'; // CSS 파일 import
import { RiKakaoTalkFill } from 'react-icons/ri';
import {SiNaver} from "react-icons/si";
import {FcGoogle} from "react-icons/fc";
import {FaUnlockAlt} from "react-icons/fa";
const LoginPage = () => {
const handleOAuthLogin = async (provider) => {
try {
// OAuth 인증 URL을 호출하여 사용자에게 인증을 요청
window.location.href = `http://localhost:8080/oauth/${provider}`;
} catch (error) {
console.error("로그인 요청 중 오류 발생:", error);
alert("로그인 요청 중 오류가 발생했습니다.");
}
};
return (
<div className="login-container">
<div className="login-box">
<div className="login-header">
<FaUnlockAlt className="user-icon"/>
<p>소셜 계정으로 로그인</p>
</div>
<button
className="login-button kakao"
onClick={() => handleOAuthLogin('kakao').then(r => {
})}
>
<RiKakaoTalkFill className="login-icon"/>
<span className="login-text">카카오 계정으로 로그인</span>
</button>
<button
className="login-button naver"
onClick={() => handleOAuthLogin('naver')}
>
<SiNaver className="login-icon"/>
<span className="login-text">네이버 계정으로 로그인</span>
</button>
<button
className="login-button google"
onClick={() => handleOAuthLogin('google')}
>
<FcGoogle className="login-icon"/>
<span className="login-text">구글 계정으로 로그인</span>
</button>
</div>
</div>
);
};
export default LoginPage;
겸사겸사 HomePage.js로 옮긴 callback부분 삭제
LoginPage.css 최종
/* 로그인 페이지 전체를 중앙에 배치 */
.login-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* 로그인 박스 스타일 */
.login-box {
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
padding: 40px;
text-align: center;
width: 300px;
display: flex;
flex-direction: column; /* 요소들을 수직으로 쌓이게 함 */
align-items: center; /* 수평 중앙 정렬 */
}
/* 로그인 헤더 스타일 */
.login-header {
font-size: 24px;
font-weight: bold;
}
/* 버튼 기본 스타일 */
.login-button {
width: 100%;
padding: 10px;
margin-bottom: 10px;
font-size: 16px;
border-radius: 5px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: flex-start;
color: white;
font-weight: bold;
height: 50px; /* 모든 버튼의 높이를 50px로 통일 */
}
/* 각 로그인 버튼의 색상 */
.kakao {
background-color: #fee500;
color: #3c1e1e;
}
.naver {
background-color: #03c75a;
color: white;
}
.google {
background-color: #ffffff;
color: black;
border: 2px solid #f1f1f1; /* 테두리 추가 */
}
/* 로그인 텍스트 아래 아이콘 스타일*/
.user-icon {
margin-top:10px;
font-size: 100px;
}
/* 개별 아이콘의 크기 조정 */
.kakao .login-icon {
font-size: 32px; /* 카카오 아이콘 크기 */
margin-left: 25px;
margin-right: 25px;
}
.naver .login-icon {
font-size: 24px; /* 네이버 아이콘 크기 */
margin-left: 28px;
margin-right: 30px;
}
.google .login-icon {
font-size: 33px; /* 구글 아이콘 크기 */
margin-left: 22px;
margin-right: 25px;
}
/* 텍스트 정렬 */
.login-text {
flex-grow: 1;
text-align: left;
padding-right: 15px; /* 텍스트의 오른쪽 여백 조정 */
}
/* 구글 텍스트만 글자 간격 조절 */
.google .login-text {
letter-spacing: 0.075em; /* 간격 조정. 1.2px */
word-spacing: 2px; /* 단어 간격 조절 */
}
/* 버튼 호버 스타일 */
.login-button:hover {
opacity: 0.9;
}
상당시 세부적으로 조정하여 정렬하였다. px은 부동소수점 단위는 브라우저에 따라 달라질 수 있다는 경고가 있어 em으로 변환했다.
참고자료 및 출처
React Icons (react-icons.github.io)