diff --git a/deployment/container/nginx.conf b/deployment/container/nginx.conf index 500b3c3..fbd7130 100644 --- a/deployment/container/nginx.conf +++ b/deployment/container/nginx.conf @@ -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 diff --git a/next.config.js b/next.config.js index fcfa97a..69c915f 100644 --- a/next.config.js +++ b/next.config.js @@ -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*', - }, ] }, } diff --git a/src/app/api/v1/events/[eventId]/draw-winners/route.ts b/src/app/api/v1/events/[eventId]/draw-winners/route.ts new file mode 100644 index 0000000..ef0b3c7 --- /dev/null +++ b/src/app/api/v1/events/[eventId]/draw-winners/route.ts @@ -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 } + ); + } +} diff --git a/src/app/api/v1/events/[eventId]/participants/[participantId]/route.ts b/src/app/api/v1/events/[eventId]/participants/[participantId]/route.ts new file mode 100644 index 0000000..98d0a24 --- /dev/null +++ b/src/app/api/v1/events/[eventId]/participants/[participantId]/route.ts @@ -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 } + ); + } +} diff --git a/src/app/api/v1/events/[eventId]/participants/route.ts b/src/app/api/v1/events/[eventId]/participants/route.ts new file mode 100644 index 0000000..8040343 --- /dev/null +++ b/src/app/api/v1/events/[eventId]/participants/route.ts @@ -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 } + ); + } +} diff --git a/src/app/api/v1/events/[eventId]/participate/route.ts b/src/app/api/v1/events/[eventId]/participate/route.ts new file mode 100644 index 0000000..f03c08b --- /dev/null +++ b/src/app/api/v1/events/[eventId]/participate/route.ts @@ -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 } + ); + } +} diff --git a/src/app/api/v1/events/[eventId]/winners/route.ts b/src/app/api/v1/events/[eventId]/winners/route.ts new file mode 100644 index 0000000..1899f0b --- /dev/null +++ b/src/app/api/v1/events/[eventId]/winners/route.ts @@ -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 } + ); + } +} diff --git a/src/shared/api/participation.api.ts b/src/shared/api/participation.api.ts index 3eeb37b..931bc19 100644 --- a/src/shared/api/participation.api.ts +++ b/src/shared/api/participation.api.ts @@ -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> => { - const response = await participationClient.post>( - `/v1/events/${eventId}/participate`, + const response = await axios.post>( + `/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>> => { const { eventId, storeVisited, page = 0, size = 20, sort = ['createdAt,DESC'] } = params; - const response = await participationClient.get>>( - `/v1/events/${eventId}/participants`, + const response = await axios.get>>( + `/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> => { - const response = await participationClient.get>( - `/v1/events/${eventId}/participants/${participantId}` + const response = await axios.get>( + `/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> => { - const response = await participationClient.post>( - `/v1/events/${eventId}/draw-winners`, + const response = await axios.post>( + `/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>> => { - const response = await participationClient.get>>( - `/v1/events/${eventId}/winners`, + const response = await axios.get>>( + `/api/v1/events/${eventId}/winners`, { params: { page,