모든 localhost API 엔드포인트를 Gateway URL로 변경

- 모든 API 클라이언트에서 localhost 참조 제거
- Gateway URL 하드코딩: http://kt-event-marketing-api.20.214.196.128.nip.io
- 프로덕션/개발 환경 구분 제거
- 런타임 설정 로직 제거
- Dockerfile 및 배포 설정 추가
This commit is contained in:
cherry2250
2025-10-30 14:05:07 +09:00
parent e65ee14d61
commit f6f6e450cd
24 changed files with 1004 additions and 33 deletions
@@ -0,0 +1,81 @@
'use client';
import { useState } from 'react';
import ContentPreviewStep from '../steps/ContentPreviewStep';
import { useRouter } from 'next/navigation';
/**
* Content Service 테스트 전용 페이지
* ContentPreviewStep을 독립적으로 테스트할 수 있습니다.
*/
export default function ContentTestPage() {
const router = useRouter();
const [result, setResult] = useState<any>(null);
// 테스트용 이벤트 데이터
const testEventId = 'test-event-' + Date.now();
const testEventTitle = 'Content API 테스트 이벤트';
const testEventDescription = '콘텐츠 생성 기능을 테스트합니다';
const handleNext = (imageStyle: string, images: any[]) => {
console.log('ContentPreview 완료:', { imageStyle, images });
setResult({ imageStyle, images });
alert(`콘텐츠 생성 완료!\n스타일: ${imageStyle}\n이미지 수: ${images.length}`);
};
const handleSkip = () => {
console.log('ContentPreview 건너뛰기');
alert('콘텐츠 생성을 건너뛰었습니다.');
};
const handleBack = () => {
router.push('/events/create');
};
return (
<div>
<ContentPreviewStep
eventId={testEventId}
eventTitle={testEventTitle}
eventDescription={testEventDescription}
onNext={handleNext}
onSkip={handleSkip}
onBack={handleBack}
/>
{/* 결과 표시 (디버깅용) */}
{result && (
<div style={{
position: 'fixed',
bottom: 20,
right: 20,
background: 'white',
border: '2px solid #4CAF50',
borderRadius: 8,
padding: 16,
maxWidth: 400,
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
zIndex: 9999
}}>
<h4 style={{ margin: '0 0 10px 0', color: '#4CAF50' }}> </h4>
<p style={{ margin: '5px 0' }}>
<strong>:</strong> {result.imageStyle}
</p>
<p style={{ margin: '5px 0' }}>
<strong> :</strong> {result.images.length}
</p>
<pre style={{
background: '#f5f5f5',
padding: 10,
borderRadius: 4,
fontSize: 12,
overflow: 'auto',
maxHeight: 200
}}>
{JSON.stringify(result, null, 2)}
</pre>
</div>
)}
</div>
);
}
@@ -0,0 +1,52 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
context: { params: Promise<{ eventDraftId: string }> }
) {
try {
const { eventDraftId } = await context.params;
const { searchParams } = new URL(request.url);
const style = searchParams.get('style');
const platform = searchParams.get('platform');
// eventDraftId is now eventId in the API
let url = `${CONTENT_API_BASE_URL}/api/v1/content/events/${eventDraftId}/images`;
const queryParams = [];
if (style) queryParams.push(`style=${style}`);
if (platform) queryParams.push(`platform=${platform}`);
if (queryParams.length > 0) {
url += `?${queryParams.join('&')}`;
}
console.log('🔄 Proxying images request to Content API:', { url });
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Content API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to get images', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
console.error('❌ Proxy error:', error);
return NextResponse.json(
{ error: 'Internal server error', details: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
);
}
}
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = process.env.NEXT_PUBLIC_CONTENT_API_URL || 'http://localhost:8084';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
@@ -0,0 +1,42 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
console.log('🔄 Proxying image generation request to Content API:', {
url: `${CONTENT_API_BASE_URL}/api/v1/content/images/generate`,
body,
});
const response = await fetch(`${CONTENT_API_BASE_URL}/api/v1/content/images/generate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Content API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to generate images', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Image generation job created:', data);
return NextResponse.json(data);
} catch (error) {
console.error('❌ Proxy error:', error);
return NextResponse.json(
{ error: 'Internal server error', details: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
);
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = process.env.NEXT_PUBLIC_CONTENT_API_URL || 'http://localhost:8084';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function POST(request: NextRequest) {
try {
@@ -0,0 +1,42 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
context: { params: Promise<{ jobId: string }> }
) {
try {
const { jobId } = await context.params;
console.log('🔄 Proxying job status request to Content API:', {
url: `${CONTENT_API_BASE_URL}/api/v1/content/images/jobs/${jobId}`,
});
const response = await fetch(`${CONTENT_API_BASE_URL}/api/v1/content/images/jobs/${jobId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Content API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to get job status', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
console.error('❌ Proxy error:', error);
return NextResponse.json(
{ error: 'Internal server error', details: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
);
}
}
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
const CONTENT_API_BASE_URL = process.env.NEXT_PUBLIC_CONTENT_API_URL || 'http://localhost:8084';
const CONTENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
+2 -1
View File
@@ -12,7 +12,8 @@ export async function POST(request: NextRequest) {
const { objective } = body;
// 백엔드 API 호출 시도
const backendUrl = 'http://localhost:8080/api/events/objectives';
const EVENT_HOST = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
const backendUrl = `${EVENT_HOST}/api/events/objectives`;
try {
const backendResponse = await fetch(backendUrl, {
+2
View File
@@ -1,4 +1,5 @@
import type { Metadata, Viewport } from 'next';
import Script from 'next/script';
import { MUIThemeProvider } from '@/shared/lib/theme-provider';
import { ReactQueryProvider } from '@/shared/lib/react-query-provider';
import { AuthProvider } from '@/features/auth';
@@ -34,6 +35,7 @@ export default function RootLayout({
/>
</head>
<body>
<Script src="/runtime-env.js" strategy="beforeInteractive" />
<MUIThemeProvider>
<ReactQueryProvider>
<AuthProvider>
@@ -1,7 +1,6 @@
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios';
const ANALYTICS_HOST =
process.env.NEXT_PUBLIC_ANALYTICS_HOST || 'http://localhost:8086';
const ANALYTICS_HOST = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export const analyticsClient: AxiosInstance = axios.create({
baseURL: ANALYTICS_HOST,
+2 -12
View File
@@ -23,20 +23,10 @@ import type {
*
* 현재는 apiClient를 사용하되, baseURL을 오버라이드합니다.
*/
const EVENT_API_BASE = '/api/v1/events';
const EVENT_HOST = process.env.NEXT_PUBLIC_EVENT_HOST || 'http://localhost:8080';
/**
* Event Service용 API 클라이언트
* Event Service는 별도 포트(8080)에서 실행되므로 별도 클라이언트 생성
*
* 로컬 개발 환경: Next.js rewrites 프록시 사용 (CORS 회피)
* 프로덕션 환경: 환경 변수에서 직접 호스트 사용
*/
import axios from 'axios';
const isProduction = process.env.NODE_ENV === 'production';
const API_BASE_URL = isProduction ? EVENT_HOST : ''; // 개발 환경에서는 상대 경로 사용
const EVENT_API_BASE = '/api/v1/events';
const API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
const eventApiClient = axios.create({
baseURL: API_BASE_URL,
+1 -1
View File
@@ -1,7 +1,7 @@
import axios, { AxiosInstance } from 'axios';
// AI Service API 클라이언트
const AI_API_BASE_URL = process.env.NEXT_PUBLIC_AI_HOST || 'http://localhost:8083';
const AI_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export const aiApiClient: AxiosInstance = axios.create({
baseURL: AI_API_BASE_URL,
+8 -7
View File
@@ -1,14 +1,15 @@
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios';
// 마이크로서비스별 호스트 설정
const GATEWAY_HOST = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
const API_HOSTS = {
user: process.env.NEXT_PUBLIC_USER_HOST || 'http://localhost:8081',
event: process.env.NEXT_PUBLIC_EVENT_HOST || 'http://localhost:8080',
content: process.env.NEXT_PUBLIC_CONTENT_HOST || 'http://localhost:8082',
ai: process.env.NEXT_PUBLIC_AI_HOST || 'http://localhost:8083',
participation: process.env.NEXT_PUBLIC_PARTICIPATION_HOST || 'http://localhost:8084',
distribution: process.env.NEXT_PUBLIC_DISTRIBUTION_HOST || 'http://localhost:8085',
analytics: process.env.NEXT_PUBLIC_ANALYTICS_HOST || 'http://localhost:8086',
user: GATEWAY_HOST,
event: GATEWAY_HOST,
content: GATEWAY_HOST,
ai: GATEWAY_HOST,
participation: GATEWAY_HOST,
distribution: GATEWAY_HOST,
analytics: GATEWAY_HOST,
};
const API_VERSION = process.env.NEXT_PUBLIC_API_VERSION || 'api';
+3 -7
View File
@@ -1,13 +1,9 @@
import axios, { AxiosInstance } from 'axios';
// Event Service API 클라이언트
const EVENT_API_BASE_URL = process.env.NEXT_PUBLIC_EVENT_HOST || 'http://localhost:8080';
const API_VERSION = process.env.NEXT_PUBLIC_API_VERSION || 'v1';
// 개발 환경에서는 상대 경로 사용 (Next.js rewrites 프록시 또는 Mock API 사용)
// 프로덕션 환경에서는 환경 변수의 호스트 사용
const isProduction = process.env.NODE_ENV === 'production';
const BASE_URL = isProduction ? `${EVENT_API_BASE_URL}/api/${API_VERSION}` : `/api/${API_VERSION}`;
const EVENT_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
const API_VERSION = 'v1';
const BASE_URL = `${EVENT_API_BASE_URL}/api/${API_VERSION}`;
export const eventApiClient: AxiosInstance = axios.create({
baseURL: BASE_URL,