[팀 개발 문화 발전시키기] Grafana를 이용하여 DB 통합 대시보드 만들기

Hadooboo·2023년 8월 27일
0
post-thumbnail

DB 통합 대시보드를 만들어야겠다고 마음먹은 이유

사실 데이터베이스 각각의 현황을 한눈에 알아볼 수 있는 웹페이지를 만들어서 보기 좋게 관리해야겠다는 생각은 항상 하고 있었다. 여러 프로토타입을 만드는 우리 팀에서는 더 자주 데이터베이스 목록이 변경되고, 데이터가 추가되었다가 삭제되기 때문에 이를 머리속에서 계속 유지하거나 매번 데이터베이스 쉘에 접속해서 cli로 확인하는 것에는 한계가 있었다.

이런 생각만 하고 있다가 마침 chromadb + clickhouse 조합으로 텍스트 벡터 임베딩을 저장해야 하는 업무가 있었다. 그런데 chromadb는 cli도 제공하지 않아 매번 python 또는 javascript로 코드를 만들어 데이터베이스 안에 있는 내용을 확인해야 하는 문제가 있었다. 동시에 이렇게 데이터베이스가 또 하나 늘어나면 관리해야 하는 데이터베이스가 mysql, mongodb, chromadb + clickhouse 조합까지 해서 3개가 되는 셈이었다.

이제는 정말 데이터베이스 통합 대시보드 툴이 필요한 시점이 되었다.

개선한 내용

chromadb + clickhouse?

chromadb + clickhouse 조합이 무엇인지부터 정리하고 넘어가자.

chromadb는 자연어 문장을 벡터 임베딩한 결과를 저장해주는 데이터베이스이다. 그러나 독립적으로 동작하는 프로그램은 아니고 실제 데이터가 저장될 데이터베이스 위에 하나의 레이어를 덧대서 임베딩 처리라든지 여러 유틸리티 기능을 제공한다.

따라서 chromadb는 실제 데이터를 저장할 데이터베이스를 지정해주어야 한다. 그것을 clickhouse로 선택한 것이다. 파일시스템에 저장하는 duckdb도 있으나 chromadb를 컨테이너로 띄우는 상황에서 데이터를 안전하게 관리하기 위해 clickhouse 데이터베이스를 선택하였다.

그렇다고 파일시스템을 사용하는 데이터베이스에 비해 무조건 clickhouse가 더 안전하다는 것은 아니다. 다만 공식 문서에서 chromadb + clickhouse를 docker-compose로 띄우는 방법을 소개하였고 도커 볼륨 마운팅을 통해 clickhouse 데이터를 도커 볼륨에 보관한다. 이를 차용하였다. chromadb 0.3.x 버전 기준이다.

chromadb에서 정의하는 콜렉션 개념이 clickhouse에 그대로 저장되기 때문에 clickhouse 를 확인하는 것만으로도 chromadb의 상태를 확인할 수 있다.

clickhouse 시각화가 필요한 이유

clickhouse는 chromadb와 달리 cli 툴을 제공한다. docker exec 을 통해 컨테이너 내부의 쉘에 접속해서 데이터베이스의 내용을 확인할 수 있다. 그러나 mysql과 mongodb는 cli 말고도 mysql workbench, mongodb compass 라는 GUI 툴을 제공해서 필요할 때 쉽게 눈으로 전체적인 내용을 확인할 수 있는 방법이 있지만 clickhouse는 공식적으로 제공하는 전용 GUI 툴이 없다. 항상 cli가 좋은 것은 아니다. 한 눈에 전체적인 내용을 확인할 필요가 종종 있다. 이것이 첫번째로 시각화 대시보드를 만들어야 하는 이유였다.

또한, mysql 같은 관계형 데이터베이스를 사용하는 유즈케이스는 정적인 경우가 많아서 데이터베이스 스키마가 변경되는 일이 그렇게 잦지는 않았다. 그러나 지금 진행중인 프로젝트는 일종의 연구 개념이 섞여 있어서 계속해서 사원들 각자가 콜렉션을 만들고 삭제하곤 했다. 각각의 콜렉션 이름 뿐만 아니라 콜렉션을 언제 만들었고, 몇 개의 아이템이 들어있는지 등 메타데이터가 있어야 빠르게 원하는 콜렉션을 선택해서 사용할 수 있었다. 이런 정보를 확인하기 위한 대시보드가 필요했다.

어떤 대시보드 툴을 사용할까?

그래서 일단 clickhouse를 시각화하는 방법을 알아보기 위해 clickhouse 공식 사이트에서 시각화를 하는 방법을 찾아보았다.

데이터를 시각화할 수 있는 여러 툴들을 알려준다. clickhouse의 시각화에만 사용할 것이라면 목록에 있는 아무 툴이나 사용해도 됐을 것이다. 그러나 마침 이참에 다른 데이터베이스, mysql, mongodb도 같이 시각화할 수 있는 툴을 사용하는 것이 좋겠다는 생각이 들었다.

그래서 기준을 Free License를 가지고 있으면서, mysql mongodb clickhouse 데이터베이스를 모두 지원하는 프로그램으로 정했다. 당연하지만 정확히 위 3개의 데이터베이스만 지원하는 것이 아니라 앞으로 추가될 여러 데이터베이스들에도 쉽게 연동이 가능하면 더 좋다.

대충 후보는 Grafana, Tableau, Superset 정도가 있었다. 각각의 특징은 다음과 같았다.

  • Grafana: 일단 들어봤다. 그리고 mysql, mongodb, clickhouse 모두 공식 connector를 제공한다.
  • Tableau: 학교 수업에서 사용해보기까지 했다. 3개의 데이터베이스 모두 connector를 제공한다. 그러나 무료가 아니다.
  • Superset: 들어봤다. 그리고 mysql, clickhouse에 대해서는 공식 connector를 제공한다. 그러나 mongodb에 대해서는 써드파티를 통해야만 연결이 되는 것 같고, 공식 문서에서도 등장하지 않는다.

따라서 더 볼 것도 없이 Grafana를 선택하게 되었다.

Grafana 설치하기

개발서버에서 프로그램을 실행할 때 가능하면 항상 도커 컨테이너로 실행하는 룰을 지키고 있다. Grafana는 도커 허브에서 공식 이미지도 제공하고 있다.

도커 허브에서 보면 grafana/grafana, grafana/grafana-oss, grafana/grafana-enterprise 3개가 있어서 헷갈릴 수 있다. 이 중 grafana/grafana, grafana/grafana-oss는 동일하고 오픈 소스 버전이다. tags 탭에 들어가서 hash digest를 확인해보면 동일한 것을 알 수 있다.

단순 대시보드 확인 용도이기 때문에 enterprise로 넘어갈 일은 없을 것 같아서 grafana/grafana-oss를 선택하였고, 버전은 가장 최신인 10보다는 하나 낮은 9에서 가장 높은 9.5.5로 선택하였다. 모든 최신 기능을 사용할 것이 아니라면 가장 최신 버전은 아무래도 문서도 적고 안정성 면에서도 꼭 좋은 선택은 아닐 것이다.

실행은 다음과 같은 command로 하였다.

$ sudo docker run -itd --name=grafana -p $GRAFANA_PORT:3000 -v grafana:/var/lib/grafana grafana/grafana-oss:9.5.5
  1. 3000 포트를 그대로 이용하는 것은 현명하지 못하다. 모든 프로그램에서 default로 제시하는 포트를 사용하지 말자. 해커들의 공격에 취약해지기 쉽다.
  2. 도커 볼륨을 이용해서 데이터를 컨테이너의 실행 중단에 상관없이 영구적으로 보존할 수 있게 한다.

초기 username:password 는 admin:admin 으로 되어 있고, 로그인하자마자 새로운 비밀번호로 바꾸라고 한다. 새로운 비밀번호를 만들어 로그인하면 기본 대시보드가 보인다.

Clickhouse 연결 설정하기

Grafana를 설치한 최우선적인 목적은 chromadb + clickhouse의 시각화를 하는 것이다. 따라서 clickhouse의 연결부터 설정하였다.

Home > Connections > Connect data 에 들어가서 검색해보면 clickhouse를 찾을 수 있다.

Grafana를 9.5.5 버전으로 설치했는데, Grafana >= 9.0.0 가 Dependencies에 걸려 있는 것을 보니 버전을 8.x 로 설치했으면 이용을 아예 못했을 것 같다.
https://grafana.com/grafana/plugins/grafana-clickhouse-datasource/

clickhouse를 누르면 여러 설정들을 할 수 있는 페이지가 나온다. 여기서 clickhouse를 접근할 수 있는 ip 주소와 port까지 지정하였다. 따로 ssl이나 credential 관련 설정은 없었다.

그러나 문제는 여기서 발생하였다. 연결을 시도하는데도 계속 connection timeout이 뜰 뿐 아무 결과가 나오지 않았다. 원인을 고민해보던 중 이전에 썼던 방화벽 관리 글이 떠올랐다. 다른 bridge 네트워크에 속한 도커 컨테이너끼리는 iptables 위에서 서로 통신이 되지 않도록 막아져있기 때문에 연결되지 않은 것이다. grafana는 system default로 있는 bridge 네트워크로 실행했고, chromadb + clickhouse는 도커 컴포즈로 실행했기 때문에 별도의 bridge 네트워크인 chroma_net 에 속한다.

이를 해결하기 위해서는 다음과 같은 명령어를 실행하면 된다.

$ docker network connect chroma_net grafana

도커 컨테이너는 동시에 여러 bridge 네트워크에 속할 수 있다. 위 명령어는 grafana 컨테이너를 chroma_net 네트워크에도 연결시키겠다는 뜻이다.

이렇게 한 뒤 grafana 설정으로 돌아와서 server address 자리에 chroma_clickhouse_1 을 입력한다. 같은 bridge 네트워크 안에서 내부적으로 dns가 작동하기 때문에 꼭 172.x.x.x 형태의 ip를 직접 입력하지 않고 컨테이너 이름으로 지정하면 된다.

이렇게 했더니 연결이 완료되었다. Save & test 버튼을 눌렀을 때 "Data source is working" 라고 나오면 성공이다.

Clickhouse 대시보드 만들기

이제 Home으로 다시 가서 clickhouse에 대한 대시보드 컴포넌트를 만들자. Home 우측 상단에 있는 Add > Row 버튼을 눌러 우선 ChromaDB 관련된 내용들을 담을 행을 만들었다. 그리고 다시 Add > Visualization 버튼을 눌러 실제 시각화할 내용을 구성할 페이지로 이동하였다.

쿼리는 다음과 같이 작성하였다. Query builder도 있지만 raw sql을 사용하는 것이 나에게는 더 편하다. default.collections.name 필드가 생성한 embeddings 컬렉션의 이름을 의미한다. 이 이름을 확인하여 어떤 컬렉션들을 만들었는지 눈으로 쉽게 확인하고 프로그램에서 필요한 것을 사용할 수 있다. 각 컬렉션 안에 embedding이 몇 개 있는지 확인하기 위해 그 개수를 counting 하는 컬럼도 조인을 통해 추가하였다.

SELECT default."collections"."uuid", default."collections"."name", default."collections"."metadata", count(*) AS "number of embeddings"
FROM default."collections"
JOIN default."embeddings" ON default."collections"."uuid" = default."embeddings"."collection_uuid"
GROUP BY default."collections"."uuid", default."collections"."name", default."collections"."metadata"

Run query 버튼을 눌러 보면 상단 탭에서 결과를 확인할 수 있다.

MySQL 연결 설정하기

Home > Connections > Connect data 에 들어가서 검색해보면 마찬가지로 mysql을 찾을 수 있다.

Clickhouse에 비해 mysql 연결은 상대적으로 간단했다. mysql은 개발서버에서 베어메탈로 실행되고 있는 프로그램이기 때문에 ip, port를 직접 입력해도 된다. 다만, grafana에서만 접근할 수 있는 mysql 유저를 새로 하나 만들어 독립성을 유지하도록 했다.

MySQL 대시보드 만들기

시각화를 추가하는 방법은 clickhouse에서와 동일하므로 생략한다. 대신 어떤 시각화들을 왜 추가했는지에 대한 내용만 남겨 놓는다.

대시보드로 만들어야 하는 것은 mysql 쉘에 접속해서 자주 쿼리하는 내용들이다. 자주 쿼리하는 내용일수록 대시보드로 만들었을 때 일의 효율성이 높아질 것이다. 그런 의미에서 우선 2가지 시각화를 만들기로 하였다.

  • 유저 목록

grafana를 위한 전용 mysql 유저를 만들었던 것처럼 각 어플리케이션을 위한 유저를 따로 두고 각각의 접근 권한을 다르게 하는 것이 데이터를 안전하게 유지 및 관리하기에 좋다. 반면에 유저가 많아지면 많아질수록 하나의 root 유저를 두었을 때보다는 기억하기에 어려워진다. 따라서 mysql.user, mysql.host 컬럼을 출력해주는 대시보드가 하나 필요하였다.

다음은 유저 목록을 확인하는 쿼리문이다. host가 localhost인 경우 출력에서 제외하였는데, 각 어플리케이션에서 사용하고 있는 유저 목록을 보기 위한 용도이므로 root 유저 등은 출력할 필요가 없기 때문이다.

SELECT User, Host FROM mysql.user WHERE Host != "localhost"
  • 데이터베이스 목록

데이터베이스 목록도 유저 목록과 같은 맥락에서 필요한 대시보드이다. 여러 프로젝트를 진행하면서 데이터베이스를 각각 생성하고, 테스트 데이터베이스를 만들기도 하며 배포 준비용으로 만들기도 한다. 이렇게 여러 데이터베이스가 생기고 없어지는 것을 머리 속 기억으로 유지하는 것은 비효율적이다.

다음은 현재 일차적으로 만든 쿼리문이다. 데이터베이스의 이름과 각 데이터베이스에 속한 테이블의 수를 표 형태로 보여주고자 하였다.

SELECT
  schema_name AS "name",
  (SELECT count(*) FROM information_schema.tables WHERE information_schema.tables.table_schema = information_schema.schemata.schema_name) AS "number of tables"
FROM information_schema.schemata;

아직은 대시보드에 최소한의 내용만으로 일단 띄워보기 위한 수준이고, 앞으로 내용이 추가될 수 있을 것이다.

MongoDB 연결 설정하기 & 대시보드 만들기

No valid Grafana Enterprise license detected.

MongoDB 커넥션을 연결하려고 하니 위와 같은 문구를 발견하였다. 지금은 CE를 사용 중이기 때문에 사용할 수가 없는 것이다.

다행히 MongoDB를 이용한 현재 진행중인 프로젝트가 없기 때문에 MongoDB 대시보드가 꼭 필요하지는 않았다. 앞으로 필요한 상황이 생긴다면 위에서 살펴본 여러 대안들 중의 하나로 이전해야 할 수도 있다. 커넥터가 존재한다는 것만 확인하는 것이 아니라 더 자세하게 각 커넥터 설명을 살펴보았어야 했다는 아쉬움이 남는다.

회고

들어가면서 말했던 것처럼 이와 같은 DB 통합 대시보드 툴을 만들어야겠다는 생각은 하고 있었다. 그리고 만들기 어려운 기술은 아니므로 시간만 들이면 충분히 직접 구현할 수도 있다.

직접 손으로 하는 구현이 필요할 때가 있다. 구현을 하면서 원리를 이해할 수도 있고, 코딩 실력, 아키텍팅 실력이 늘 수도 있다. 그러나 개발자란 내가 할 수 있는가만 생각하면서 개발을 하는 것이 아니라 얼마나 효율적으로 그 구현을 할 수 있는가를 항상 생각하여야 한다. 이미 널리 사용되고 검증된 Grafana라는 툴이 있었기 때문에 이것을 선택했다. 구현 연습을 하기에는 다른 주제도 많다.

DB 통합 대시보드를 만들고 나니 앞으로 관리가 정말 편해질 것 같다는 생각이 든다. 아직 추가하지 않은 여러 메트릭들도 SQL 몇 개만 이용해서 쉽게 추가할 수 있을 것이다. 더 나아간다면 Grafana + Loki + Promtail 스택을 이용하여 ELK 스택처럼 로그 수집 및 분석을 위해서도 사용할 수 있을 것이다.

어디서 개발자는 1년 전의 나보다 더 나은 방법으로 개발하고 있어야 한다는 글을 보았다. 1년 전의 나는 MySQL 쉘에 일일이 접속해서 매번 비슷한 쿼리를 통해 인포메이션을 얻고 있었다. 적어도 이 부분에 있어서는 1년 전의 나보다 나아진 것 같다.

profile
'왜'를 궁금해하는 개발자

0개의 댓글