Participation API 프록시 라우트 URL 구조 수정

- 5개 Participation API 프록시 라우트에 /api/v1/participations 베이스 경로 추가
- 백엔드 Swagger 경로 구조에 맞춰 URL 수정
  - GET /api/v1/events/{eventId}/participants
  - GET /api/v1/events/{eventId}/winners
  - POST /api/v1/events/{eventId}/draw-winners
  - GET /api/v1/events/{eventId}/participants/{participantId}
  - POST /api/v1/events/{eventId}/participate
- nginx.conf 버퍼 설정 최적화 (proxy_buffers 8 64k)
- next.config.js output 'standalone' 설정 유지
This commit is contained in:
cherry2250 2025-10-30 17:16:16 +09:00
parent e50cc86ece
commit e3f1e2e3c7
8 changed files with 288 additions and 21 deletions

View File

@ -23,6 +23,10 @@ http {
keepalive_timeout 65;
types_hash_max_size 2048;
# 헤더 쿠키 버퍼 크기 증가
large_client_header_buffers 4 32k;
client_header_buffer_size 32k;
gzip on;
gzip_vary on;
gzip_proxied any;
@ -59,6 +63,11 @@ http {
proxy_connect_timeout 180s;
proxy_send_timeout 180s;
proxy_read_timeout 180s;
# 프록시 버퍼 크기 증가
proxy_buffer_size 32k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
}
# Static files

View File

@ -25,11 +25,6 @@ const nextConfig = {
source: '/api/v1/events/:path*',
destination: 'http://localhost:8080/api/v1/events/:path*',
},
// Participation Service API Proxy (외부 서버)
{
source: '/api/v1/participations/:path*',
destination: 'http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/participations/:path*',
},
]
},
}

View File

@ -0,0 +1,47 @@
import { NextRequest, NextResponse } from 'next/server';
const PARTICIPATION_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function POST(
request: NextRequest,
{ params }: { params: { eventId: string } }
) {
try {
const { eventId } = params;
const body = await request.json();
console.log('🔄 Proxying draw winners request to Participation API:', {
url: `${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/draw-winners`,
eventId,
body,
});
const response = await fetch(`${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/draw-winners`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Participation API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to draw winners', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Winners drawn:', 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 }
);
}
}

View File

@ -0,0 +1,48 @@
import { NextRequest, NextResponse } from 'next/server';
const PARTICIPATION_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
{ params }: { params: { eventId: string; participantId: string } }
) {
try {
const { eventId, participantId } = params;
console.log('🔄 Proxying get participant request to Participation API:', {
url: `${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/participants/${participantId}`,
eventId,
participantId,
});
const response = await fetch(
`${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/participants/${participantId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}
);
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Participation API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to get participant', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Participant retrieved:', 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 }
);
}
}

View File

@ -0,0 +1,61 @@
import { NextRequest, NextResponse } from 'next/server';
const PARTICIPATION_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
{ params }: { params: { eventId: string } }
) {
try {
const { eventId } = params;
const { searchParams } = new URL(request.url);
// Extract query parameters
const storeVisited = searchParams.get('storeVisited');
const page = searchParams.get('page') || '0';
const size = searchParams.get('size') || '20';
const sort = searchParams.getAll('sort');
// Build query string
const queryParams = new URLSearchParams();
if (storeVisited !== null) queryParams.append('storeVisited', storeVisited);
queryParams.append('page', page);
queryParams.append('size', size);
sort.forEach(s => queryParams.append('sort', s));
const url = `${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/participants?${queryParams.toString()}`;
console.log('🔄 Proxying participants list request to Participation API:', {
url,
eventId,
params: { storeVisited, page, size, sort },
});
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Participation API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to get participants', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Participants retrieved:', 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 }
);
}
}

View File

@ -0,0 +1,47 @@
import { NextRequest, NextResponse } from 'next/server';
const PARTICIPATION_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function POST(
request: NextRequest,
{ params }: { params: { eventId: string } }
) {
try {
const { eventId } = params;
const body = await request.json();
console.log('🔄 Proxying participation request to Participation API:', {
url: `${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/participate`,
eventId,
body,
});
const response = await fetch(`${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/participate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Participation API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to participate in event', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Participation 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 }
);
}
}

View File

@ -0,0 +1,59 @@
import { NextRequest, NextResponse } from 'next/server';
const PARTICIPATION_API_BASE_URL = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
export async function GET(
request: NextRequest,
{ params }: { params: { eventId: string } }
) {
try {
const { eventId } = params;
const { searchParams } = new URL(request.url);
// Extract query parameters
const page = searchParams.get('page') || '0';
const size = searchParams.get('size') || '20';
const sort = searchParams.getAll('sort');
// Build query string
const queryParams = new URLSearchParams();
queryParams.append('page', page);
queryParams.append('size', size);
sort.forEach(s => queryParams.append('sort', s));
const url = `${PARTICIPATION_API_BASE_URL}/api/v1/participations/api/v1/events/${eventId}/winners?${queryParams.toString()}`;
console.log('🔄 Proxying winners list request to Participation API:', {
url,
eventId,
params: { page, size, sort },
});
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ Participation API error:', response.status, errorText);
return NextResponse.json(
{ error: 'Failed to get winners', details: errorText },
{ status: response.status }
);
}
const data = await response.json();
console.log('✅ Winners retrieved:', 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 }
);
}
}

View File

@ -1,4 +1,4 @@
import { participationClient } from './client';
import axios from 'axios';
import type {
ApiResponse,
PageResponse,
@ -10,18 +10,19 @@ import type {
/**
* Participation API Service
* API
* Next.js API Routes를 CORS
*/
/**
*
* POST /v1/events/{eventId}/participate
* POST /api/v1/events/{eventId}/participate
*/
export const participate = async (
eventId: string,
data: ParticipationRequest
): Promise<ApiResponse<ParticipationResponse>> => {
const response = await participationClient.post<ApiResponse<ParticipationResponse>>(
`/v1/events/${eventId}/participate`,
const response = await axios.post<ApiResponse<ParticipationResponse>>(
`/api/v1/events/${eventId}/participate`,
data
);
return response.data;
@ -29,15 +30,15 @@ export const participate = async (
/**
* ()
* GET /v1/events/{eventId}/participants
* GET /api/v1/events/{eventId}/participants
*/
export const getParticipants = async (
params: GetParticipantsParams
): Promise<ApiResponse<PageResponse<ParticipationResponse>>> => {
const { eventId, storeVisited, page = 0, size = 20, sort = ['createdAt,DESC'] } = params;
const response = await participationClient.get<ApiResponse<PageResponse<ParticipationResponse>>>(
`/v1/events/${eventId}/participants`,
const response = await axios.get<ApiResponse<PageResponse<ParticipationResponse>>>(
`/api/v1/events/${eventId}/participants`,
{
params: {
storeVisited,
@ -52,14 +53,14 @@ export const getParticipants = async (
/**
*
* GET /v1/events/{eventId}/participants/{participantId}
* GET /api/v1/events/{eventId}/participants/{participantId}
*/
export const getParticipant = async (
eventId: string,
participantId: string
): Promise<ApiResponse<ParticipationResponse>> => {
const response = await participationClient.get<ApiResponse<ParticipationResponse>>(
`/v1/events/${eventId}/participants/${participantId}`
const response = await axios.get<ApiResponse<ParticipationResponse>>(
`/api/v1/events/${eventId}/participants/${participantId}`
);
return response.data;
};
@ -112,15 +113,15 @@ export const searchParticipants = async (
/**
*
* POST /v1/events/{eventId}/draw-winners
* POST /api/v1/events/{eventId}/draw-winners
*/
export const drawWinners = async (
eventId: string,
winnerCount: number,
applyStoreVisitBonus?: boolean
): Promise<ApiResponse<import('../types/api.types').DrawWinnersResponse>> => {
const response = await participationClient.post<ApiResponse<import('../types/api.types').DrawWinnersResponse>>(
`/v1/events/${eventId}/draw-winners`,
const response = await axios.post<ApiResponse<import('../types/api.types').DrawWinnersResponse>>(
`/api/v1/events/${eventId}/draw-winners`,
{
winnerCount,
applyStoreVisitBonus,
@ -131,7 +132,7 @@ export const drawWinners = async (
/**
*
* GET /v1/events/{eventId}/winners
* GET /api/v1/events/{eventId}/winners
*/
export const getWinners = async (
eventId: string,
@ -139,8 +140,8 @@ export const getWinners = async (
size = 20,
sort: string[] = ['winnerRank,ASC']
): Promise<ApiResponse<PageResponse<ParticipationResponse>>> => {
const response = await participationClient.get<ApiResponse<PageResponse<ParticipationResponse>>>(
`/v1/events/${eventId}/winners`,
const response = await axios.get<ApiResponse<PageResponse<ParticipationResponse>>>(
`/api/v1/events/${eventId}/winners`,
{
params: {
page,