From 82e198836a176f48232898afff4e6887f68c49c2 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 7 May 2025 10:18:28 +0900 Subject: [PATCH 1/5] refactor: remove suitable and surveySales API modules to streamline codebase --- src/api/suitable.ts | 95 ------------------------------------------ src/api/surveySales.ts | 71 ------------------------------- 2 files changed, 166 deletions(-) delete mode 100644 src/api/suitable.ts delete mode 100644 src/api/surveySales.ts diff --git a/src/api/suitable.ts b/src/api/suitable.ts deleted file mode 100644 index e8458c4..0000000 --- a/src/api/suitable.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { database } from '@/data' -import { axiosInstance } from '@/libs/axios' - -export interface Suitable { - id?: number - product_name: string - manufacturer: string - roof_material: string - shape: string - support_roof_tile: string - support_roof_tile_memo: string - support_roof_bracket: string - support_roof_bracket_memo: string - yg_anchor: string - yg_anchor_memo: string - rg_roof_tile_part: string - rg_roof_tile_part_memo: string - dido_hunt_support_tile_2: string - dido_hunt_support_tile_2_memo: string - takashima_power_base: string - takashima_power_base_memo: string - takashima_tile_bracket: string - takashima_tile_bracket_memo: string - slate_bracket_4: string - slate_bracket_4_memo: string - slate_single_metal_bracket: string - slate_single_metal_bracket_memo: string - dido_hunt_short_rack_4: string - dido_hunt_short_rack_4_memo: string - takashima_slate_bracket_slate_single: string - takashima_slate_bracket_slate_single_memo: string - df_metal_bracket: string - df_metal_bracket_memo: string - slate_metal_bracket: string - slate_metal_bracket_memo: string - takashima_slate_bracket_metal_roof: string - takashima_slate_bracket_metal_roof_memo: string -} - -export const suitableApi = { - getList: async (): Promise => { - const response = await axiosInstance.get('/api/suitable/list') - console.log('🚀 ~ getList: ~ response:', response) - return response.data - }, - - getDetails: async (roofMaterial: string): Promise => { - const response = await axiosInstance.get(`/api/suitable/details?roof-material=${roofMaterial}`) - return response.data - }, - - create: async () => { - const suitableData: Suitable[] = [] - - database.forEach((item) => { - suitableData.push({ - product_name: item[0], - manufacturer: item[1], - roof_material: item[2], - shape: item[3], - support_roof_tile: item[4], - support_roof_tile_memo: item[5], - support_roof_bracket: item[6], - support_roof_bracket_memo: item[7], - yg_anchor: item[8], - yg_anchor_memo: item[9], - rg_roof_tile_part: item[10], - rg_roof_tile_part_memo: item[11], - dido_hunt_support_tile_2: item[12], - dido_hunt_support_tile_2_memo: item[13], - takashima_power_base: item[14], - takashima_power_base_memo: item[15], - takashima_tile_bracket: item[16], - takashima_tile_bracket_memo: item[17], - slate_bracket_4: item[18], - slate_bracket_4_memo: item[19], - slate_single_metal_bracket: item[20], - slate_single_metal_bracket_memo: item[21], - dido_hunt_short_rack_4: item[22], - dido_hunt_short_rack_4_memo: item[23], - takashima_slate_bracket_slate_single: item[24], - takashima_slate_bracket_slate_single_memo: item[25], - df_metal_bracket: item[26], - df_metal_bracket_memo: item[27], - slate_metal_bracket: item[28], - slate_metal_bracket_memo: item[29], - takashima_slate_bracket_metal_roof: item[30], - takashima_slate_bracket_metal_roof_memo: item[31], - }) - }) - - const response = await axiosInstance.post('/api/suitable', suitableData) - return response.data - }, -} diff --git a/src/api/surveySales.ts b/src/api/surveySales.ts deleted file mode 100644 index e54f856..0000000 --- a/src/api/surveySales.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { axiosInstance } from '@/libs/axios' - -export interface SurveySalesBasicInfo { - id?: number - representative: String - store: String | null - construction_point: String | null - investigation_date: String | null - building_name: String | null - customer_name: String | null - post_code: String | null - address: String | null - address_detail: String | null - submission_status: Boolean - submission_date?: String | null - detail_info?: SurveySalesDetailInfo | null -} - -export interface SurveySalesDetailInfo { - id?: number - contract_capacity: String | null - retail_company: String | null - supplementary_facilities: Number | null - supplementary_facilities_etc: String | null - installation_system: Number | null - installation_system_etc: String | null - construction_year: Number | null - construction_year_etc: String | null - roof_material: Number | null - roof_material_etc: String | null - roof_shape: Number | null - roof_shape_etc: String | null - roof_slope: String | null - house_structure: Number | null - house_structure_etc: String | null - rafter_material: Number | null - rafter_material_etc: String | null - rafter_size: Number | null - rafter_size_etc: String | null - rafter_pitch: Number | null - rafter_pitch_etc: String | null - rafter_direction: Number | null - open_field_plate_kind: Number | null - open_field_plate_kind_etc: String | null - open_field_plate_thickness: String | null - leak_trace: Boolean | null - waterproof_material: Number | null - waterproof_material_etc: String | null - insulation_presence: Number | null - insulation_presence_etc: String | null - structure_order: Number | null - structure_order_etc: String | null - installation_availability: Number | null - installation_availability_etc: String | null - memo: String | null -} - -export const surveySalesApi = { - create: async (data: SurveySalesBasicInfo): Promise => { - const response = await axiosInstance.post('/api/survey-sales', data) - return response.data - }, - getList: async (): Promise => { - const response = await axiosInstance.get('/api/survey-sales') - return response.data - }, - update: async (data: SurveySalesBasicInfo): Promise => { - const response = await axiosInstance.put(`/api/survey-sales`, data) - return response.data - }, -} From 2166b7836e6b67aef8e14d7f43fa313969b98980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 7 May 2025 15:08:33 +0900 Subject: [PATCH 2/5] =?UTF-8?q?snake=20case=20->=20camel=20case=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/axios.ts | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libs/axios.ts b/src/libs/axios.ts index 4fa4554..9f3aa8d 100644 --- a/src/libs/axios.ts +++ b/src/libs/axios.ts @@ -22,9 +22,43 @@ axiosInstance.interceptors.request.use( // Response interceptor axiosInstance.interceptors.response.use( - (response) => response, + (response) => transferResponse(response), (error) => { // 에러 처리 로직 return Promise.reject(error) }, ) + +// response데이터가 array, object에 따라 분기하여 키 변환 +const transferResponse = (response: any) => { + if (!response.data) return response.data + + // 배열인 경우 각 객체의 키를 변환 + if (Array.isArray(response.data)) { + return response.data.map((item: any) => transformObjectKeys(item)) + } + + // 단일 객체인 경우 + return transformObjectKeys(response.data) +} + +// camel case object 반환 +const transformObjectKeys = (obj: any): any => { + if (Array.isArray(obj)) { + return obj.map(transformObjectKeys) + } + + if (obj !== null && typeof obj === 'object') { + return Object.keys(obj).reduce((acc: any, key: string) => { + const camelKey = snakeToCamel(key) + acc[camelKey] = transformObjectKeys(obj[key]) + return acc + }, {}) + } + + return obj +} +// snake case to camel case +const snakeToCamel = (str: string): string => { + return str.replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace('-', '').replace('_', '')) +} From 5048fe1c0831b9f81f712693ddab22ec0927d9b1 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 7 May 2025 15:17:01 +0900 Subject: [PATCH 3/5] =?UTF-8?q?chore:=20axios=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 6 +++- .env.production | 6 +++- next.config.ts | 8 +++-- src/app/api/auth/route.ts | 14 ++++++++ src/components/Login.tsx | 72 +++++++++++++++++++++++++++++++++++---- src/libs/axios.ts | 19 ++++++----- 6 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 src/app/api/auth/route.ts diff --git a/.env.development b/.env.development index 53e90fd..c8a3ab5 100644 --- a/.env.development +++ b/.env.development @@ -1,3 +1,7 @@ # 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경 # 다시 로컬에서 개발할때는 localhost로 변경 -NEXT_PUBLIC_API_URL=http://localhost:3000 \ No newline at end of file +#route handler +NEXT_PUBLIC_API_URL=http://localhost:3000 + +#qsp 로그인 api +NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 \ No newline at end of file diff --git a/.env.production b/.env.production index f5f1630..1d169db 100644 --- a/.env.production +++ b/.env.production @@ -1 +1,5 @@ -NEXT_PUBLIC_API_URL=http://172.30.1.35:3000 \ No newline at end of file +#route handler +NEXT_PUBLIC_API_URL=http://172.30.1.35:3000 + +#qsp 로그인 api +NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index 1ff5ba6..bc718b5 100644 --- a/next.config.ts +++ b/next.config.ts @@ -9,9 +9,13 @@ const nextConfig: NextConfig = { async rewrites() { return [ { - source: '/api/:path*', - destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`, + source: '/api/user/login', + destination: `${process.env.NEXT_PUBLIC_QSP_API_URL}/api/user/login`, }, + // { + // source: '/api/:path*', + // destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`, + // }, ] }, } diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts new file mode 100644 index 0000000..f9fc859 --- /dev/null +++ b/src/app/api/auth/route.ts @@ -0,0 +1,14 @@ +import { axiosInstance } from '@/libs/axios' +import { NextResponse } from 'next/server' + +export async function POST(request: Request) { + const { loginId, pwd } = await request.json() + + const result = await axiosInstance(`${process.env.NEXT_PUBLIC_QSP_API_URL}`).post(`/api/user/login`, { + loginId, + pwd, + }) + console.log('🚀 ~ result ~ result:', result) + + return NextResponse.json('ok') +} diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 8f6e373..c17373f 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -1,16 +1,68 @@ 'use client' -import { useState } from 'react' +import { axiosInstance } from '@/libs/axios' +import { useQuery } from '@tanstack/react-query' +import { useEffect, useReducer, useState } from 'react' +import { AxiosResponse } from 'axios' + +interface AccountState { + loginId: string + pwd: string +} export default function Login() { - const [pwShow, setPwShow] = useState(false) //비밀번호 보이기 숨기기 + //비밀번호 보이기 숨기기 + const [pwShow, setPwShow] = useState(false) + //ID 저장 체크박스 + const [idSave, setIdSave] = useState(false) + //Q.PARTNERS 체크박스 + const [isPartners, setIsPartners] = useState(false) + //로그인 상태 + const [isLogin, setIsLogin] = useState(false) + + const reducer = (state: AccountState, newState: Partial) => ({ ...state, ...newState }) + const [account, setAccount] = useReducer(reducer, { + loginId: '', + pwd: '', + }) + + const { + data: loginData, + isPending, + error, + } = useQuery({ + queryKey: ['login', 'account'], + queryFn: () => { + const result = axiosInstance('').post(`/api/auth`, { + loginId: account.loginId, + pwd: account.pwd, + }) + return result + }, + enabled: isLogin, + staleTime: 0, + retry: false, + }) + + useEffect(() => { + if (loginData) { + console.log('🚀 ~ Login ~ loginData:', loginData) + setIsLogin(false) + } + }, [loginData]) return ( <>
- + setAccount({ loginId: e.target.value })} + /> @@ -18,7 +70,13 @@ export default function Login() {
- + setAccount({ pwd: e.target.value })} + /> @@ -26,19 +84,19 @@ export default function Login() {
- + setIdSave(!idSave)} />
Q.PARTNERS
-
diff --git a/src/libs/axios.ts b/src/libs/axios.ts index 9f3aa8d..db7a625 100644 --- a/src/libs/axios.ts +++ b/src/libs/axios.ts @@ -1,16 +1,17 @@ import axios from 'axios' -const baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000' - -export const axiosInstance = axios.create({ - baseURL, - headers: { - 'Content-Type': 'application/json', - }, -}) +export const axiosInstance = (url: string) => { + let baseURL = url !== '' || url === undefined ? url : process.env.NEXT_PUBLIC_API_URL + return axios.create({ + baseURL, + headers: { + Accept: 'application/json', + }, + }) +} // Request interceptor -axiosInstance.interceptors.request.use( +axios.interceptors.request.use( (config) => { // 여기에 토큰 추가 등의 공통 로직을 넣을 수 있습니다 return config From 05f4fe4e941da4bbae640ad47ebe9ed4041cd6e9 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 7 May 2025 17:16:26 +0900 Subject: [PATCH 4/5] refactor: enhance session management and routing in middleware and API authentication --- next.config.ts | 8 ++--- src/app/@header/default.tsx | 2 +- src/app/api/auth/logout/route.ts | 15 +++++++++ src/app/api/auth/route.ts | 48 +++++++++++++++++++++++++++-- src/app/page.tsx | 8 +++++ src/components/Login.tsx | 29 ++++++++--------- src/components/ui/Main.tsx | 17 ++++++++-- src/components/ui/common/Header.tsx | 28 +++++++++-------- src/libs/axios.ts | 7 +++-- src/libs/session.ts | 45 ++++++++++++++++++++++----- src/middleware.ts | 9 +++--- src/types/Auth.ts | 30 ++++++++++++++++++ 12 files changed, 194 insertions(+), 52 deletions(-) create mode 100644 src/app/api/auth/logout/route.ts create mode 100644 src/types/Auth.ts diff --git a/next.config.ts b/next.config.ts index bc718b5..1a3917a 100644 --- a/next.config.ts +++ b/next.config.ts @@ -12,10 +12,10 @@ const nextConfig: NextConfig = { source: '/api/user/login', destination: `${process.env.NEXT_PUBLIC_QSP_API_URL}/api/user/login`, }, - // { - // source: '/api/:path*', - // destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`, - // }, + { + source: '/api/:path*', + destination: `${process.env.NEXT_PUBLIC_API_URL}/api/:path*`, + }, ] }, } diff --git a/src/app/@header/default.tsx b/src/app/@header/default.tsx index 33c708b..aff8409 100644 --- a/src/app/@header/default.tsx +++ b/src/app/@header/default.tsx @@ -1,5 +1,5 @@ import Header from '@/components/ui/common/Header' -export default function page() { +export default async function page() { return
} diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts new file mode 100644 index 0000000..390f8d1 --- /dev/null +++ b/src/app/api/auth/logout/route.ts @@ -0,0 +1,15 @@ +import { sessionOptions } from '@/libs/session' +import { SessionData } from '@/types/Auth' +import { getIronSession } from 'iron-session' +import { cookies } from 'next/headers' +import { NextResponse } from 'next/server' + +export async function GET(request: Request) { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + + session.destroy() + // return redirect('/login') + + return NextResponse.json({ code: 200, message: 'Logout successful' }) +} diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts index f9fc859..8cbbc1a 100644 --- a/src/app/api/auth/route.ts +++ b/src/app/api/auth/route.ts @@ -1,6 +1,12 @@ -import { axiosInstance } from '@/libs/axios' +import { cookies } from 'next/headers' import { NextResponse } from 'next/server' +import { getIronSession } from 'iron-session' +import { axiosInstance } from '@/libs/axios' +import { sessionOptions } from '@/libs/session' + +import type { SessionData } from '@/types/Auth' + export async function POST(request: Request) { const { loginId, pwd } = await request.json() @@ -10,5 +16,43 @@ export async function POST(request: Request) { }) console.log('🚀 ~ result ~ result:', result) - return NextResponse.json('ok') + if (result.data.result.code === 200) { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + + console.log('start session edit!') + session.langCd = result.data.data.langCd + session.currPage = result.data.data.currPage + session.rowCount = result.data.data.rowCount + session.startRow = result.data.data.startRow + session.endRow = result.data.data.endRow + session.compCd = result.data.data.compCd + session.agencyStoreId = result.data.data.agencyStoreId + session.storeId = result.data.data.storeId + session.userId = result.data.data.userId + session.category = result.data.data.category + session.userNm = result.data.data.userNm + session.userNmKana = result.data.data.userNmKana + session.telNo = result.data.data.telNo + session.fax = result.data.data.fax + session.email = result.data.data.email + session.lastEditUser = result.data.data.lastEditUser + session.storeGubun = result.data.data.storeGubun + session.pwCurr = result.data.data.pwCurr + session.pwdInitYn = result.data.data.pwdInitYn + session.apprStatCd = result.data.data.apprStatCd + session.loginFailCnt = result.data.data.loginFailCnt + session.loginFailMinYn = result.data.data.loginFailMinYn + session.priceViewStatCd = result.data.data.priceViewStatCd + session.groupId = result.data.data.groupId + session.storeLvl = result.data.data.storeLvl + session.custCd = result.data.data.custCd + session.builderNo = result.data.data.builderNo + session.isLoggedIn = true + console.log('end session edit!') + + await session.save() + } + + return NextResponse.json({ code: 200, message: 'Login is Succecss!!' }) } diff --git a/src/app/page.tsx b/src/app/page.tsx index ac97ef3..b803534 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,14 @@ import Main from '@/components/ui/Main' +import { sessionOptions } from '@/libs/session' +import type { SessionData } from '@/types/Auth' +import { getIronSession } from 'iron-session' +import { cookies } from 'next/headers' export default async function Home() { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + console.log('🚀 ~ Home ~ session:', session) + return ( <>
diff --git a/src/components/Login.tsx b/src/components/Login.tsx index c17373f..66a3f0c 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -1,9 +1,9 @@ 'use client' -import { axiosInstance } from '@/libs/axios' +import { useReducer, useState } from 'react' +import { useRouter } from 'next/navigation' import { useQuery } from '@tanstack/react-query' -import { useEffect, useReducer, useState } from 'react' -import { AxiosResponse } from 'axios' +import { axiosInstance } from '@/libs/axios' interface AccountState { loginId: string @@ -11,6 +11,7 @@ interface AccountState { } export default function Login() { + const router = useRouter() //비밀번호 보이기 숨기기 const [pwShow, setPwShow] = useState(false) //ID 저장 체크박스 @@ -26,31 +27,31 @@ export default function Login() { pwd: '', }) + interface LoginData { + code: number + message: string | null + } + const { data: loginData, isPending, error, - } = useQuery({ + } = useQuery({ queryKey: ['login', 'account'], - queryFn: () => { - const result = axiosInstance('').post(`/api/auth`, { + queryFn: async () => { + const { data } = await axiosInstance('').post(`/api/auth`, { loginId: account.loginId, pwd: account.pwd, }) - return result + router.push('/') + + return data }, enabled: isLogin, staleTime: 0, retry: false, }) - useEffect(() => { - if (loginData) { - console.log('🚀 ~ Login ~ loginData:', loginData) - setIsLogin(false) - } - }, [loginData]) - return ( <>
diff --git a/src/components/ui/Main.tsx b/src/components/ui/Main.tsx index a9eb336..37de8e7 100644 --- a/src/components/ui/Main.tsx +++ b/src/components/ui/Main.tsx @@ -1,16 +1,27 @@ 'use client' import { useHeaderStore } from '@/store/header' -import { useRouter } from 'next/navigation' +import { useSideNavState } from '@/store/sideNavState' +import { usePathname, useRouter } from 'next/navigation' import { useEffect } from 'react' export default function Main() { const router = useRouter() + const pathname = usePathname() const { setBackBtn } = useHeaderStore() + const { reset } = useSideNavState() + /** + * 헤더 뒤로가기 버튼 컨트롤 + * 사이드바 초기화 컨트롤 + */ useEffect(() => { - setBackBtn(false) - }, []) + if (pathname === '/') { + setBackBtn(false) + } + //사이드바 초기화 + reset() + }, [pathname]) return ( <> diff --git a/src/components/ui/common/Header.tsx b/src/components/ui/common/Header.tsx index 580545d..443e078 100644 --- a/src/components/ui/common/Header.tsx +++ b/src/components/ui/common/Header.tsx @@ -1,16 +1,17 @@ 'use client' -import { useEffect, useState } from 'react' - import Link from 'next/link' import { usePathname, useRouter } from 'next/navigation' import { Swiper, SwiperSlide } from 'swiper/react' +import { useSideNavState } from '@/store/sideNavState' +import { useHeaderStore } from '@/store/header' + import type { HeaderProps } from '@/types/Header' import 'swiper/css' -import { useSideNavState } from '@/store/sideNavState' +import { axiosInstance } from '@/libs/axios' // type HeaderProps = { // name: string //header 이름 @@ -20,27 +21,26 @@ import { useSideNavState } from '@/store/sideNavState' export default function Header({ name }: HeaderProps) { const router = useRouter() const pathname = usePathname() - const { sideNavIsOpen, setSideNavIsOpen, reset } = useSideNavState() - const [isShowBackBtn, setIsShowBackBtn] = useState(false) + const { sideNavIsOpen, setSideNavIsOpen } = useSideNavState() + const { backBtn } = useHeaderStore() if (pathname === '/login') { return null } - useEffect(() => { - if (pathname !== '/') { - setIsShowBackBtn(true) + const handleLogout = async () => { + const { data } = await axiosInstance(null).get('/api/auth/logout') + if (data.code === 200) { + router.push('/login') } - //사이드바 초기화 - reset() - }, [pathname]) + } return ( <>
- {isShowBackBtn && ( + {backBtn && (
@@ -112,7 +112,9 @@ export default function Header({ name }: HeaderProps) {
  • - +
  • diff --git a/src/libs/axios.ts b/src/libs/axios.ts index db7a625..5f1b076 100644 --- a/src/libs/axios.ts +++ b/src/libs/axios.ts @@ -1,7 +1,8 @@ import axios from 'axios' -export const axiosInstance = (url: string) => { - let baseURL = url !== '' || url === undefined ? url : process.env.NEXT_PUBLIC_API_URL +export const axiosInstance = (url: string | null | undefined) => { + const baseURL = url || process.env.NEXT_PUBLIC_API_URL + return axios.create({ baseURL, headers: { @@ -22,7 +23,7 @@ axios.interceptors.request.use( ) // Response interceptor -axiosInstance.interceptors.response.use( +axios.interceptors.response.use( (response) => transferResponse(response), (error) => { // 에러 처리 로직 diff --git a/src/libs/session.ts b/src/libs/session.ts index a61c755..21a0479 100644 --- a/src/libs/session.ts +++ b/src/libs/session.ts @@ -1,5 +1,7 @@ +import type { SessionData } from '@/types/Auth' import { getIronSession, SessionOptions } from 'iron-session' import { cookies } from 'next/headers' +import { redirect } from 'next/navigation' export const sessionOptions: SessionOptions = { cookieName: 'onsitesurvey_session', @@ -14,15 +16,34 @@ export const sessionOptions: SessionOptions = { }, } -export interface SessionData { - username: string | null - email: string | null - isLoggedIn: boolean -} - export const defaultSession: SessionData = { - username: '', - email: '', + langCd: null, + currPage: 0, + rowCount: 0, + startRow: 0, + endRow: 0, + compCd: null, + agencyStoreId: null, + storeId: null, + userId: null, + category: null, + userNm: null, + userNmKana: null, + telNo: null, + fax: null, + email: null, + lastEditUser: null, + storeGubun: null, + pwCurr: null, + pwdInitYn: null, + apprStatCd: null, + loginFailCnt: null, + loginFailMinYn: null, + priceViewStatCd: null, + groupId: null, + storeLvl: null, + custCd: null, + builderNo: null, isLoggedIn: false, } @@ -31,3 +52,11 @@ export const getSession = async () => { const session = await getIronSession(cookieStore, sessionOptions) return session } + +export const logout = async () => { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + + session.destroy() + return redirect('/login') +} diff --git a/src/middleware.ts b/src/middleware.ts index 5fe31f3..115fd8a 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -2,16 +2,17 @@ import { NextResponse } from 'next/server' import { cookies } from 'next/headers' import type { NextRequest } from 'next/server' import { getIronSession } from 'iron-session' -import { SessionData, sessionOptions } from './libs/session' +import { sessionOptions } from './libs/session' +import type { SessionData } from './types/Auth' export async function middleware(request: NextRequest) { const cookieStore = await cookies() const session = await getIronSession(cookieStore, sessionOptions) // todo: 로그인 기능 추가 시 주석 해제 - // if (!session.isLoggedIn) { - // return NextResponse.redirect(new URL('/login', request.url)) - // } + if (!session.isLoggedIn) { + return NextResponse.redirect(new URL('/login', request.url)) + } return NextResponse.next() } diff --git a/src/types/Auth.ts b/src/types/Auth.ts new file mode 100644 index 0000000..8920afc --- /dev/null +++ b/src/types/Auth.ts @@ -0,0 +1,30 @@ +export interface SessionData { + langCd: null + currPage: Number | null + rowCount: Number | null + startRow: Number | null + endRow: Number | null + compCd: null + agencyStoreId: null + storeId: null + userId: null + category: null + userNm: null + userNmKana: null + telNo: null + fax: null + email: null + lastEditUser: null + storeGubun: null + pwCurr: null + pwdInitYn: null + apprStatCd: null + loginFailCnt: Number | null + loginFailMinYn: null + priceViewStatCd: null + groupId: null + storeLvl: null + custCd: null + builderNo: null + isLoggedIn: boolean +} From 692d2b7d8427776d4e4b5387fb60b86ac48a8634 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 7 May 2025 17:37:09 +0900 Subject: [PATCH 5/5] refactor: comment out login redirection in middleware for future implementation --- src/middleware.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/middleware.ts b/src/middleware.ts index 115fd8a..1bcfd96 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -10,9 +10,9 @@ export async function middleware(request: NextRequest) { const session = await getIronSession(cookieStore, sessionOptions) // todo: 로그인 기능 추가 시 주석 해제 - if (!session.isLoggedIn) { - return NextResponse.redirect(new URL('/login', request.url)) - } + // if (!session.isLoggedIn) { + // return NextResponse.redirect(new URL('/login', request.url)) + // } return NextResponse.next() }