Log Central

Category
Other Project

Log Management Platform

복잡한 로그 설정 과정을 코드 없이 UI에서 완결하고, Grafana 대시보드를 자동으로 생성/관리하여 시스템 모니터링의 진입 장벽을 낮춘 프론트엔드 및 프로비저닝 자동화 프로젝트입니다.
 
개발 기간: 2024.09 - 2024.11 (3개월)
팀 구성: 2인 팀 (프론트엔드 및 Grafana 자동화 담당)
링크:
(현재 데모는 서버 비용으로 인해 중단되어있는 상태입니다)
 

1. 프로젝트

  • Project Overview: 여러 클라우드에 분산된 서비스 로그를 통합 관리하는 시스템에서, 기존 솔루션의 복잡한 설정 과정과 높은 운영 비용 문제를 해결하고자 했습니다. 사용자가 직관적인 웹 UI를 통해 로그 수집 및 파싱 규칙을 정의하면, Grafana 데이터소스와 대시보드가 자동으로 프로비저닝되고, 애플리케이션 내부에 임베딩되어 통합된 모니터링 경험을 제공하는 것을 목표로 했습니다.
  • Project Overview: 마이크로서비스 아키텍처가 보편화되면서, 여러 클라우드에 분산된 서비스 로그를 통합 관리하는 것은 복잡한 설정 과정과 높은 운영 비용 문제를 야기했습니다. 장애 발생 시 원인을 찾기 위해 여러 서버에 접속하고, 각기 다른 로그 파일을 일일이 확인하는 과정은 문제 해결 시간을 지연시키는 치명적인 비효율을 낳습니다.
    • 또한, 새로운 프로젝트가 추가될 때마다 개발자가 수동으로 모니터링 대시보드를 설정하는 반복 작업은 개발 생산성을 저해하는 요인이었습니다.
      목표: "클릭 몇 번으로 시작하는 중앙 집중식 실시간 로그 모니터링"
      이러한 문제를 해결하기 위해,
      ① 안정적인 실시간 로그 파이프라인을 구축하고,
      ② 복잡한 설정 과정을 코드로 자동화하며,
      ③ 사용자가 직관적인 단일 대시보드에서 모든 로그를 탐색할 수 있는 SaaS형 플랫폼을 구축하는 것을 목표로 삼았습니다.
       
  • My Role: 프론트엔드 개발 및 Grafana 프로비저닝 자동화 (기여도: 프론트엔드 100%, 프로비저닝 설계/구현). 사용자 경험(UX) 전체를 책임지는 React 기반 프론트엔드 애플리케이션 개발과, Grafana의 Provisioning 기능을 활용하여 사용자별/프로젝트별 대시보드 생성을 자동화하는 백엔드 연계 로직 설계를 담당했습니다.
  • Key Outcomes
    • React Hook Form과 Zod를 활용한 로그 설정 워크플로우를 구현하여, 코드 작성 없이 UI만으로 복잡한 파싱 규칙 정의가 가능하도록 했습니다.
    • Grafana Provisioning 자동화를 통해, 신규 프로젝트 생성 시 수동 대시보드 설정 시간을 1시간 이상에서 5분 이내로 단축했습니다.
    • Custom Hook(useProjectPolling)을 구현하여 백엔드의 비동기 작업 상태를 실시간으로 UI에 피드백하고, iframe 임베딩을 통해 서비스 내에서 Grafana 대시보드를 끊김 없이 탐색하는 통합 UX를 제공했습니다.
 
 
 

2. 기술 스택 및 선정 이유

  • Frontend Framework: React, TypeScript, Vite
    • 선정 이유: (TypeScript) 복잡한 폼 상태, API 응답 등 전체 애플리케이션의 타입 안전성을 확보하여 런타임 오류를 최소화하고 개발 생산성을 높였습니다. (Vite) Webpack 대비 빠른 개발 서버 속도와 HMR로 개발 경험을 극대화했습니다.
  • Form Handling & Validation: React Hook Form, Zod
    • 선정 이유: (React Hook Form) 비제어 컴포넌트 기반으로 복잡한 4단계 설정 폼에서도 뛰어난 성능을 보장합니다. (Zod) TypeScript 타입 정의와 런타임 유효성 검사 로직을 하나의 스키마로 통합 관리하여 코드 중복을 제거하고 타입 안전성을 향상시켰습니다.
  • UI & Styling: Emotion.js, @dnd-kit/core
    • 선정 이유: (Emotion) 컴포넌트 상태에 따른 동적 스타일링 구현이 용이하고 TypeScript와의 통합이 우수합니다. (dnd-kit) Plain Text 로그 파싱 시 필드 순서가 중요하므로, 접근성(키보드 지원)과 모바일 터치 호환성을 갖춘 드래그 앤 드롭 라이브러리로 dnd-kit을 선택했습니다.
  • API Client & Routing: Axios, React Router
    • 선정 이유: (Axios) HTTP 요청/응답 인터셉터, 타임아웃 설정 등 API 통신에 필요한 기능을 편리하게 제공합니다. (React Router) 표준적인 SPA 라우팅 솔루션으로, Private Route 구현 등 인증 기반 라우팅 관리에 용이하기 때문에 선택하였습니다..
  • Provisioning Automation: Grafana Provisioning (File-based), Backend API (Django - 협업)
    • 선정 이유: (Grafana Provisioning) Grafana의 공식 기능을 활용하여 코드를 통해 데이터소스와 대시보드를 선언적으로 관리하고 자동 생성/업데이트가 가능합니다. 이를 통해 수동 설정의 비효율과 휴먼 에러를 제거했습니다. 백엔드(Django)와의 협업을 통해 설정 파일 생성을 자동화했습니다.

3. 아키텍처

프론트엔드 아키텍처

notion image
 

핵심 설계 원칙

  • 기능 기반 구조: src/components, src/pages 등을 auth, project 와 같은 기능 단위로 그룹화하여 관련 코드 응집도를 높이고, 다른 기능과의 결합도를 낮춰 유지보수성과 확장성을 확보했습니다.
  • 관심사 분리: UI(Components), 상태 관리(Zustand), API 통신(Axios), 폼 처리(React Hook Form), 타입 정의(TypeScript/Zod) 등 각 관심사를 명확한 계층과 모듈로 분리하여 코드의 가독성과 테스트 용이성을 높였습니다.
  • 타입 안정성 우선: 프로젝트 전반에 TypeScript strict 모드를 적용하고, Zod를 이용한 런타임 검증까지 추가하여 데이터 관련 오류를 컴파일 타임과 런타임 양쪽에서 방지했습니다.
  • UI/UX 일관성: Emotion의 ThemeProvider와 디자인 토큰(theme.ts)을 활용하여 애플리케이션 전체의 색상, 폰트, 간격 등 디자인 일관성을 유지했습니다.
 

4. 주요 기능

1. 코드 없이 간단한 로그 설정 워크플로우

  • React Hook Form 기반의 4단계 UI를 통해 사용자가 단계별로 로그 프로젝트 설정을 완료하도록 안내합니다.
  • 로그 형식(JSON, Plain Text, CSV 등), 수집 경로, 파싱 규칙(정규식, 필드 매핑), 필터링 조건 등을 코드 작성 없이 UI 상에서 직관적으로 설정할 수 있습니다.
  • Zod 스키마를 통해 각 단계별 입력값의 유효성을 실시간으로 검증하고, 명확한 에러 메시지를 사용자에게 제공합니다.
  • Plain Text 로그 설정 시, dnd-kit 을 활용한 드래그 앤 드롭 인터페이스를 제공하여 사용자가 추출할 필드의 순서를 시각적으로 쉽게 변경할 수 있도록 구현했습니다 (정규식 그룹 순서와 연동).
    • notion image
 

2. Grafana 대시보드 자동 생성 및 통합 (Provisioning 연계)

  • 사용자가 웹 UI에서 프로젝트 생성을 완료하면, 백엔드 API를 호출하여 Grafana 대시보드 생성을 요청합니다.
  • 백엔드에서는 Grafana의 Provisioning 기능을 활용하여 해당 프로젝트 설정에 맞는 데이터소스(datasource.yml)와 대시보드(dashboard.yml, JSON 모델) 설정 파일을 자동으로 생성합니다. Grafana는 이 파일들을 감지하여 자동으로 리소스를 생성/업데이트합니다.
  • 생성된 Grafana 대시보드의 ID와 URL은 백엔드 DB에 저장되어 사용자 프로젝트와 매핑됩니다.
  • 프론트엔드에서는 프로젝트 상세 페이지에 iframe을 사용하여 해당 Grafana 대시보드를 애플리케이션 내부에 자연스럽게 임베딩합니다. 이를 통해 사용자는 별도 로그인이나 페이지 이동 없이 통합된 환경에서 로그 데이터를 시각적으로 탐색할 수 있습니다.
  • Public Dashboard URL 생성 기능을 제공하여, 사용자에게 특정 대시보드를 공유할 수 있습니다.

3. 실시간 프로젝트 상태 모니터링 (Polling)

  • 대시보드 생성과 같이 백엔드에서 비동기적으로 처리되는 작업의 상태(IN_PROGRESS, READY, FAILED)를 사용자에게 실시간으로 피드백하기 위해 Custom Hook (useProjectPolling) 을 구현했습니다.
  • 이 Hook은 상태가 IN_PROGRESS인 프로젝트 목록을 받아, 5초 간격으로 각 프로젝트의 최신 상태를 API 서버에 조회(GET /monitoring/project/:id)합니다.
  • 조회된 상태는 Zustand Store를 통해 업데이트되며, UI(프로젝트 목록, Toast 알림)는 이 변경 사항을 즉시 반영합니다.
  • 모든 프로젝트의 상태가 READY 또는 FAILED로 변경되면, Hook은 자동으로 폴링을 중지하여 불필요한 네트워크 요청을 방지합니다.
notion image
 

5. 핵심 경험 및 문제 해결 과정

1. 사용자별 대시보드 자동화 (Grafana Provisioning)

  • 도전 과제: 사용자가 서비스를 통해 로그 프로젝트를 생성할 때마다, 해당 사용자(또는 팀)의 프로젝트 데이터에 맞는 Grafana 데이터소스와 대시보드를 자동으로 생성 및 격리해야 했습니다. 수동 설정은 확장성 및 운영 효율성 측면에서 불가능했습니다.
  • 해결 과정
      1. Grafana Provisioning 도입: Grafana가 특정 디렉토리의 YAML 설정 파일을 감지하여 데이터소스와 대시보드를 자동으로 생성/관리하는 File-based Provisioning 기능을 활용하기로 결정했습니다.
      1. 백엔드 연동 설계 (협업): 프론트엔드에서 프로젝트 생성 요청(POST /monitoring/log-project/step2)을 보내면, 백엔드(Django)에서 다음 작업을 수행하도록 API를 설계했습니다.
          • 사용자/프로젝트 정보를 기반으로 고유한 데이터소스 설정 YAML 파일대시보드 정의 JSON 파일을 동적으로 생성합니다. (대시보드 JSON은 미리 정의된 템플릿 사용 가능)
          • 생성된 파일들을 Grafana가 감시하는 Provisioning 디렉토리에 저장합니다.
          • Provisioning을 통해 생성된 Grafana 대시보드의 ID, URL 등의 정보를 백엔드 DB에 저장하고, 프론트엔드에 작업 시작 상태(IN_PROGRESS)를 응답합니다.
      1. 프론트엔드 상태 추적: 이후 useProjectPolling Hook을 통해 해당 프로젝트의 상태가 READY로 변경될 때까지 주기적으로 확인합니다.
  • 결과: 신규 프로젝트 생성 시 Grafana 리소스(데이터소스, 대시보드)가 100% 자동으로 생성 및 연동되는 시스템을 구축할 수 있었습니다. 이를 통해 관리자의 수동 설정 작업을 완전히 제거하고, 서비스의 확장성운영 효율성을 크게 향상시켰습니다. Grafana API와 파일 기반 설정을 연동하는 DevOps 자동화 경험을 쌓을 수 있었습니다.
 

2. 실시간 프로젝트 상태 폴링의 메모리 누수 방지 및 최적화

  • 문제 상황: 프로젝트 생성 후 백엔드의 비동기 작업 상태를 UI에 실시간 반영하기 위해 setInterval을 사용한 초기 폴링 로직은, 사용자가 페이지를 벗어나도 인터벌이 해제되지 않아 백그라운드에서 불필요한 API 호출을 계속 발생시키는 메모리 누수를 유발했습니다. 또한, 페이지 재진입 시 중복 폴링이 실행되는 문제도 있었습니다.
  • 해결 과정
      1. Custom Hook (useProjectPolling) 분리: 폴링 관련 로직을 컴포넌트로부터 분리하여 재사용 가능하고 테스트 용이한 Custom Hook으로 만들었습니다.
      1. useRef 활용: Hook 내부에 intervalRefisPollingRefuseRef로 관리하여, 컴포넌트 리렌더링과 관계없이 최신 상태를 유지했습니다
      1. 자동 정리 로직: useEffectcleanup 함수를 사용하여, Hook을 사용하는 컴포넌트가 언마운트될 때 clearInterval을 호출하고 isPollingReffalse로 설정하여 폴링을 안전하게 중지하도록 구현했습니다.
  • 결과: 메모리 누수와 중복 폴링 문제를 해결했습니다. Chrome DevTools로 검증 시, 페이지 이동 후 불필요한 네트워크 요청이 발생하지 않았습니다. 또한, 필요한 경우에만 폴링을 실행하고 완료 시 자동으로 중지함으로써 네트워크 트래픽과 서버 부하를 최소화하는 실시간 상태 업데이트 시스템을 구현할 수 있었습니다.
 

3. 복잡한 다단계 폼 상태 관리 및 유효성 검사

  • 문제 상황: 4단계로 구성된 프로젝트 생성 폼은 단계별로 입력 필드와 유효성 검사 규칙이 다르고, 이전 단계로 돌아가 값을 수정하면 이후 단계의 상태와 일관성을 유지해야 하는 복잡성을 가졌습니다. useState만 사용한 초기 구현은 상태 관리 로직이 복잡하고 오류 발생 가능성이 높았습니다.
  • 해결 과정
      1. React Hook Form 도입: 비제어 컴포넌트 기반으로 동작하여 입력 시 불필요한 리렌더링을 최소화하고, 복잡한 폼 상태 관리를 위한 강력한 API를 제공하여 선택했습니다.
      1. Zod 스키마 통합: 각 단계별 또는 전체 폼 데이터 구조에 대한 Zod 스키마를 정의하고, zodResolver를 사용하여 React Hook Form과 연동했습니다. 이를 통해 TypeScript 타입 정의와 런타임 유효성 검사 로직을 하나로 통합하여 코드 중복을 제거하고 타입 안전성을 확보했습니다.
      1. 단계별 상태 유지: 전체 폼 데이터를 하나의 useForm 인스턴스에서 관리하되, UI는 단계별 컴포넌트로 분리했습니다. 사용자가 단계를 이동해도 입력값은 유지되며, 최종 단계에서 handleSubmit을 통해 전체 데이터를 한 번에 검증하고 서버로 전송했습니다.
      1. 조건부 로직: watch API를 사용하여 특정 필드의 값 변화를 감지하고, 이에 따라 다른 필드의 표시 여부나 유효성 검사 규칙을 동적으로 변경하는 로직을 구현했습니다.
  • 결과: 복잡한 다단계 폼의 상태 관리 로직을 간결하고 예측 가능하게 만들었습니다. Zod 스키마를 통해 유효성 검사 코드의 양을 40% 이상 줄이고 타입 안전성을 확보했습니다. 비제어 방식 덕분에 폼 입력 시 성능 저하 없이 부드러운 사용자 경험을 제공할 수 있었습니다.
 

6. 프로젝트 성과

  • 정량적 성과
    • 운영 효율성: Grafana 대시보드 수동 설정 시간 1시간 → 5분 이내로 90% 이상 단축 (자동화 구현).
    • 사용자 경험: 실시간 상태 폴링 및 Toast 알림으로 작업 완료까지의 대기 시간 체감 감소. iframe 임베딩으로 서비스 이탈 없이 Grafana 기능 사용 가능.
    • 개발 생산성: React Hook Form + Zod 도입으로 폼 관련 코드량 40% 감소타입/검증 오류 감소.
  • 정성적 성과
    • 진입 장벽 완화: 코드 없이 UI만으로 로그 모니터링 설정을 완료할 수 있게 하여, 비전문가도 쉽게 로그 관리 시스템 도입 가능.
    • 통합된 모니터링 환경: 사용자가 여러 도구를 오갈 필요 없이, 하나의 플랫폼 내에서 로그 설정부터 데이터 시각화까지 원활하게 수행 가능.
    •  
       

7. 회고 및 배운 점

  • 기술적 성장: 이번 프로젝트를 통해 프론트엔드 개발뿐만 아니라, 백엔드(API 설계 협업) 및 인프라 자동화(Grafana Provisioning) 영역까지 경험하며 시스템 전체를 보는 시야를 넓힐 수 있었습니다. 특히, 복잡한 UI 요구사항(다단계 폼, 드래그앤드롭, 실시간 폴링)을 React Hooks와 최신 라이브러리(Zustand, RHF, Zod, dnd-kit)를 활용하여 성능과 유지보수성을 고려하여 구현하는 실전 경험을 쌓았습니다. Grafana Provisioning을 직접 다루며 DevOps 자동화의 강력함과 중요성을 체감했습니다.
  • 아쉬운 점 및 개선 방향: 현재 iframe으로 Grafana를 임베딩하는 방식은 완벽한 통합 UX에는 한계가 있습니다. 향후 Grafana의 Embed SDKPlugin 개발을 통해 더욱 네이티브한 경험(예: 커스텀 필터링 UI 연동)을 제공하고 싶습니다. 또한, 현재 폴링 방식은 실시간성이 다소 떨어지므로, WebSocket이나 Server-Sent Events(SSE) 를 도입하여 백엔드 작업 완료 시 즉시 UI에 반영되도록 개선할 수 있을것 같습니다.
  • 사용자 중심 설계: 사용자가 Grafana의 복잡성을 인지하지 못하도록 UI/UX를 설계하는 과정에서, 기술적 구현뿐만 아니라 사용자의 관점에서 문제를 바라보고 해결책을 제시하는 것의 중요성을 배웠습니다. 'Zero-Code' 설정이라는 목표를 달성하기 위해 폼 설계와 유효성 검증 로직에 많은 노력을 기울였고, 이는 사용자 편의성 증대에 대해 많은 고민을 할 수 있게 해주었습니다.