728x90
KOBIS 오픈 API를 사용해 일별 박스오피스 데이터를 가져오는 코드를 Node.js와 Nuxt.js(TypeScript)로 변환하겠습니다. 아래는 주어진 Python 코드를 기반으로, Node.js 백엔드와 Nuxt.js 프론트엔드를 TypeScript로 구현한 샘플 코드입니다. API 호출은 서버에서 처리하고, Nuxt.js에서 데이터를 표시합니다.
전제 조건
- KOBIS API 키: KOBIS 오픈 API 키가 필요합니다. (https://www.kobis.or.kr/kobisopenapi/homepg/main/main.do에서 발급)
- 환경:
- Node.js (최신 LTS 버전 권장)
- Nuxt 3 (TypeScript 지원)
- 설치:
- 프로젝트 디렉토리에서
npm install axios
를 실행해 API 요청을 위한axios
를 설치합니다. - Nuxt.js 프로젝트는
npx create-nuxt-app
또는npx nuxi@latest init
으로 생성하세요. TypeScript를 선택하도록 설정합니다.
- 프로젝트 디렉토리에서
디렉토리 구조
project/
├── server/
│ └── api/
│ └── boxoffice.ts # Node.js API 엔드포인트
├── pages/
│ └── index.vue # Nuxt.js 프론트엔드 페이지
├── types/
│ └── boxoffice.ts # TypeScript 인터페이스
├── nuxt.config.ts # Nuxt 설정
├── package.json
1. Node.js 서버 API (server/api/boxoffice.ts
)
Nuxt 3의 서버 미들웨어를 사용해 API 엔드포인트를 구현합니다. 이 엔드포인트는 KOBIS API를 호출해 데이터를 반환합니다.
// server/api/boxoffice.ts
import axios from 'axios';
import { H3Event } from 'hono';
import type { BoxOfficeResponse, Movie } from '~/types/boxoffice';
// KOBIS API 설정
const API_KEY = 'f5eef3421c602c6cb7ea224104795888'; // 본인의 API 키로 교체
const BASE_URL = 'http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json';
// API 핸들러
export default defineEventHandler(async (event: H3Event) => {
const query = getQuery(event);
const targetDt = query.targetDt as string || '20250721'; // 기본값: 2025-07-21
const itemPerPage = query.itemPerPage as string || '10';
try {
const response = await axios.get(BASE_URL, {
params: {
key: API_KEY,
targetDt,
itemPerPage,
},
});
const data: BoxOfficeResponse = response.data;
if (!data.boxOfficeResult?.dailyBoxOfficeList) {
return { error: 'No box office data found for the specified date.' };
}
const movies: Movie[] = data.boxOfficeResult.dailyBoxOfficeList.map((movie) => ({
rank: movie.rank,
movieNm: movie.movieNm,
audiCnt: movie.audiCnt,
salesAmt: movie.salesAmt,
openDt: movie.openDt,
}));
return { movies };
} catch (error) {
if (axios.isAxiosError(error)) {
return { error: `HTTP error: ${error.message}` };
}
return { error: `Error occurred: ${String(error)}` };
}
});
2. TypeScript 인터페이스 (types/boxoffice.ts
)
API 응답과 데이터 구조를 정의합니다.
// types/boxoffice.ts
export interface Movie {
rank: string;
movieNm: string;
audiCnt: string;
salesAmt: string;
openDt: string;
}
export interface BoxOfficeResult {
dailyBoxOfficeList: Movie[];
}
export interface BoxOfficeResponse {
boxOfficeResult?: BoxOfficeResult;
}
3. Nuxt.js 프론트엔드 페이지 (pages/index.vue
)
Nuxt.js 페이지에서 서버 API를 호출하고 데이터를 표시합니다. CSV 다운로드 기능도 포함합니다.
<!-- pages/index.vue -->
<template>
<div class="container">
<h1>Daily Box Office ({{ targetDate }})</h1>
<input v-model="targetDate" type="date" @change="fetchBoxOffice" />
<button @click="fetchBoxOffice">Search</button>
<button @click="downloadCSV">Download CSV</button>
<div v-if="error" class="error">{{ error }}</div>
<table v-else-if="movies.length" class="table">
<thead>
<tr>
<th>Rank</th>
<th>Movie Name</th>
<th>Audience Count</th>
<th>Sales Amount</th>
<th>Open Date</th>
</tr>
</thead>
<tbody>
<tr v-for="movie in movies" :key="movie.rank">
<td>{{ movie.rank }}</td>
<td>{{ movie.movieNm }}</td>
<td>{{ movie.audiCnt }}</td>
<td>{{ movie.salesAmt }}</td>
<td>{{ movie.openDt }}</td>
</tr>
</tbody>
</table>
<p v-else>No data available.</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import type { Movie } from '~/types/boxoffice';
// 상태 관리
const targetDate = ref('2025-07-21'); // 기본 날짜
const movies = ref<Movie[]>([]);
const error = ref<string | null>(null);
// API 호출
const fetchBoxOffice = async () => {
try {
const formattedDate = targetDate.value.replace(/-/g, '');
const response = await $fetch('/api/boxoffice', {
query: { targetDt: formattedDate, itemPerPage: '10' },
}) as { movies?: Movie[]; error?: string };
if (response.error) {
error.value = response.error;
movies.value = [];
} else {
movies.value = response.movies || [];
error.value = null;
}
} catch (err) {
error.value = `Failed to fetch data: ${String(err)}`;
movies.value = [];
}
};
// CSV 다운로드
const downloadCSV = () => {
if (!movies.value.length) return;
const headers = ['Rank,Movie Name,Audience Count,Sales Amount,Open Date'];
const rows = movies.value.map(movie =>
`${movie.rank},"${movie.movieNm}",${movie.audiCnt},${movie.salesAmt},${movie.openDt}`
);
const csvContent = [...headers, ...rows].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = `daily_box_office_${targetDate.value}.csv`;
link.click();
};
// 초기 데이터 로드
fetchBoxOffice();
</script>
<style scoped>
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.table th,
.table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.error {
color: red;
margin-top: 20px;
}
</style>
4. Nuxt 설정 (nuxt.config.ts
)
Nuxt 프로젝트 설정 파일입니다.
// nuxt.config.ts
export default defineNuxtConfig({
devtools: { enabled: true },
typescript: {
strict: true,
},
modules: [],
});
5. 실행 방법
- 프로젝트 초기화:
npx nuxi@latest init my-kobis-app cd my-kobis-app npm install npm install axios
- 파일 생성:
- 위의 파일들을 해당 디렉토리에 저장합니다.
API_KEY
를 본인의 KOBIS API 키로 교체합니다.
- 서버 실행:
- 개발 서버가
http://localhost:3000
에서 실행됩니다.
- 개발 서버가
npm run dev
- 결과 확인:
- 브라우저에서
http://localhost:3000
에 접속하면 날짜 선택 UI와 박스오피스 데이터 테이블이 표시됩니다. - 날짜를 변경해 데이터를 조회하거나 CSV로 다운로드할 수 있습니다.
- 브라우저에서
코드 설명
- 서버 API (
boxoffice.ts
):- Nuxt 3의 서버 미들웨어를 사용해
/api/boxoffice
엔드포인트를 정의합니다. axios
로 KOBIS API를 호출하고, TypeScript 타입(BoxOfficeResponse
,Movie
)을 사용해 데이터 구조를 명확히 정의합니다.- 쿼리 파라미터(
targetDt
,itemPerPage
)를 받아 동적으로 요청을 처리합니다.
- Nuxt 3의 서버 미들웨어를 사용해
- 프론트엔드 (
index.vue
):- Vue 3의 Composition API와
<script setup>
을 사용합니다. - 날짜 입력과 버튼으로 데이터를 조회하고, 테이블로 표시합니다.
- CSV 다운로드 기능은 클라이언트 측에서 Blob을 생성해 파일을 저장합니다.
- Vue 3의 Composition API와
- 타입 정의 (
boxoffice.ts
):- KOBIS API 응답 구조를 TypeScript 인터페이스로 정의해 타입 안정성을 보장합니다.
추가 참고
- KOBIS API 문서: https://www.kobis.or.kr/kobisopenapi/homepg/apiservice/searchServiceInfo.do
- 오류 처리: API 키가 잘못되었거나, 날짜에 데이터가 없는 경우 에러 메시지가 표시됩니다.
- 확장 가능성:
- 다른 KOBIS API(예: 주간 박스오피스, 영화 상세 정보)를 추가하려면 유사한 방식으로 엔드포인트를 확장할 수 있습니다.
- Nuxt의
useAsyncData
를 사용해 서버사이드 렌더링을 최적화할 수 있습니다.
궁금한 점이나 추가 기능이 필요하면 말씀해주세요!
728x90
'Vue.js 를 배워보자' 카테고리의 다른 글
태그 자신의 :속성 값을 확인하는 방법은 (1) | 2025.06.26 |
---|---|
Vue 3와 TypeScript로 동적 키-값 쌍을 배열에 저장하기: <script setup> 방식 (0) | 2025.06.20 |
TypeScript에서 두 객체의 공통 요소와 내포된 객체 복사하기 (1) | 2025.06.13 |
TypeScript와 Vue 3로 깔끔한 유효성 검증 구현하기 (0) | 2025.06.05 |
Vue 3와 TypeScript로 구현한 실무적인 발주서 작성 화면 (0) | 2025.05.31 |