Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/api/auth/check-email/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { createPublicAuthServerAxios } from "@/lib/api/server";
import { AUTH_ENDPOINT } from "@/lib/api/constants";

export async function GET(request: NextRequest) {
try {
Expand All @@ -20,7 +21,7 @@ export async function GET(request: NextRequest) {
// 로컬 게이트웨이(localhost:8099)를 통해 /das/**로 라우팅됩니다
const serverAxios = createPublicAuthServerAxios();
const response = await serverAxios.get(
`/das/api/auth/check-email?email=${encodeURIComponent(email)}`
`${AUTH_ENDPOINT}/check-email?email=${encodeURIComponent(email)}`
);

return NextResponse.json(response.data);
Expand Down
3 changes: 2 additions & 1 deletion src/app/api/auth/check-nickname/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { createPublicAuthServerAxios } from "@/lib/api/server";
import { AUTH_ENDPOINT } from "@/lib/api/constants";

export async function GET(request: NextRequest) {
try {
Expand All @@ -20,7 +21,7 @@ export async function GET(request: NextRequest) {
// 로컬 게이트웨이(localhost:8099)를 통해 /das/**로 라우팅됩니다
const serverAxios = createPublicAuthServerAxios();
const response = await serverAxios.get(
`/das/api/auth/check-nickname?nickname=${encodeURIComponent(nickname)}`
`${AUTH_ENDPOINT}/check-nickname?nickname=${encodeURIComponent(nickname)}`
);

return NextResponse.json(response.data);
Expand Down
3 changes: 2 additions & 1 deletion src/app/api/auth/login/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { createAuthServerAxios } from "@/lib/api/server";
import { AUTH_ENDPOINT } from "@/lib/api/constants";

export async function POST(request: NextRequest) {
try {
Expand All @@ -9,7 +10,7 @@ export async function POST(request: NextRequest) {
// Auth Server로 로그인 요청
// 로컬 게이트웨이(localhost:8099)를 통해 /das/**로 라우팅됩니다
const serverAxios = createAuthServerAxios(request);
const response = await serverAxios.post("/das/api/auth/login", {
const response = await serverAxios.post(`${AUTH_ENDPOINT}/login`, {
email,
password,
});
Expand Down
12 changes: 11 additions & 1 deletion src/app/api/auth/me/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { USER_ENDPOINT } from "@/lib/api/constants";
import { createAuthServerAxios } from "@/lib/api/server";
import { NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
try {
const serverAxios = createAuthServerAxios(request);
const response = await serverAxios.get(`${USER_ENDPOINT}/info`);

console.log("User info response:", response.data);

return NextResponse.json(response.data);

/*
// 쿠키에서 access_token 확인
const accessToken = request.cookies.get("access_token")?.value;
Comment on lines +10 to 16
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console.log statement left in production code. Debug logging should be removed or replaced with a proper logging mechanism before merging to production.

Suggested change
console.log("User info response:", response.data);
return NextResponse.json(response.data);
/*
// 쿠키에서 access_token 확인
const accessToken = request.cookies.get("access_token")?.value;
return NextResponse.json(response.data);
/*
// 쿠키에서 access_token 확인
const accessToken = request.cookies.get("access_token")?.value;
// 쿠키에서 access_token 확인
const accessToken = request.cookies.get("access_token")?.value;

Copilot uses AI. Check for mistakes.

Expand All @@ -28,7 +38,6 @@ export async function GET(request: NextRequest) {
return NextResponse.json({
success: true,
data: {
userId: payload.userId,
email: payload.sub,
nickname: payload.nickname || "사용자",
profileImageUrl: null,
Expand All @@ -43,6 +52,7 @@ export async function GET(request: NextRequest) {
{ status: 401 }
);
}
*/
} catch (error) {
console.error("사용자 정보 조회 API 에러:", error);
return NextResponse.json(
Expand Down
17 changes: 15 additions & 2 deletions src/app/api/auth/signup/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { createPublicAuthServerAxios } from "@/lib/api/server";
import { AUTH_ENDPOINT } from "@/lib/api/constants";

export async function POST(request: NextRequest) {
try {
Expand All @@ -9,13 +10,25 @@ export async function POST(request: NextRequest) {
// 로컬 게이트웨이(localhost:8099)를 통해 /das/**로 라우팅됩니다
// multipart/form-data로 전송
const serverAxios = createPublicAuthServerAxios();
const response = await serverAxios.post("/das/api/auth/signup", formData, {
const response = await serverAxios.post(`${AUTH_ENDPOINT}/signup`, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});

return NextResponse.json(response.data);
const nextResponse = NextResponse.json(response.data);

const cookies = response.headers["set-cookie"];
if (cookies) {
if (Array.isArray(cookies)) {
cookies.forEach((cookie) => nextResponse.headers.append("Set-Cookie", cookie));
} else {
nextResponse.headers.set("Set-Cookie", cookies);
}
}
Comment on lines +21 to +28
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cookie forwarding logic is duplicated across multiple route files (signup.ts, signup/social/route.ts). This repeated code block should be extracted into a reusable utility function to improve maintainability and reduce duplication. Consider creating a helper function like forwardCookiesToResponse in a shared utility module.

Copilot uses AI. Check for mistakes.

return nextResponse;

} catch (error: unknown) {
console.error("회원가입 API 에러:", error);

Expand Down
17 changes: 15 additions & 2 deletions src/app/api/auth/signup/social/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { createPublicAuthServerAxios } from "@/lib/api/server";
import { AUTH_ENDPOINT } from "@/lib/api/constants";

export async function POST(request: NextRequest) {
try {
Expand All @@ -8,13 +9,25 @@ export async function POST(request: NextRequest) {

// Auth Server로 소셜 회원가입 요청
const serverAxios = createPublicAuthServerAxios();
const response = await serverAxios.post("/das/api/auth/signup/social", formData, {
const response = await serverAxios.post(`${AUTH_ENDPOINT}/signup/social`, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});

return NextResponse.json(response.data);
const nextResponse = NextResponse.json(response.data);

const cookies = response.headers["set-cookie"];
if (cookies) {
if (Array.isArray(cookies)) {
cookies.forEach((cookie) => nextResponse.headers.append("Set-Cookie", cookie));
} else {
nextResponse.headers.set("Set-Cookie", cookies);
}
}

return nextResponse;

} catch (error: unknown) {
console.error("소셜 회원가입 API 에러:", error);

Expand Down
24 changes: 15 additions & 9 deletions src/components/auth/SocialSignUpForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,26 +208,32 @@ export default function SocialSignUpForm({
<FormControl>
<div className="flex flex-col items-center gap-4">
{previewUrl ? (
<div className="relative w-32 h-32 rounded-full overflow-hidden border-4 border-gray-200">
<Image
src={previewUrl}
alt="Profile preview"
fill
className="object-cover"
/>
<div className="relative w-32 h-32">

<div className="w-full h-full rounded-full overflow-hidden border-4 border-gray-200 shadow-sm relative">
<Image
src={previewUrl}
alt="Profile preview"
fill
className="object-cover"
/>
</div>

<button
type="button"
onClick={removeImage}
className="absolute top-1 right-1 w-6 h-6 bg-red-500 text-white rounded-full flex items-center justify-center hover:bg-red-600 transition-colors"
className="absolute top-1 right-1 w-8 h-8 bg-red-500 text-white rounded-full flex items-center justify-center hover:bg-red-600 transition-all shadow-lg z-10 border-2 border-white"
title="이미지 삭제"
>
<X className="w-4 h-4" />
<X className="w-5 h-5" />
</button>
</div>
) : (
<div className="w-32 h-32 rounded-full bg-gray-100 flex items-center justify-center border-2 border-dashed border-gray-300">
<User className="w-12 h-12 text-gray-400" />
</div>
)}

<label className="cursor-pointer">
<input
type="file"
Expand Down
4 changes: 4 additions & 0 deletions src/lib/api/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ export const AUCTION_HISTORY_ENDPOINT = "/oab/auction-history";
export const BOARDS_ENDPOINT = "/dcs/api/boards";
export const POSTS_ENDPOINT = "/dcs/api/posts";
export const COMMENTS_ENDPOINT = "/dcs/api/comments";

// Auth API Endpoints (prefix: /das/api)
export const AUTH_ENDPOINT = "/das/api/auth";
export const USER_ENDPOINT = "/das/api/user";
6 changes: 3 additions & 3 deletions src/lib/api/gateway-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ export function selectGatewayUrl(path: string): string {
* 클라이언트 환경 변수를 사용할 수 없으므로 별도 함수 제공
*/
export function selectServerGatewayUrl(path: string): string {
const localUrl = process.env.GATEWAY_LOCAL_URL;
const devUrl = process.env.GATEWAY_DEV_URL;
const useLocalFor = process.env.USE_LOCAL_GATEWAY_FOR || "";
const localUrl = process.env.NEXT_PUBLIC_GATEWAY_LOCAL_URL;
const devUrl = process.env.NEXT_PUBLIC_GATEWAY_DEV_URL;
const useLocalFor = process.env.NEXT_PUBLIC_USE_LOCAL_GATEWAY_FOR || "";
Comment on lines +86 to +88
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The selectServerGatewayUrl function is documented as being for server-side usage, yet it's now using NEXT_PUBLIC_* prefixed environment variables which are client-exposed variables in Next.js. This contradicts the function's purpose and documentation. Server-side functions should use server-only environment variables (without the NEXT_PUBLIC_ prefix) to avoid exposing sensitive configuration to the client bundle.

Suggested change
const localUrl = process.env.NEXT_PUBLIC_GATEWAY_LOCAL_URL;
const devUrl = process.env.NEXT_PUBLIC_GATEWAY_DEV_URL;
const useLocalFor = process.env.NEXT_PUBLIC_USE_LOCAL_GATEWAY_FOR || "";
const localUrl = process.env.GATEWAY_LOCAL_URL;
const devUrl = process.env.GATEWAY_DEV_URL;
const useLocalFor = process.env.USE_LOCAL_GATEWAY_FOR || "";

Copilot uses AI. Check for mistakes.

// 기본값: 개발 서버 게이트웨이
if (!devUrl) {
Expand Down
6 changes: 5 additions & 1 deletion src/lib/auth/socialAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* 소셜 로그인/회원가입 유틸리티
*/

import { selectGatewayUrl } from "../api/gateway-selector";

export type SocialProvider = "google" | "kakao" | "naver";

export interface SocialAuthResponse {
Expand All @@ -28,8 +30,10 @@ export function initiateSocialLogin(provider: SocialProvider): void {
const currentUrl = window.location.href;
sessionStorage.setItem("social_login_return_url", currentUrl);

const gateWayUrl = selectGatewayUrl("/das");
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent camelCase naming. The variable name should be gatewayUrl instead of gateWayUrl to follow JavaScript/TypeScript naming conventions where compound words in camelCase don't capitalize mid-word characters.

Copilot uses AI. Check for mistakes.

// 로컬 게이트웨이를 통해 Auth Server의 OAuth2 엔드포인트로 이동
const authUrl = `http://localhost:8099/das/oauth2/authorization/${provider}`;
const authUrl = `http://${gateWayUrl}/das/oauth2/authorization/${provider}`;
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL construction appears problematic. The selectGatewayUrl function returns a full URL (e.g., "http://localhost:8090" or "http://168.107.43.221:8080"), but the code constructs the authUrl as http://${gateWayUrl}/das/oauth2/authorization/${provider}, which would result in a malformed URL like "http://http://localhost:8090/das/oauth2/authorization/google". The protocol prefix "http://" should be removed since selectGatewayUrl already returns a complete URL.

Suggested change
const authUrl = `http://${gateWayUrl}/das/oauth2/authorization/${provider}`;
const authUrl = `${gateWayUrl}/das/oauth2/authorization/${provider}`;

Copilot uses AI. Check for mistakes.

// 새 탭에서 소셜 로그인 팝업 열기 (더 나은 UX)
const width = 500;
Expand Down