서비스가 점차 커지면서 에러를 빠르게 대응할 수 있는 환경이 필요했습니다. 이를 위해 모니터링 툴을 도입한 과정을 풀어봅니다.
모니터링 툴 선정하기
배경
대학교 bcsd 동아리에서는 학교 정보를 모아볼 수 있는 ‘코인(KOreatech INfo)’ 서비스를 제공하고 있습니다. 최근 적극적인 홍보와 학생들이 원하는 니즈를 잘 맞추어 기능을 빠르게 만들어내면서 서비스 사용자 수도 빠르게 늘어나고 있습니다. 그와 동시에 사용자들이 에러를 경험하고 동아리에 문의를 남기는 경우도 증가하게 되었습니다. 이유를 생각해 보자면 크게 두 가지가 나오는 것 같습니다.
- 기능을 빠르게 만들어냈지만, 그 만큼 기능에 대한 QA와 에러 처리가 제대로 되지 못했다.
- 사용자 풀이 넓어지면서 다양한 환경에서의 대응이 되지 않고 있다.
서비스 초기에는 console.error와 간단한 alert 정도로 에러를 찾아내 처리하는 식의 에러 대응 방법을 취했습니다.
하지만 현재 상황은 예전과는 사뭇 달라졌습니다. 서비스 사용자의 풀이 늘어나게 되면서 에러가 발생하게 되면 최대한 빠르게 이를 감지하고 해결할 수 있어야 했습니다. 또한 특정 오류 케이스는 개발자 환경에서 재현이 안되는 경우도 있었습니다. 이 문제 해결을 위해 코인 서비스에 모니터링 툴을 도입하고자 합니다.
개념
프론트엔드에서 모니터링 툴은 “사용자 경험, 성능, 오류 등을 실시간으로 감지하고 분석하는 도구” 라고 이야기 할 수 있을 것 같습니다. 대체적으로 아래 기능들을 제공합니다.
- 에러 추적 (Error Tracking)
- JavaScript 런타임 에러, 콘솔 에러, API 요청 실패 등을 자동으로 수집
- stack trace, 발생 시점의 URL, 사용자 정보 등을 함께 저장
- 사용자 세션 리플레이 (Session Replay)
- 실제 사용자가 페이지를 어떻게 이용했는지 영상처럼 재생
- 클릭, 스크롤, 폼 입력 등을 시각적으로 확인
- 성능 모니터링 (Performance Monitoring)
- 페이지 로딩 시간, LCP (Largest Content Paint), TTI (Time to Interactive) 등 Core Web Vitals 측정
- 특정 브라우저/기기에서 느린 이유를 파악 가능
- 사용자 행동 분석
- 사용자 행동 이벤트 추적 (클릭, 페이지 전환 등)
- 퍼널 분석, 이탈 포인트 분석 등 마케팅과도 연결 가능
- 실시간 알림
- 오류나 성능 저하 발생 시 Slack, Email 등으로 알림
이외에도 툴마다 더 다양한 기능이 있을 수 있을 수 있습니다.
우선순위 산정
모니터링 툴을 선정하기 전에 모니터링 툴을 선정하기 위한 우선순위를 산정해 보았습니다.
- 도입 배경에 맞는 문제 해결
- 에러를 빠르게 감지 및 해결
- 오류 케이스 재현 문제 해결
- 최대한 낮은 Cost
- 모니터링 툴 사용 시 추가적인 비용이 가능하면 없어야 함.
- 동아리 차원에서 모니터링 툴에 지속적으로 예산을 지원하기 어려움.
- 최소한의 컴퓨팅 자원
- 모니터링 툴을 직접 호스팅하게 된다면 고려해야함.
- aws EC2 T4g.small 스펙에 적용 가능해야함.

- 에러 연동
- Slack에 에러를 연동할 수 있어야함.
- 모니터링 툴 사용성 및 개발 효율성
- 관련 자료가 풍부한 사용자가 많은 모니터링 툴
- 문서를 통해 개발을 빠르게 진행 가능한 모니터링 툴
- 추가 기능 지원
- 사용자 에러 세션 리플레이
- 성능 모니터링 및 행동 분석 등
모니터링 툴 후보 선정 및 선택
모니터링 툴 후보를 선정할 때는 기본적으로 free trial을 제공하는 서비스만 포함해 5가지 후보를 선정했습니다.
- Openobserve
- Sentry
- Bugsink
- Bugsnag
- GlitchTip
Sentry와 Bugsnag은 각각 월에 5K, 7K 이벤트에 대해 무료 트래킹이 가능합니다. 다만, 현재 코인 서비스의 경우 월 약 34K 이벤트 수가 발생하고 있기 때문에 최악의 경우를 본다면, 두 모니터링 툴을 적용하기에는 예산적으로 무리가 있습니다.

따라서 후보군을 Openobserve, Bugsink, Glitchtip으로 줄여 생각해 볼 수 있습니다.
세 가지 모니터링 툴을 좀 더 자세히 알아보았습니다.

동일하게 셀프 호스팅을 지원하며 기본적인 도입배경에 대한 기능을 모두 충족하고 있습니다.
Openobserve의 경우 세션 리플레이 및 사용자 행동 분석 기능을 추가적으로 제공하지만 코인 서비스의 컴퓨팅 자원(t4g.small)만으로는 관리가 힘들 수 있다고 판단했습니다. Bugsink, Glitchtip의 경우 추가적인 세션 리플레이와 사용자 행동 분석과 같은 기능을 제공하지는 않지만, 도입 배경에 맞는 문제를 해결하기 위한 기능은 충분히 제공하고 있습니다.
특히 Bugsink는 가장 적은 컴퓨팅 자원만으로도 관리가 가능했기에 적합하다고 판단했습니다.
Bugsink에서 Glitchtip으로
하지만 Bugsink 적용 도중 Bugsink discord 채널을 통해 뒤늦게 multi file sourcemap을 아직 지원하지 않는다는 사실을 알게 되었습니다. Bugsink는 공식적으로 React + Vite 프로젝트에서 생성된 Source Map의 경로를 안정적으로 매핑하거나 활용하는 데 있어 제한적인 호환성을 보였고, 디버깅을 위한 stack trace의 역추적이 제대로 되지 않는 문제가 발생했습니다.
sourcemap을 제대로 사용하지 못하면 모니터링 툴을 적용하는 가장 큰 이유인 에러를 빠르게 감지 및 해결
하는데 어려움이 있었습니다.
이에 따라, Source Map을 안정적으로 처리할 수 있으며 Vite 환경에 대한 공식적인 지원 또는 검증된 사례가 있는 GlitchTip을 재검토하게 되었습니다.
Bugsink보다는 자원을 더 소모하고 설치하는 과정이 더 까다롭지만, 나머지 모니터링 툴에 비하면 가지고 있는 자원 내에서 해결할 수 있는 범주에 속했습니다. 특히 GlitchTip은 Sentry 기반의 오픈소스 프로젝트로, 자체 호스팅이 가능하며 Sentry와 거의 동일한 수준의 에러 추적 기능을 제공하면서도 Vite 환경에서의 Source Map 업로드 및 매핑에 대해 코드에서 sentry vite plugin을 활용한다는 것을 확인했습니다.
그래서 최종적으로 GlitchTip을 도입하기로 결정했습니다.
Bugsink를 적용했던 과정은 해당 노션 문서에 정리해 두었습니다. Bugsink 적용 과정을 확인하고 싶으신 분은 참고해주세요.
배경지식
GlitchTip의 경우 아래와 같은 구성으로 설계할 예정입니다.

이와 같이 설계하기 위해서 설계 그림에서 보여주는 서비스, 기술의 이해가 필요합니다. 배경 지식을 아래에 간단히 기술해 놓겠습니다.
배경 지식 확인하기
EC2
- AWS EC2는 AWS에서 제공하는 Virtual Server 서비스입니다.
- AWS Cloud 내의 server를 빌려서 사용한다고 생각할 수 있습니다.
AWS CloudFront
- AWS CloudFront는 AWS에서 제공하는 CDN입니다.
Nginx
- Nginx는 웹 서버, 리버스 프록시 서버, 로드 밸런서, http 캐시 기능을 제공하는 오픈소스 소프트웨어입니다.
Route53
- AWS Route53은 AWS에서 제공하는 DNS 서비스입니다.
Docker
- docker는 다양한 환경에서 앱을 실행하기 위한 동일한 환경을 구성 할 수 있도록합니다.
- 프로젝트 내에(Root에)
Dockerfile
파일을 만들어 환경 구성을 위한 코드를 작성합니다.
Image
- 설정된 환경과 Dockerfile 코드들을 통틀어 Image라고 하며 Image는 “프로젝트 세팅을 위한 설계도”로 이해할 수 있습니다.
- Dockerfile이 존재하는 프로젝트 폴더에서
docker build -t project-name
과 같이 docker image build를 할 수 있고, 이렇게 도커 이미지를 생성할 수 있습니다.
Container
- 실제로 실행한 프로그램 인스턴스를 말합니다.
docker run -dit -p 3000:80 project-name
과 같이 컨테이너로 실행할 수 있습니다.-p my-port:container-port
로 포트에서 포트로의 연결을 설정할 수 있습니다.- -dit의 경우 추가 옵션들에 해당합니다.
Docker-compose
- 여러 개의 Docker 컨테이너를 한 파일로 관리하는 도구입니다.
- 예를 들어, 프론트엔드의 react, 백엔드의 node.js+Express API, DB를 따로 실행해야 하는 경우 3개의 컨테이너를 실행시켜야 합니다. 이와 같은 상황에서 docker-compose.yml 파일을 활용해 모든 컨테이너의 설정을 기술하고,
docker-compose up
명령어로 한 번에 실행할 수 있습니다.
proxy
- proxy는 client쪽을 대신하며 client의 요청을 proxy가 대신 보냅니다.
- 대신 전달해주는 중간 서버 정도로 이해할 수 있습니다.
reverse proxy
- reverse proxy의 경우 client가 사이트에 접속하게 되면, 리버스 프록시 서버가 뒤에 있는 여러 서버들 중 하나에 요청을 대신 보내고 받아와서 전달합니다. (즉, 서버를 대신해서 요청을 받고 진짜 서버로 보내줍니다.)
- reverse가 붙고 안붙고의 차이로 누구를 위해 대신하냐로 구분됩니다.
web-service
- GlitchTip의 프론트엔드와 백엔드가 같이 들어있는 Django 기반 웹 서버 컨테이너입니다.
- 실질적인 에러처리를 확인하는 사이트를 제공합니다.
worker
- Celery라는 Python 비동기 프레임워크가 사용됩니다.
- GlitchTip은 일부 작업(예: 이메일 전송, 성능 이벤트 처리, 사용자 알림 등)을 즉시 처리하지 않고 큐에 넣고 백그라운드에서 처리합니다. 이 때 실제로 큐에서 작업을 가져와 처리하는 것이 worker입니다.
redis(valkey)
- GlitchTip의 web 컨테이너는 처리해야 할 비동기 작업을 큐에 넣고, worker는 그 큐를 읽어서 처리합니다. 그 중간 저장소 역할을 합니다.
- 즉, web와 worker가 메시지를 주고받기 위해 redis(valkey)를 사용하는 구조입니다.
postgreSQL
- GlitchTip은 Django 기반이고, 모든 프로젝트 정보, 사용자 정보, 이벤트 로그, 알림 설정 등이 전부 데이터베이스에 저장됩니다. 이 데이터베이스가 PostgreSQL입니다.
self-hosting
GlitchTip을 선택하게 된 이유 중 하나로 self-hosting을 들 수 있습니다. GlitchTip은 self-hosting의 목적에 부합하게 만들어져 있습니다.
- 외부 의존성이 없다.
- 소유한 서버, 환경 등에 직접 설치 가능하다.
에러 추적을 하게 되면 민감한 데이터를 포함하게 될 수 밖에 없습니다. 예를 들어 코인 서비스에 이를 적용하게 되면
- 학생 정보(이름, 학번, is, pw)
- 학점, 시간표 정보
- session token
등이 될 수 있습니다. 따라서 이를 제 3자의 서비스에 넘겨주는 상황을 사전에 방지해야 합니다. 이러한 방법을 data scrubbing이라고 하는데 이 과정이 상당히 복잡합니다.
실제 서비스 앱에서 민감 데이터를 식별하고 제거하는 코드를 작성한 뒤 테스트 해야합니다. 서비스의 기능이 추가되고 업데이트 될 때 마다 data scrubbing을 지속적으로 관리해야합니다. 제거의 정도를 제대로 조절하지 못하면 쓸모없는 리포트가 만들어질 수 있습니다. (ex. 에러 로그가 찍혀서 봤는데, 사용자 id가 지워져 있다면 누가 어떤 에러를 마주했는지 알 수 없어집니다.)
이 과정을 관리할 리소스가 동아리 내에 없었기 때문에 데이터를 내부에 유지할 수 있는 self-hosting을 활용하기로 했습니다.
docker-compose
GlitchTip은 self-host 환경 구축을 위해 필요한 이미지를 docker-compose를 예시로 제공합니다. 따라서 이에 맞추어 환경 구성을 위해 docker-compose를 활용합니다.
GlitchTip 적용
glitchtip 환경을 구성할 koin_internal ec2에 접속합니다.
docker-compose
GlitchTip에서 제공하는 docker-compose.sample.yml 을 활용해 docker-compose 환경을 구성합니다.
이 중 x-enviroment 안의 값들과 volumes의 경로 정도만 수정해주었습니다. T4g.small에서는 cpu core를 2개까지 지원하므로 CELERY_WORKER_AUTOSCALE 항목은 “1, 2”로 수정합니다.
volumes의 경우 아래와 같이 바라보게 하였습니다.
volumes:
- /var/lib/docker/volumes/glitchtip/pg-data:기존sample경로
docker compose up -d
를 통해 컨테이너를 올리면 아래와 같이 총 4개의 컨테이너가 올라갑니다.

약 virtual 1GB 정도의 컨테이너가 올라갔습니다.
RAM limit 설정
glitchtip 구동을 위해 관련 컨테이너가 사용하는 RAM이 EC2의 제한량과 나머지 컨테이너에게 영향을 끼치지 않도록 RAM limit을 설정했습니다.
우선 혼잡하지 않은 평소의 memory usage를 확인합니다. docker stats 명령을 사용합니다.

기존 memory usage에 맞게 약 2배 정도의 여유를 주어 limit을 걸어줍니다. docker-compose.yml 파일의 service에 명시되어 있는 각 컨테이너들에 mem_limit 옵션을 추가해 줍니다.
최종적으로 아래와 같은 파일 형태를 사용했습니다.
x-environment: &default-environment
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:${POSTGRES_PORT}/${POSTGRES_DATABASE}
SECRET_KEY: ${SECRET_KEY}
PORT: 8000 # If changing, change the web service port too
EMAIL_URL: consolemail:// # Example smtp://email:password@smtp_url:port https://glitchtip.com/documentation/install#configuration
GLITCHTIP_DOMAIN: https://glitchtip.bcsdlab.com # Change this to your domain
DEFAULT_FROM_EMAIL: smallkdb@gmail.com # Change this to your email
CELERY_WORKER_AUTOSCALE: "1,2" # Scale between 1 and 3 to prevent excessive memory usage. Change it or remove to set it to the number of cpu cores.
x-depends_on: &default-depends_on
- postgres
- redis
services:
postgres:
image: postgres:17
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DATABASE}
restart: unless-stopped
mem_limit: 100m
volumes:
- ${POSTGRES_VOLUME_PATH}:/var/lib/postgresql/data
redis:
image: valkey/valkey
restart: unless-stopped
mem_limit: 50m
web:
image: glitchtip/glitchtip
depends_on: *default-depends_on
ports:
- "8000:8000"
environment: *default-environment
restart: unless-stopped
mem_limit: 250m
volumes:
- ${CODE_UPLOADS_VOLUME_PATH}:/code/uploads
worker:
image: glitchtip/glitchtip
command: ./bin/run-celery-with-beat.sh
depends_on: *default-depends_on
environment: *default-environment
restart: unless-stopped
mem_limit: 270m
volumes:
- ${CODE_UPLOADS_VOLUME_PATH}:/code/uploads
migrate:
image: glitchtip/glitchtip
depends_on: *default-depends_on
command: ./bin/run-migrate.sh
environment: *default-environment
~
router53, nginx 설정
router53에 glitchtip
레코드를 추가해서 사용합니다.(과정은 생략합니다.)
https ssl 설정과 dns 할당을 위해 nginx 설정 파일을 작성합니다.
공식 문서를 참고해 기본 틀을 작성했습니다.
koin_internal EC2 서버에서는 /etc/nginx/sites-available
에 nginx 파일을 저장하고 있습니다.
glitchtip파일을 만들어 작성합니다.
server {
server_name glitchtip.bcsdlab.com;
client_max_body_size 40M;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' '*' always;
add_header 'Access-Control-Allow-Headers' '*' always;
add_header 'Access-Control-Max-Age' 86400 always;
return 204;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8000;
}
}
certbot으로 ssl 인증서를 발급받습니다.
sudo certbot --nginx -d glitchtip.bcsdlab.com
발급에 성공하면 glitchtip nginx 파일에 관련 코드가 추가 됩니다. nginx와 docker compose를 재실행한 후 해당 도메인에서 GlitchTip이 잘 동작하는지 확인합니다.

sentry sdk 설정
KOIN front 프로젝트로 이동한 후, @sentry/browser를 설치해줍니다.
npm i @sentry/browser –save
그리고 production 환경에서만 에러를 트래킹 할 수 있도록 init 로직을 작성합니다. dsn 경로는 추후 값의 변경과 너무 쉽게 값이 노출되는 문제를 막고자 환경 변수로 분리했습니다.
import * as Sentry from '@sentry/browser';
if (import.meta.env.MODE === 'production' && import.meta.env.VITE_GLITCHTIP_DSN) {
Sentry.init({
dsn: import.meta.env.VITE_GLITCHTIP_DSN,
release: 'koin@0.1.0',
});
}
에러가 잘 들어오는 것을 확인할 수 있습니다.

sourcemap 설정
GlitchTip은 @sentry/vite-plugin을 지원합니다. 따라서 해당 플러그인을 사용해 sourcemap을 설정했습니다.
연결을 위한 Auth Token을 발급받습니다.

vite.config.ts 의 plugin에 빌드와 배포 url에 맞게 다음 설정을 추가하고 build의 sourcemap option을 true로 바꾸어 설정을 마무리 합니다.
... // 중략
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default defineConfig(({ mode }) => {
...
return {
plugins: [
...,
sentryVitePlugin({
org: 'bcsdlab',
project: 'koin',
url: 'https://glitchtip.bcsdlab.com/',
release: {
name: 'koin@0.1.0',
uploadLegacySourcemaps: {
paths: ['./build/assets'],
urlPrefix: '~/assets',
},
},
authToken: env.VITE_SENTRY_AUTH_TOKEN,
}),
],
server: {
port: 3000,
},
build: {
outDir: 'build',
sourcemap: true,
},
};
});
빌드 과정에서 다음과 같은 에러를 마주했습니다.

해당 에러는 GlitchTip 프로세스가 해당 경로에 디렉토리나 파일을 만들 권한이 없기 때문에 발생합니다. 따라서 sourcemap을 읽고 사용할 web-service 컨테이너의 uid를 확인한 후 이에 맞게 호스트 소유권 변경을 진행했습니다.
// container uid 확인
$ docker exec -it glitch-tip-compose-web-1 id
uid=5000(app) gid=5000(app) groups=5000(app)
// permission 수정
$ sudo chown -R 5000:5000 (해당하는 docker-compose의 volume)
$ sudo chmod -R 755 (해당하는 docker-compose의 volume)
이후 컨테이너를 다시 내렸다 올립니다.

sourcemap이 정상적으로 올라갔습니다. test용 에러를 찍어 sourcemap이 제대로 매핑된 모습을 확인할 수 있습니다.

프로덕션 sourcemap 삭제
sourcemap 으로 전체 코드가 노출되는 것을 방지하지 위해 glitchtip에 sourcemap 정보를 전달한 후 실제 배포 시엔 sourcemap을 삭제하는 과정을 거쳐줍니다.
빌드 디렉토리에 sourcemap이 존재하는 경로를 찾아 삭제시키는 스트립트를 작성합니다.
// 중략...
"sourcemap:clean": "find ./build -name '*.map' -type f -delete"
그리고 jenkins execute shell 과정에서 yarn build
후 yarn sourcemap:clean
을 해줍니다.
배포 환경을 확인해보면 .map파일이 삭제된 것을 확인할 수 있습니다.
GlitchTip webhook 설정
slack과 연동하기
GlitchTip은 자체적으로 web hook을 지원합니다. project setting에서 에러 발생 시 alert recipients를 설정해줄 수 있습니다.

web hook url은 slack api에서 해당하는 그룹의 app을 들어가서(없다면 생성) 해당 채널의 incoming web hook url을 복사해 사용하면됩니다.

에러가 발생하면 채널에 설정한 앱에 맞게 메세지를 띄워주는 것을 확인할 수 있습니다.

B_BOT과 연동하기
slack 채널에 연동하기 위해서는 위와 같이만 진행해도 무방합니다. 하지만 텍스트 메세지를 꾸미거나 에러가 나왔을 때 특정 인원을 멘션하는 등의 추가적인 기능을 넣기 위해 slack bot 전용 서버인 B_BOT에 연결해서 사용을 하려 합니다.
B_BOT은 Nitro 웹 서버 기반으로 구성된 프로젝트입니다.
Nitro plugin으로 slack bot token을 받아 전용 web client를 만들어줄 수 있습니다.
Nitro는 unJS를 사용하고 있기 때문에 defineNitroPlugin
함수의 선언이나 import 없이 사용할 수 있습니다.
import { WebClient } from '@slack/web-api';
import { createPool } from '~/helper/adapter/mysql';
export default defineNitroPlugin(async (nitroApp) => {
const webClient = new WebClient(import.meta.env.SLACK_BOT_TOKEN);
const pool = createPool();
nitroApp.hooks.hook('request', (event) => {
event.context = {
...event.context,
slackWebClient: webClient,
sqlPool: pool,
};
});
});
이 web client를 사용해 glitchtip에서 받은 alert 메세지를 커스텀 해서 새롭게 보내줄 수 있습니다.
웹 서버에서 glitchtip alert 메세지를 받을 api 경로는 아래와 같이 설정했습니다. nitro는 next와 비슷하게 폴더기반 api를 자동으로 생성해줍니다.

그리고 glitchtip alert 메세지 형태를 확인하고 잘 넘어오는지의 여부를 위해 콘솔을 찍어봅니다.
export default defineEventHandler(async (event) => {
try {
const test = await readBody(event);
console.log(test);
return 'OK';
} catch (error) {
throw createError({
statusCode: 500,
statusMessage: `Error: ${error}`,
});
}
});
로컬 환경 테스트
로컬 환경에서 테스트를 위해서 ngrok을 사용했습니다. ngrok은 로컬에서 실행 중인 서버를 외부 인터넷에 안전하게 노출시켜주는 터널링 도구입니다. ngrok을 통해 로컬에서 실행 중인 서버를 외부에서 접근 가능한 URL로 변환할 수 있습니다. 설치 과정은 생략하겠습니다.
KOIN 프로젝트에 테스트용 에러를 포함해 로컬에서 build하고 서버와의 CORS policy를 위해 3000번 포트로 열어줍니다.
B_BOT 웹 서버는 3001번 포트로 열어줍니다.

이제 3001번 포트의 로컬 웹 서버를 외부에서 접근 가능한 url로 변환합니다.
npx ngrok http 3001
다음과 같은 화면으로 전환되며 forwarding에서 외부 접근 가능한 url을 확인할 수 있습니다.

변환된 url을 활용해 glitchtip web hook url에 https://ab4e-220-68-91-183.ngrok-free.app/api/glitchtip/frontend
을 적용합니다.
이후 테스트용 에러를 빌드된 코인 프로젝트에서 발생시키면 아래와 같이 콘솔에 찍힌 응답을 받을 수 있습니다.

받은 응답을 참고해서 api 코드를 수정했습니다.
import CHANNEL_ID from '@/constant/CHANNEL_ID.json';
export default defineEventHandler(async (event) => {
try {
const { attachments } = await readBody(event);
await event.context.slackWebClient.chat.postMessage({
channel: CHANNEL_ID.코인_오류_front_end,
text: ':rotating_light: 코인 서비스에서 오류가 발생했습니다.',
attachments,
});
return 'OK';
} catch (error) {
throw createError({
statusCode: 500,
statusMessage: `Error: ${error}`,
});
}
});
그리고 glitchtip webhook url을 웹 서버 도메인을 갖도록 수정합니다.

이제 커스텀한 alert 메세지를 받을 수 있습니다.

맺음말
마무리하며, 이번 포스팅에서는 코인 서비스에 에러 트래킹을 위한 GlitchTip 모니터링 툴을 도입한 전체 과정을 살펴보았습니다. Bugsink에서 겪었던 sourcemap 호환성 문제를 해결하기 위해 GlitchTip을 재검토하고, EC2 위 self-hosting 환경에 맞추어 Docker-Compose, Nginx, Route 53, SSL 인증, 그리고 Vite 기반 프론트엔드와의 통합까지 차례로 구성해 보았습니다. 또한, Slack 알림뿐 아니라 Nitro 기반의 B_BOT과 연동해 더 세밀한 커스텀 알림을 구현한 과정도 다뤘습니다.
이제 GlitchTip이 안정적으로 운영 중이니, 다양한 환경에서 재현하기 어려웠던 오류도 상세한 stack trace와 세션 정보를 통해 더욱 빠르게 디버깅할 수 있게 되었습니다. 잎으로 실시간 에러 발생 시 즉각적인 대응이 실직적으로 이루어졌는지 살펴보고자 합니다. 감사합니다.