
Kafka 클러스터 모니터링을 위한 프런트엔드 애플리케이션인 Kafka Kopanda를 개발하며, 사용자 경험과 시스템 안정성을 저해하는 몇 가지 문제에 직면했습니다. 초기 개발 단계에서는 발견하지 못했던 이 문제들은 실제 사용 환경에서 예측 불가능한 오류와 불편함을 야기했죠.
주요 문제점은 다음과 같았습니다:
ReferenceError 발생ConnectionForm.vue 컴포넌트에서 폼 데이터를 초기화하는 resetForm 함수가 정의되기 전에 호출되는 JavaScript 호이스팅(Hoisting) 문제가 발생했습니다. 이는 예측 불가능한 런타임 오류로 이어져 사용자에게 혼란을 주었습니다.
에러 메시지:
Uncaught (in promise) ReferenceError: Cannot access 'resetForm' before initialization
at watch.immediate (ConnectionForm.vue:144:5)
애플리케이션의 핵심 기능 중 하나인 라우팅 시스템에서도 문제가 발견되었습니다. 특정 페이지 접근 시 연결 상태를 확인하기 위해 라우터 가드(Router Guard) 내에서 Pinia Store(useConnectionStore())를 직접 사용하려 했으나, 이는 Vue Router와 Pinia의 초기화 시점 차이로 인해 올바르게 동작하지 않았습니다. 결과적으로 사용자가 페이지 이동 시 불필요하게 차단되는 현상이 발생했습니다.
발견된 문제점들을 해결하고 Kafka Kopanda Frontend의 안정성을 높이기 위해 다음과 같은 개선 작업을 진행했습니다.
ConnectionForm.vue: 호이스팅 문제 해결resetForm 함수가 watch 구문보다 먼저 정의되도록 코드 순서를 변경하여 호이스팅 문제를 근본적으로 해결했습니다.
💡 Before (문제 코드):
// watch 구문들...
watch(() => props.connection, (connection) => {
// ...
else {
resetForm() // ❌ 함수가 정의되기 전에 호출
}
}, { immediate: true })
const resetForm = () => { // ❌ 나중에 정의됨
// 폼 초기화 로직
}
✅ After (개선 코드):
resetForm 함수를 watch 구문 위로 이동시켜 정의 시점을 앞당겼습니다.
const resetForm = () => { // ✅ watch보다 먼저 정의
form.value = { /* ... 초기화 로직 */ }
formRef.value?.clearValidate()
}
// watch 구문들...
watch(() => props.connection, (connection) => {
// ...
else {
resetForm() // ✅ 이제 안전하게 호출 가능
}
}, { immediate: true })
개선 효과:
ReferenceError 없이 컴포넌트가 안정적으로 초기화됩니다.라우터 가드에서 Pinia Store를 사용하는 대신, 각 뷰(View) 컴포넌트 내에서 개별적으로 연결 상태를 확인하고 처리하도록 구조를 변경했습니다. 이는 라우팅 시스템의 복잡성을 줄이고 더 유연한 네비게이션 흐름을 가능하게 합니다.
💡 Before (문제 코드):
라우터 가드에서 useConnectionStore()를 사용하여 오류가 발생했습니다.
// src/router/index.ts
import { useConnectionStore } from '@/stores/connection' // ❌ 잘못된 import
router.beforeEach((to, from, next) => {
const connectionStore = useConnectionStore() // ❌ 오류 발생
if (to.meta.requiresConnection && !connectionStore.currentConnection) {
next('/connections')
} else {
next()
}
})
✅ After (개선 코드):
라우터 가드를 제거하고, 라우트 정의를 단순화했습니다.
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
// ...
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Dashboard',
component: Dashboard // ✅ 간단한 라우트 정의
},
// ...
]
})
export default router // ✅ 라우터 가드 제거
개선 효과:
연결 상태에 따라 대시보드 콘텐츠를 조건부로 렌더링하도록 Dashboard.vue 컴포넌트를 개선했습니다. 연결이 없는 경우 사용자에게 명확한 안내와 함께 '연결 관리' 페이지로 이동할 수 있는 버튼을 제공하여 사용자 경험을 크게 향상시켰습니다.
💡 Before (문제 코드):
연결 상태 확인 없이 바로 컴포넌트를 렌더링했습니다.
<template>
<div class="dashboard">
<MetricsDashboard :connection-id="currentConnection.id" />
</div>
</template>
✅ After (개선 코드):
v-if를 사용하여 연결 상태에 따른 조건부 렌더링을 구현했습니다.
<template>
<div class="dashboard">
<div v-if="!currentConnection" class="no-connection">
<el-empty description="연결된 클러스터가 없습니다">
<el-button type="primary" @click="$router.push('/connections')">
연결 관리로 이동
</el-button>
</el-empty>
</div>
<div v-else class="dashboard-content">
<MetricsDashboard :connection-id="currentConnection.id" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useConnectionStore } from '@/stores/connection'
import MetricsDashboard from '@/components/metrics/MetricsDashboard.vue'
const connectionStore = useConnectionStore()
const currentConnection = computed(() => connectionStore.currentConnection)
</script>
개선 효과:
이번 문제 해결 및 개선 과정을 통해 Kafka Kopanda Frontend는 다음과 같은 긍정적인 변화를 맞이했습니다.
이번 Kafka Kopanda Frontend 개선 프로젝트는 단순한 코드 수정 이상의 의미를 가집니다. 개발 과정에서 얻은 중요한 교훈들은 앞으로 더 나은 소프트웨어를 만드는 데 큰 자산이 될 것입니다.
이러한 개선을 통해 Kafka Kopanda Frontend는 더욱 안정적이고 사용자 친화적인 애플리케이션으로 거듭났습니다. 앞으로도 사용자들의 피드백에 귀 기울이며 지속적으로 발전시켜 나갈 예정입니다.