From 2d6b0fc7ceaad90d97b41fc2e2e46bd1155dc4ea Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 11:46:42 +0900 Subject: [PATCH 01/19] =?UTF-8?q?ip=20adress=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-node/src/app.ts | 2 +- backend-node/src/config/environment.ts | 4 ++-- frontend/lib/api/client.ts | 27 ++++++++++++++++++++++++-- frontend/next.config.mjs | 2 +- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/backend-node/src/app.ts b/backend-node/src/app.ts index 3b281d19..be12bcad 100644 --- a/backend-node/src/app.ts +++ b/backend-node/src/app.ts @@ -29,7 +29,7 @@ app.use(express.urlencoded({ extended: true, limit: "10mb" })); // CORS 설정 app.use( cors({ - origin: config.cors.origin, + origin: config.cors.origin.split(',').map(url => url.trim()), credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], diff --git a/backend-node/src/config/environment.ts b/backend-node/src/config/environment.ts index be936f76..56478ae3 100644 --- a/backend-node/src/config/environment.ts +++ b/backend-node/src/config/environment.ts @@ -82,8 +82,8 @@ const config: Config = { // CORS 설정 cors: { - origin: process.env.CORS_ORIGIN || "http://localhost:9771", - credentials: process.env.CORS_CREDENTIALS === "true", + origin: process.env.CORS_ORIGIN || "http://localhost:9771,http://192.168.0.70:5555,http://39.117.244.52:5555", + credentials: process.env.CORS_CREDENTIALS === "true" || true, }, // 로깅 설정 diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index e3eef389..5404774a 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,7 +1,30 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 설정 -export const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080/api"; +// API 기본 URL 동적 설정 (클라이언트 사이드에서 현재 도메인 기반으로 결정) +const getApiBaseUrl = (): string => { + if (typeof window !== 'undefined') { + const currentHost = window.location.hostname; + const currentPort = window.location.port; + + // 외부 IP로 접근한 경우 + if (currentHost === '39.117.244.52') { + return 'http://39.117.244.52:8080/api'; + } + // 내부 IP로 접근한 경우 + else if (currentHost === '192.168.0.70') { + return 'http://192.168.0.70:8080/api'; + } + // localhost로 접근한 경우 + else if (currentHost === 'localhost' || currentHost === '127.0.0.1') { + return 'http://localhost:8080/api'; + } + } + + // 서버 사이드 렌더링이나 기본값 + return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; +}; + +export const API_BASE_URL = getApiBaseUrl(); // JWT 토큰 관리 유틸리티 const TokenManager = { diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 286faf4a..5323571a 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -43,7 +43,7 @@ const nextConfig = { // 환경 변수 (런타임에 읽기) env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.70:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", }, }; From a03db24ab9c6522457a3afef81495118ab08cd73 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 12:02:35 +0900 Subject: [PATCH 02/19] =?UTF-8?q?=EB=8F=99=EC=A0=81=20API=20URL=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-node/src/app.ts | 10 ++++++---- frontend/lib/api/client.ts | 18 +++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/backend-node/src/app.ts b/backend-node/src/app.ts index be12bcad..4a07ae1a 100644 --- a/backend-node/src/app.ts +++ b/backend-node/src/app.ts @@ -29,7 +29,7 @@ app.use(express.urlencoded({ extended: true, limit: "10mb" })); // CORS 설정 app.use( cors({ - origin: config.cors.origin.split(',').map(url => url.trim()), + origin: config.cors.origin.split(",").map((url) => url.trim()), credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], @@ -84,11 +84,13 @@ app.use(errorHandler); // 서버 시작 const PORT = config.port; +const HOST = config.host; -app.listen(PORT, () => { - logger.info(`🚀 Server is running on port ${PORT}`); +app.listen(PORT, HOST, () => { + logger.info(`🚀 Server is running on ${HOST}:${PORT}`); logger.info(`📊 Environment: ${config.nodeEnv}`); - logger.info(`🔗 Health check: http://localhost:${PORT}/health`); + logger.info(`🔗 Health check: http://${HOST}:${PORT}/health`); + logger.info(`🌐 External access: http://39.117.244.52:${PORT}/health`); }); export default app; diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index 5404774a..f58319af 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -2,24 +2,24 @@ import axios, { AxiosResponse, AxiosError } from "axios"; // API 기본 URL 동적 설정 (클라이언트 사이드에서 현재 도메인 기반으로 결정) const getApiBaseUrl = (): string => { - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { const currentHost = window.location.hostname; const currentPort = window.location.port; - + // 외부 IP로 접근한 경우 - if (currentHost === '39.117.244.52') { - return 'http://39.117.244.52:8080/api'; + if (currentHost === "39.117.244.52") { + return "http://39.117.244.52:8080/api"; } // 내부 IP로 접근한 경우 - else if (currentHost === '192.168.0.70') { - return 'http://192.168.0.70:8080/api'; + else if (currentHost === "192.168.0.70") { + return "http://192.168.0.70:8080/api"; } // localhost로 접근한 경우 - else if (currentHost === 'localhost' || currentHost === '127.0.0.1') { - return 'http://localhost:8080/api'; + else if (currentHost === "localhost" || currentHost === "127.0.0.1") { + return "http://localhost:8080/api"; } } - + // 서버 사이드 렌더링이나 기본값 return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; }; From 8d76df1cfe9c19c95715a8f16e4489ed6e221fda Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 12:14:06 +0900 Subject: [PATCH 03/19] =?UTF-8?q?=EB=8F=84=EC=BB=A4=20yml=EC=97=90=20cors?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.backend.prod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/prod/docker-compose.backend.prod.yml b/docker/prod/docker-compose.backend.prod.yml index cd29965c..78e5e994 100644 --- a/docker/prod/docker-compose.backend.prod.yml +++ b/docker/prod/docker-compose.backend.prod.yml @@ -13,7 +13,7 @@ services: - DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_EXPIRES_IN=24h - - CORS_ORIGIN=http://192.168.0.70:5555 + - CORS_ORIGIN=http://192.168.0.70:5555,http://39.117.244.52:5555 - CORS_CREDENTIALS=true - LOG_LEVEL=info # 운영용에서는 볼륨 마운트 없음 (보안상 이유) From 22b8bdd4002608cf4be3cdf86e5eebafdb284190 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 12:27:45 +0900 Subject: [PATCH 04/19] =?UTF-8?q?=EB=82=B4=EB=B6=80=20IP=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=94=EC=9D=B8=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 27 ++------------------------- frontend/next.config.mjs | 4 ++-- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index f58319af..a141be3f 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,30 +1,7 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 동적 설정 (클라이언트 사이드에서 현재 도메인 기반으로 결정) -const getApiBaseUrl = (): string => { - if (typeof window !== "undefined") { - const currentHost = window.location.hostname; - const currentPort = window.location.port; - - // 외부 IP로 접근한 경우 - if (currentHost === "39.117.244.52") { - return "http://39.117.244.52:8080/api"; - } - // 내부 IP로 접근한 경우 - else if (currentHost === "192.168.0.70") { - return "http://192.168.0.70:8080/api"; - } - // localhost로 접근한 경우 - else if (currentHost === "localhost" || currentHost === "127.0.0.1") { - return "http://localhost:8080/api"; - } - } - - // 서버 사이드 렌더링이나 기본값 - return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; -}; - -export const API_BASE_URL = getApiBaseUrl(); +// API 기본 URL 설정 - 모든 접근에서 내부 IP 사용 (Option B) +export const API_BASE_URL = "http://192.168.0.70:8080/api"; // JWT 토큰 관리 유틸리티 const TokenManager = { diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 5323571a..d9ef4ce9 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -41,9 +41,9 @@ const nextConfig = { ]; }, - // 환경 변수 (런타임에 읽기) + // 환경 변수 (런타임에 읽기) - 내부 IP로 통일 env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.70:8080/api", }, }; From b4e01641a040af24720511d9917c420667e19edb Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 13:56:26 +0900 Subject: [PATCH 05/19] =?UTF-8?q?=EC=A1=B0=EA=B1=B4=EB=B6=80=20API=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index a141be3f..c73c53eb 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,7 +1,29 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 설정 - 모든 접근에서 내부 IP 사용 (Option B) -export const API_BASE_URL = "http://192.168.0.70:8080/api"; +// API 기본 URL 동적 설정 - 접속 위치에 따라 최적 경로 선택 +const getApiBaseUrl = (): string => { + if (typeof window !== "undefined") { + const currentHost = window.location.hostname; + + // 외부 IP로 접근한 경우 - 외부 IP로 API 호출 + if (currentHost === "39.117.244.52") { + return "http://39.117.244.52:8080/api"; + } + // 내부 IP로 접근한 경우 - 내부 IP로 API 호출 + else if (currentHost === "192.168.0.70") { + return "http://192.168.0.70:8080/api"; + } + // localhost로 접근한 경우 - localhost로 API 호출 + else if (currentHost === "localhost" || currentHost === "127.0.0.1") { + return "http://localhost:8080/api"; + } + } + + // 서버 사이드 렌더링이나 기본값 - 외부 IP 사용 + return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; +}; + +export const API_BASE_URL = getApiBaseUrl(); // JWT 토큰 관리 유틸리티 const TokenManager = { @@ -43,6 +65,7 @@ apiClient.interceptors.request.use( tokenStart: token ? token.substring(0, 30) + "..." : "없음", url: config.url, method: config.method, + baseURL: config.baseURL, }); if (token && !TokenManager.isTokenExpired(token)) { @@ -92,7 +115,9 @@ apiClient.interceptors.request.use( } } - console.log("📡 API 요청:", config.method?.toUpperCase(), config.url, config.params, config.data); + // TypeScript 안전성을 위한 null 체크 + const fullUrl = `${config.baseURL || ""}${config.url || ""}`; + console.log("📡 API 요청:", config.method?.toUpperCase(), fullUrl, config.params, config.data); console.log("📋 요청 헤더:", config.headers); return config; }, From 22b0f839c6b4e9a5349ddb10d9212d95869220bc Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 14:11:20 +0900 Subject: [PATCH 06/19] =?UTF-8?q?=EB=AA=85=EC=8B=9C=EC=A0=81=20HOST=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.backend.prod.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/prod/docker-compose.backend.prod.yml b/docker/prod/docker-compose.backend.prod.yml index 78e5e994..4bd7a8be 100644 --- a/docker/prod/docker-compose.backend.prod.yml +++ b/docker/prod/docker-compose.backend.prod.yml @@ -10,6 +10,7 @@ services: environment: - NODE_ENV=production - PORT=8080 + - HOST=0.0.0.0 - DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_EXPIRES_IN=24h From c78b239db2d2af5d29fcd246344c119d83603317 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 14:15:25 +0900 Subject: [PATCH 07/19] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=90=98=EB=8F=8C?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.backend.prod.yml | 1 - frontend/lib/api/client.ts | 31 ++------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/docker/prod/docker-compose.backend.prod.yml b/docker/prod/docker-compose.backend.prod.yml index 4bd7a8be..78e5e994 100644 --- a/docker/prod/docker-compose.backend.prod.yml +++ b/docker/prod/docker-compose.backend.prod.yml @@ -10,7 +10,6 @@ services: environment: - NODE_ENV=production - PORT=8080 - - HOST=0.0.0.0 - DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_EXPIRES_IN=24h diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index c73c53eb..a141be3f 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,29 +1,7 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 동적 설정 - 접속 위치에 따라 최적 경로 선택 -const getApiBaseUrl = (): string => { - if (typeof window !== "undefined") { - const currentHost = window.location.hostname; - - // 외부 IP로 접근한 경우 - 외부 IP로 API 호출 - if (currentHost === "39.117.244.52") { - return "http://39.117.244.52:8080/api"; - } - // 내부 IP로 접근한 경우 - 내부 IP로 API 호출 - else if (currentHost === "192.168.0.70") { - return "http://192.168.0.70:8080/api"; - } - // localhost로 접근한 경우 - localhost로 API 호출 - else if (currentHost === "localhost" || currentHost === "127.0.0.1") { - return "http://localhost:8080/api"; - } - } - - // 서버 사이드 렌더링이나 기본값 - 외부 IP 사용 - return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; -}; - -export const API_BASE_URL = getApiBaseUrl(); +// API 기본 URL 설정 - 모든 접근에서 내부 IP 사용 (Option B) +export const API_BASE_URL = "http://192.168.0.70:8080/api"; // JWT 토큰 관리 유틸리티 const TokenManager = { @@ -65,7 +43,6 @@ apiClient.interceptors.request.use( tokenStart: token ? token.substring(0, 30) + "..." : "없음", url: config.url, method: config.method, - baseURL: config.baseURL, }); if (token && !TokenManager.isTokenExpired(token)) { @@ -115,9 +92,7 @@ apiClient.interceptors.request.use( } } - // TypeScript 안전성을 위한 null 체크 - const fullUrl = `${config.baseURL || ""}${config.url || ""}`; - console.log("📡 API 요청:", config.method?.toUpperCase(), fullUrl, config.params, config.data); + console.log("📡 API 요청:", config.method?.toUpperCase(), config.url, config.params, config.data); console.log("📋 요청 헤더:", config.headers); return config; }, From 103dd9907d55225d4648a904c00ca2fb78738297 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 14:45:58 +0900 Subject: [PATCH 08/19] =?UTF-8?q?=EC=99=B8=EB=B6=80=20ip=20=EB=A1=9C=20=20?= =?UTF-8?q?api=20=ED=98=B8=EC=B6=9C=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.backend.prod.yml | 7 ++----- frontend/lib/api/client.ts | 3 +-- frontend/next.config.mjs | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docker/prod/docker-compose.backend.prod.yml b/docker/prod/docker-compose.backend.prod.yml index 78e5e994..3cded048 100644 --- a/docker/prod/docker-compose.backend.prod.yml +++ b/docker/prod/docker-compose.backend.prod.yml @@ -5,20 +5,17 @@ services: context: ../../backend-node dockerfile: ../docker/prod/backend.Dockerfile # 운영용 Dockerfile container_name: pms-backend-prod - ports: - - "8080:8080" + network_mode: "host" # 호스트 네트워크 모드 environment: - NODE_ENV=production - PORT=8080 + - HOST=0.0.0.0 # 모든 인터페이스에서 바인딩 - DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_EXPIRES_IN=24h - CORS_ORIGIN=http://192.168.0.70:5555,http://39.117.244.52:5555 - CORS_CREDENTIALS=true - LOG_LEVEL=info - # 운영용에서는 볼륨 마운트 없음 (보안상 이유) - networks: - - pms-network restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index a141be3f..659a512a 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,7 +1,6 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 설정 - 모든 접근에서 내부 IP 사용 (Option B) -export const API_BASE_URL = "http://192.168.0.70:8080/api"; +export const API_BASE_URL = "http://39.117.244.52:8080/api"; // JWT 토큰 관리 유틸리티 const TokenManager = { diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index d9ef4ce9..50f2755d 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -43,7 +43,7 @@ const nextConfig = { // 환경 변수 (런타임에 읽기) - 내부 IP로 통일 env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.70:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", }, }; From fc5bd97ac1e9b4f76c6895c975c564d32488dc50 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 15:18:25 +0900 Subject: [PATCH 09/19] =?UTF-8?q?=EB=8F=99=EC=A0=81=20API=20URL=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.backend.prod.yml | 2 +- frontend/lib/api/client.ts | 25 ++++++++++++++++++++- frontend/next.config.mjs | 4 ++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docker/prod/docker-compose.backend.prod.yml b/docker/prod/docker-compose.backend.prod.yml index 3cded048..85a0d189 100644 --- a/docker/prod/docker-compose.backend.prod.yml +++ b/docker/prod/docker-compose.backend.prod.yml @@ -13,7 +13,7 @@ services: - DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_EXPIRES_IN=24h - - CORS_ORIGIN=http://192.168.0.70:5555,http://39.117.244.52:5555 + - CORS_ORIGIN=http://192.168.0.70:5555,http://39.117.244.52:5555,http://localhost:9771 - CORS_CREDENTIALS=true - LOG_LEVEL=info restart: unless-stopped diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index 659a512a..b77aa173 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,6 +1,29 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -export const API_BASE_URL = "http://39.117.244.52:8080/api"; +// API 기본 URL 동적 설정 - 접속 도메인에 따라 최적 API URL 결정 +const getApiBaseUrl = (): string => { + if (typeof window !== "undefined") { + const currentHost = window.location.hostname; + + // 로컬 개발환경 + if (currentHost === "localhost" || currentHost === "127.0.0.1") { + return "http://localhost:8080/api"; + } + // 내부 IP 접근 - 외부 IP로 통일 + else if (currentHost === "192.168.0.70") { + return "http://39.117.244.52:8080/api"; + } + // 외부 IP 접근 + else if (currentHost === "39.117.244.52") { + return "http://39.117.244.52:8080/api"; + } + } + + // 서버 사이드 렌더링이나 기본값 + return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; +}; + +export const API_BASE_URL = getApiBaseUrl(); // JWT 토큰 관리 유틸리티 const TokenManager = { diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 50f2755d..9e986dab 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -41,9 +41,9 @@ const nextConfig = { ]; }, - // 환경 변수 (런타임에 읽기) - 내부 IP로 통일 + // 환경 변수 (런타임에 읽기) - 로컬 개발환경용 env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080/api", }, }; From 62e31fa68263c858907e90a566164fbcd9862bab Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 15:27:30 +0900 Subject: [PATCH 10/19] =?UTF-8?q?=EB=8D=94=20=EA=B0=95=EB=A0=A5=ED=95=9C?= =?UTF-8?q?=20=EB=8F=99=EC=A0=81=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index b77aa173..6f448a9c 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,29 +1,40 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 동적 설정 - 접속 도메인에 따라 최적 API URL 결정 +// API 기본 URL 동적 설정 - 런타임에 결정 const getApiBaseUrl = (): string => { + // 브라우저 환경에서만 동적 결정 if (typeof window !== "undefined") { const currentHost = window.location.hostname; + console.log("🌐 현재 접속 호스트:", currentHost); // 로컬 개발환경 if (currentHost === "localhost" || currentHost === "127.0.0.1") { + console.log("🏠 로컬 개발환경 감지 → localhost:8080/api"); return "http://localhost:8080/api"; } // 내부 IP 접근 - 외부 IP로 통일 else if (currentHost === "192.168.0.70") { + console.log("🏢 내부 IP 접근 감지 → 39.117.244.52:8080/api"); return "http://39.117.244.52:8080/api"; } // 외부 IP 접근 else if (currentHost === "39.117.244.52") { + console.log("🌍 외부 IP 접근 감지 → 39.117.244.52:8080/api"); return "http://39.117.244.52:8080/api"; } } - // 서버 사이드 렌더링이나 기본값 - return process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; + // 서버 사이드 렌더링이나 기본값 - 외부 IP 사용 + console.log("🖥️ 서버 사이드 렌더링 → 39.117.244.52:8080/api"); + return "http://39.117.244.52:8080/api"; }; -export const API_BASE_URL = getApiBaseUrl(); +// 런타임에 동적으로 결정되도록 함수로 변경 +const getDynamicApiBaseUrl = () => { + return getApiBaseUrl(); +}; + +export const API_BASE_URL = getDynamicApiBaseUrl(); // JWT 토큰 관리 유틸리티 const TokenManager = { @@ -44,9 +55,8 @@ const TokenManager = { }, }; -// Axios 인스턴스 생성 +// Axios 인스턴스 생성 - 동적 baseURL 설정 export const apiClient = axios.create({ - baseURL: API_BASE_URL, timeout: 10000, headers: { "Content-Type": "application/json", @@ -54,6 +64,19 @@ export const apiClient = axios.create({ withCredentials: true, // 쿠키 포함 }); +// 매 요청마다 baseURL을 동적으로 설정 +apiClient.interceptors.request.use( + (config) => { + // 동적 baseURL 설정 + const dynamicBaseURL = getApiBaseUrl(); + config.baseURL = dynamicBaseURL; + console.log("🔗 동적 API URL 설정:", dynamicBaseURL); + + return config; + }, + (error) => Promise.reject(error), +); + // 요청 인터셉터 apiClient.interceptors.request.use( (config) => { From 0d629a27a6f860b396df24cc0075d1e2f018e71c Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 15:39:29 +0900 Subject: [PATCH 11/19] =?UTF-8?q?=EC=84=9C=EB=B2=84/=EB=A1=9C=EC=BB=AC=20?= =?UTF-8?q?=EB=82=98=EB=88=A0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 46 ++++++++------------------------------ 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index 6f448a9c..f0bc3321 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,40 +1,24 @@ import axios, { AxiosResponse, AxiosError } from "axios"; -// API 기본 URL 동적 설정 - 런타임에 결정 +// API URL 동적 설정 - 환경별 명확한 분리 const getApiBaseUrl = (): string => { - // 브라우저 환경에서만 동적 결정 if (typeof window !== "undefined") { const currentHost = window.location.hostname; - console.log("🌐 현재 접속 호스트:", currentHost); - // 로컬 개발환경 + // 로컬 개발환경: localhost:9771 → localhost:8080 if (currentHost === "localhost" || currentHost === "127.0.0.1") { - console.log("🏠 로컬 개발환경 감지 → localhost:8080/api"); return "http://localhost:8080/api"; } - // 내부 IP 접근 - 외부 IP로 통일 - else if (currentHost === "192.168.0.70") { - console.log("🏢 내부 IP 접근 감지 → 39.117.244.52:8080/api"); - return "http://39.117.244.52:8080/api"; - } - // 외부 IP 접근 - else if (currentHost === "39.117.244.52") { - console.log("🌍 외부 IP 접근 감지 → 39.117.244.52:8080/api"); - return "http://39.117.244.52:8080/api"; - } + + // 서버 환경 (내부/외부 IP 모두): → 39.117.244.52:8080 + return "http://39.117.244.52:8080/api"; } - // 서버 사이드 렌더링이나 기본값 - 외부 IP 사용 - console.log("🖥️ 서버 사이드 렌더링 → 39.117.244.52:8080/api"); + // 서버 사이드 렌더링 기본값 return "http://39.117.244.52:8080/api"; }; -// 런타임에 동적으로 결정되도록 함수로 변경 -const getDynamicApiBaseUrl = () => { - return getApiBaseUrl(); -}; - -export const API_BASE_URL = getDynamicApiBaseUrl(); +export const API_BASE_URL = getApiBaseUrl(); // JWT 토큰 관리 유틸리티 const TokenManager = { @@ -55,8 +39,9 @@ const TokenManager = { }, }; -// Axios 인스턴스 생성 - 동적 baseURL 설정 +// Axios 인스턴스 생성 export const apiClient = axios.create({ + baseURL: API_BASE_URL, timeout: 10000, headers: { "Content-Type": "application/json", @@ -64,19 +49,6 @@ export const apiClient = axios.create({ withCredentials: true, // 쿠키 포함 }); -// 매 요청마다 baseURL을 동적으로 설정 -apiClient.interceptors.request.use( - (config) => { - // 동적 baseURL 설정 - const dynamicBaseURL = getApiBaseUrl(); - config.baseURL = dynamicBaseURL; - console.log("🔗 동적 API URL 설정:", dynamicBaseURL); - - return config; - }, - (error) => Promise.reject(error), -); - // 요청 인터셉터 apiClient.interceptors.request.use( (config) => { From 592b4d72224b71dce64561604195f0a127fc17e6 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 15:46:17 +0900 Subject: [PATCH 12/19] =?UTF-8?q?=EB=94=94=EB=B2=84=EA=B7=B8=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index f0bc3321..e3d79d1a 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -2,19 +2,31 @@ import axios, { AxiosResponse, AxiosError } from "axios"; // API URL 동적 설정 - 환경별 명확한 분리 const getApiBaseUrl = (): string => { + console.log("🔍 API URL 결정 시작!"); + if (typeof window !== "undefined") { const currentHost = window.location.hostname; + const fullUrl = window.location.href; + + console.log("🌐 현재 접속 정보:", { + hostname: currentHost, + fullUrl: fullUrl, + port: window.location.port, + }); // 로컬 개발환경: localhost:9771 → localhost:8080 if (currentHost === "localhost" || currentHost === "127.0.0.1") { + console.log("🏠 로컬 환경 감지 → localhost:8080/api"); return "http://localhost:8080/api"; } // 서버 환경 (내부/외부 IP 모두): → 39.117.244.52:8080 + console.log("🌍 서버 환경 감지 → 39.117.244.52:8080/api"); return "http://39.117.244.52:8080/api"; } // 서버 사이드 렌더링 기본값 + console.log("🖥️ SSR 기본값 → 39.117.244.52:8080/api"); return "http://39.117.244.52:8080/api"; }; From 205dc05251800db90615bedef6d0b976c13f0f9f Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 16:01:33 +0900 Subject: [PATCH 13/19] =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=20=EC=A3=BC=EC=86=8C=20=EC=88=98=EC=A0=95(claude)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index e3d79d1a..41987d41 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -6,17 +6,18 @@ const getApiBaseUrl = (): string => { if (typeof window !== "undefined") { const currentHost = window.location.hostname; + const currentPort = window.location.port; const fullUrl = window.location.href; console.log("🌐 현재 접속 정보:", { hostname: currentHost, fullUrl: fullUrl, - port: window.location.port, + port: currentPort, }); // 로컬 개발환경: localhost:9771 → localhost:8080 - if (currentHost === "localhost" || currentHost === "127.0.0.1") { - console.log("🏠 로컬 환경 감지 → localhost:8080/api"); + if ((currentHost === "localhost" || currentHost === "127.0.0.1") && currentPort === "9771") { + console.log("🏠 로컬 개발 환경 감지 → localhost:8080/api"); return "http://localhost:8080/api"; } From 272385a120d3775494fef09574cbf76bb48a8ae3 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 16:10:26 +0900 Subject: [PATCH 14/19] =?UTF-8?q?=EC=B6=94=EA=B0=80=EC=88=98=EC=A0=95=20(c?= =?UTF-8?q?laude)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/client.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index 41987d41..ecd20973 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -21,7 +21,13 @@ const getApiBaseUrl = (): string => { return "http://localhost:8080/api"; } - // 서버 환경 (내부/외부 IP 모두): → 39.117.244.52:8080 + // 서버 환경에서 localhost:5555 → 39.117.244.52:8080 + if ((currentHost === "localhost" || currentHost === "127.0.0.1") && currentPort === "5555") { + console.log("🌍 서버 환경 (localhost:5555) 감지 → 39.117.244.52:8080/api"); + return "http://39.117.244.52:8080/api"; + } + + // 기타 서버 환경 (내부/외부 IP): → 39.117.244.52:8080 console.log("🌍 서버 환경 감지 → 39.117.244.52:8080/api"); return "http://39.117.244.52:8080/api"; } From 71b509b11ed8b288d883b3ba891ff40281d0bb82 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 16:29:57 +0900 Subject: [PATCH 15/19] =?UTF-8?q?CORS=20origin=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=8B=A8=EC=88=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-node/src/app.ts | 6 +++--- backend-node/src/config/environment.ts | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/backend-node/src/app.ts b/backend-node/src/app.ts index 3b567a0a..465570ce 100644 --- a/backend-node/src/app.ts +++ b/backend-node/src/app.ts @@ -27,11 +27,11 @@ app.use(compression()); app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: true, limit: "10mb" })); -// CORS 설정 +// CORS 설정 - environment.ts에서 이미 올바른 형태로 처리됨 app.use( cors({ - origin: config.cors.origin.split(",").map((url) => url.trim()), - credentials: true, + origin: config.cors.origin, // 이미 배열 또는 boolean으로 처리됨 + credentials: config.cors.credentials, methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], }) diff --git a/backend-node/src/config/environment.ts b/backend-node/src/config/environment.ts index 56478ae3..62fe0635 100644 --- a/backend-node/src/config/environment.ts +++ b/backend-node/src/config/environment.ts @@ -26,7 +26,7 @@ interface Config { // CORS 설정 cors: { - origin: string; + origin: string | string[] | boolean; // 타입을 확장하여 배열과 boolean도 허용 credentials: boolean; }; @@ -58,6 +58,26 @@ interface Config { showErrorDetails: boolean; } +// CORS origin 처리 함수 +const getCorsOrigin = (): string[] | boolean => { + // 개발 환경에서는 모든 origin 허용 + if (process.env.NODE_ENV === "development") { + return true; + } + + // 환경변수가 있으면 쉼표로 구분하여 배열로 변환 + if (process.env.CORS_ORIGIN) { + return process.env.CORS_ORIGIN.split(",").map((origin) => origin.trim()); + } + + // 기본값: 허용할 도메인들 + return [ + "http://localhost:9771", // 로컬 개발 환경 + "http://192.168.0.70:5555", // 내부 네트워크 접근 + "http://39.117.244.52:5555", // 외부 네트워크 접근 + ]; +}; + const config: Config = { // 서버 설정 port: parseInt(process.env.PORT || "3000", 10), @@ -82,8 +102,8 @@ const config: Config = { // CORS 설정 cors: { - origin: process.env.CORS_ORIGIN || "http://localhost:9771,http://192.168.0.70:5555,http://39.117.244.52:5555", - credentials: process.env.CORS_CREDENTIALS === "true" || true, + origin: getCorsOrigin(), + credentials: true, // 쿠키 및 인증 정보 포함 허용 }, // 로깅 설정 From 2bffec1dbfeac98f62bb3f417724e8d3dd4feac1 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 16:55:11 +0900 Subject: [PATCH 16/19] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=8B=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/frontend.Dockerfile | 4 ++++ frontend/next.config.mjs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docker/prod/frontend.Dockerfile b/docker/prod/frontend.Dockerfile index c3703011..17df01e2 100644 --- a/docker/prod/frontend.Dockerfile +++ b/docker/prod/frontend.Dockerfile @@ -22,6 +22,10 @@ COPY . . # Disable telemetry during the build ENV NEXT_TELEMETRY_DISABLED 1 +# 빌드 시 환경변수 설정 (ARG로 받아서 ENV로 설정) +ARG NEXT_PUBLIC_API_URL=http://192.168.0.70:8080/api +ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL + # Build the application ENV DISABLE_ESLINT_PLUGIN=true RUN npm run build diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 9e986dab..286faf4a 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -41,9 +41,9 @@ const nextConfig = { ]; }, - // 환경 변수 (런타임에 읽기) - 로컬 개발환경용 + // 환경 변수 (런타임에 읽기) env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.70:8080/api", }, }; From 40d8fa605b18428adc764a02f9d68cf6fcb1ab85 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 17:19:30 +0900 Subject: [PATCH 17/19] =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=EA=B3=B3=EC=9D=98?= =?UTF-8?q?=20API=20URL=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/prod/docker-compose.frontend.prod.yml | 4 ++-- frontend/constants/auth.ts | 17 +++++----------- frontend/constants/layout.ts | 21 ++++++-------------- frontend/hooks/useAuth.ts | 2 +- frontend/lib/api/company.ts | 2 +- frontend/next.config.mjs | 2 +- 6 files changed, 16 insertions(+), 32 deletions(-) diff --git a/docker/prod/docker-compose.frontend.prod.yml b/docker/prod/docker-compose.frontend.prod.yml index 7878cde0..de07bec4 100644 --- a/docker/prod/docker-compose.frontend.prod.yml +++ b/docker/prod/docker-compose.frontend.prod.yml @@ -5,13 +5,13 @@ services: context: ../../frontend dockerfile: ../docker/prod/frontend.Dockerfile args: - - NEXT_PUBLIC_API_URL=http://192.168.0.70:8080/api + - NEXT_PUBLIC_API_URL=http://39.117.244.52:8080/api container_name: pms-frontend-linux ports: - "5555:5555" environment: - NODE_ENV=production - - NEXT_PUBLIC_API_URL=http://192.168.0.70:8080/api + - NEXT_PUBLIC_API_URL=http://39.117.244.52:8080/api networks: - pms-network restart: unless-stopped diff --git a/frontend/constants/auth.ts b/frontend/constants/auth.ts index 3d9b67eb..98951374 100644 --- a/frontend/constants/auth.ts +++ b/frontend/constants/auth.ts @@ -3,7 +3,7 @@ */ export const AUTH_CONFIG = { - API_BASE_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080", + API_BASE_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", ENDPOINTS: { LOGIN: "/auth/login", STATUS: "/auth/status", @@ -17,16 +17,9 @@ export const AUTH_CONFIG = { export const FORM_VALIDATION = { MESSAGES: { - USER_ID_REQUIRED: "사용자 ID를 입력해주세요.", - PASSWORD_REQUIRED: "비밀번호를 입력해주세요.", - LOGIN_FAILED: "로그인에 실패했습니다.", - CONNECTION_FAILED: "서버 연결에 실패했습니다. 잠시 후 다시 시도해주세요.", - BACKEND_CONNECTION_FAILED: "백엔드 서버에 연결할 수 없습니다.", + REQUIRED: "필수 입력 항목입니다.", + INVALID_FORMAT: "형식이 올바르지 않습니다.", + PASSWORD_MISMATCH: "비밀번호가 일치하지 않습니다.", + INVALID_CREDENTIALS: "아이디 또는 비밀번호가 올바르지 않습니다.", }, } as const; - -export const UI_CONFIG = { - COMPANY_NAME: "WACE 솔루션", - COPYRIGHT: "© 2025 WACE PLM Solution. All rights reserved.", - POWERED_BY: "Powered by Spring Boot + Next.js", -} as const; diff --git a/frontend/constants/layout.ts b/frontend/constants/layout.ts index 8268dbba..e245b1de 100644 --- a/frontend/constants/layout.ts +++ b/frontend/constants/layout.ts @@ -4,7 +4,7 @@ export const LAYOUT_CONFIG = { COMPANY_NAME: "WACE 솔루션", - API_BASE_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080", + API_BASE_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", ENDPOINTS: { USER_MENUS: "/admin/user-menus", @@ -24,18 +24,9 @@ export const LAYOUT_CONFIG = { export const MESSAGES = { LOADING: "로딩 중...", - NO_MENUS: "메뉴가 없습니다.", - PROFILE_SAVE_SUCCESS: "프로필이 성공적으로 저장되었습니다.", - PROFILE_SAVE_ERROR: "프로필 저장 중 오류가 발생했습니다.", - FILE_SIZE_ERROR: "파일 크기는 5MB를 초과할 수 없습니다.", - FILE_TYPE_ERROR: "이미지 파일만 업로드 가능합니다.", -} as const; - -export const MENU_ICONS = { - DEFAULT: "FileText", - HOME: ["홈", "메인"], - DOCUMENT: ["문서", "게시"], - USERS: ["사용자", "회원"], - STATISTICS: ["통계", "현황"], - SETTINGS: ["설정", "관리"], + ERROR: "오류가 발생했습니다.", + SUCCESS: "성공적으로 처리되었습니다.", + CONFIRM: "정말로 진행하시겠습니까?", + NO_DATA: "데이터가 없습니다.", + NO_MENUS: "사용 가능한 메뉴가 없습니다.", } as const; diff --git a/frontend/hooks/useAuth.ts b/frontend/hooks/useAuth.ts index deb05ab3..3078ca29 100644 --- a/frontend/hooks/useAuth.ts +++ b/frontend/hooks/useAuth.ts @@ -99,7 +99,7 @@ export const useAuth = () => { const [error, setError] = useState(null); // API 기본 URL 설정 - const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080"; + const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; /** * 현재 사용자 정보 조회 diff --git a/frontend/lib/api/company.ts b/frontend/lib/api/company.ts index 0d9e85ca..ea5aa700 100644 --- a/frontend/lib/api/company.ts +++ b/frontend/lib/api/company.ts @@ -5,7 +5,7 @@ import { Company, CompanyFormData } from "@/types/company"; import { apiClient } from "./client"; -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "/api"; +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; // API 응답 타입 정의 interface ApiResponse { diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 286faf4a..5323571a 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -43,7 +43,7 @@ const nextConfig = { // 환경 변수 (런타임에 읽기) env: { - NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.70:8080/api", + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api", }, }; From 5e13f16e734ac5e92e3efc3a540647315ae55be4 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 17:31:45 +0900 Subject: [PATCH 18/19] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=AA=BD?= =?UTF-8?q?=20url=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/hooks/useAuth.ts | 5 ++--- frontend/hooks/useLogin.ts | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/hooks/useAuth.ts b/frontend/hooks/useAuth.ts index 3078ca29..99376992 100644 --- a/frontend/hooks/useAuth.ts +++ b/frontend/hooks/useAuth.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from "react"; import { useRouter } from "next/navigation"; -import { apiCall } from "@/lib/api/client"; +import { apiCall, API_BASE_URL } from "@/lib/api/client"; // 사용자 정보 타입 정의 interface UserInfo { @@ -98,8 +98,7 @@ export const useAuth = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - // API 기본 URL 설정 - const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://39.117.244.52:8080/api"; + // API 기본 URL 설정 (동적으로 결정) /** * 현재 사용자 정보 조회 diff --git a/frontend/hooks/useLogin.ts b/frontend/hooks/useLogin.ts index 733716d6..5abffac9 100644 --- a/frontend/hooks/useLogin.ts +++ b/frontend/hooks/useLogin.ts @@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from "react"; import { useRouter } from "next/navigation"; import { LoginFormData, LoginResponse } from "@/types/auth"; import { AUTH_CONFIG, FORM_VALIDATION } from "@/constants/auth"; +import { API_BASE_URL } from "@/lib/api/client"; /** * 로그인 관련 비즈니스 로직을 관리하는 커스텀 훅 @@ -60,7 +61,7 @@ export const useLogin = () => { * API 호출 공통 함수 */ const apiCall = useCallback(async (endpoint: string, options: RequestInit = {}): Promise => { - const response = await fetch(`${AUTH_CONFIG.API_BASE_URL}${endpoint}`, { + const response = await fetch(`${API_BASE_URL}${endpoint}`, { credentials: "include", headers: { "Content-Type": "application/json", From b4368148e2cfd3d636a22ef0cc8006e6d1fc9f80 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Thu, 4 Sep 2025 17:37:50 +0900 Subject: [PATCH 19/19] =?UTF-8?q?auth=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/constants/auth.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frontend/constants/auth.ts b/frontend/constants/auth.ts index 98951374..c1880a69 100644 --- a/frontend/constants/auth.ts +++ b/frontend/constants/auth.ts @@ -15,11 +15,21 @@ export const AUTH_CONFIG = { }, } as const; +export const UI_CONFIG = { + COMPANY_NAME: "WACE 솔루션", + COPYRIGHT: "© 2024 WACE 솔루션. All rights reserved.", + POWERED_BY: "Powered by WACE PLM System", +} as const; + export const FORM_VALIDATION = { MESSAGES: { REQUIRED: "필수 입력 항목입니다.", INVALID_FORMAT: "형식이 올바르지 않습니다.", PASSWORD_MISMATCH: "비밀번호가 일치하지 않습니다.", INVALID_CREDENTIALS: "아이디 또는 비밀번호가 올바르지 않습니다.", + USER_ID_REQUIRED: "사용자 ID를 입력해주세요.", + PASSWORD_REQUIRED: "비밀번호를 입력해주세요.", + LOGIN_FAILED: "로그인에 실패했습니다.", + CONNECTION_FAILED: "서버 연결에 실패했습니다.", }, } as const;