diff --git a/src/app/components/ImgInputForm.tsx b/src/app/components/ImgInputForm.tsx
index 449b74e..4a27624 100644
--- a/src/app/components/ImgInputForm.tsx
+++ b/src/app/components/ImgInputForm.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useCallback, useRef, useState } from 'react'
+import { useCallback, useRef, useState, useEffect } from 'react'
import styles from './ImgInputForm.module.css'
const MAX_FILE_SIZE = 5 * 1024 * 1024 // 5MB
@@ -18,6 +18,24 @@ const ImgInputForm = () => {
//process.env.NEXT_PUBLIC_API_URL ||
const API_BASE = 'http://localhost:9001'
+ useEffect(() => {
+ const checkAuth = async () => {
+ try {
+ const res = await fetch(`${API_BASE}/auth/check-token`, {
+ method: 'GET',
+ credentials: 'include',
+ })
+ if (!res.ok) throw new Error('인증 실패')
+ console.log('사용자 인증 성공')
+ } catch (err) {
+ console.error('사용자 인증 실패:', (err as Error).message)
+ setError('로그인이 필요합니다.')
+ }
+ }
+
+ checkAuth()
+ }, [])
+
const handleFile = useCallback((file: File) => {
setError(null)
setSuccess(null)
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index de589d7..e3c0fdd 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -1,5 +1,14 @@
'use client';
-import LoginForm from "../components/LoginForm";
+import LoginForm from '../components/LoginForm';
-
\ No newline at end of file
+const LoginPage = () => {
+ return (
+
+
로그인
+
+
+ );
+};
+
+export default LoginPage;
\ No newline at end of file
diff --git a/src/app/pages/oauth/callback.tsx b/src/app/pages/oauth/callback.tsx
new file mode 100644
index 0000000..d72731f
--- /dev/null
+++ b/src/app/pages/oauth/callback.tsx
@@ -0,0 +1,51 @@
+'use client';
+
+import { useEffect, useState } from 'react';
+import { useRouter } from 'next/navigation';
+
+const OAuthCallback = () => {
+ const router = useRouter();
+ const [error, setError] = useState(null);
+ const [message, setMessage] = useState(null);
+
+ useEffect(() => {
+ const handleOAuthCallback = async () => {
+ console.log('OAuth 콜백 처리 중...');
+ const urlParams = new URLSearchParams(window.location.search);
+ const code = urlParams.get('code');
+ const error = urlParams.get('error');
+
+ if (error) {
+ setError('카카오 로그인 중 오류가 발생했습니다.');
+ return;
+ }
+
+ if (code) {
+ try {
+ const res = await fetch('/api/oauth/kakao', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ code }),
+ });
+
+ if (!res.ok) throw new Error('서버 요청 실패');
+ const data = await res.json();
+ setMessage(`로그인 성공: ${data.message}`);
+ } catch (err) {
+ setError((err as Error).message || '로그인 처리 중 오류가 발생했습니다.');
+ }
+ }
+ };
+
+ handleOAuthCallback();
+ }, []);
+
+ return (
+
+ {error &&
{error}
}
+ {message &&
{message}
}
+
+ );
+};
+
+export default OAuthCallback;
diff --git a/src/pages/api/oauth/kakao.ts b/src/pages/api/oauth/kakao.ts
new file mode 100644
index 0000000..74aaaaa
--- /dev/null
+++ b/src/pages/api/oauth/kakao.ts
@@ -0,0 +1,33 @@
+import type { NextApiRequest, NextApiResponse } from 'next';
+
+export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ if (req.method !== 'POST') {
+ return res.status(405).json({ message: 'Method Not Allowed' });
+ }
+
+ const { code } = req.body;
+
+ if (!code) {
+ return res.status(400).json({ message: 'Authorization code is missing' });
+ }
+
+ try {
+ const tokenResponse = await fetch('https://kauth.kakao.com/oauth/token', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ body: new URLSearchParams({
+ grant_type: 'authorization_code',
+ client_id: process.env.KAKAO_CLIENT_ID!,
+ redirect_uri: process.env.KAKAO_REDIRECT_URI!,
+ code,
+ }),
+ });
+
+ if (!tokenResponse.ok) throw new Error('Failed to fetch access token');
+ const tokenData = await tokenResponse.json();
+
+ res.status(200).json({ message: '카카오 로그인 성공', token: tokenData });
+ } catch (err) {
+ res.status(500).json({ message: (err as Error).message });
+ }
+}