디버깅(?) 기록 - DB복구, Sentry

shkilo·2021년 6월 27일
0
post-custom-banner

DB 복구

운영하던 서비스의 DB를 날려먹는 사고가 났다...

부하테스팅을 위해 테스트용 DB와 앱서버를 띄웠고 테스트 할 때마다 테이블을 초기화 하도록 설정해 놓았다. 그런데 .env 의 호스트정보를 업데이트 하지 않아 프로덕션 DB 데이터가 다 날라간 것이다. 심지어 3일 후에 알았는데 작은 서비스인데도 식은땀이 줄줄 났다,,

다행히도 RDS 자동 백업이 활성화 되어있어서 사고 하루 전의 DB로 복구하고 이후 데이터는 쿼리 및 하드코딩을 통해 복구했다. RDS를 사용하니 백업 및 복구가 매우 쉬운 것 같다. 기존 머신에다 DB 설치 후 띄우는 방식으로 계속 사용했었으면 아마 복구하지 못했을 것 같다.

앞으로 이런 일를 방지하기 위해 DB유저의 권한을 바꾼다.

REVOKE DROP ON *.* FROM 'username'@'%';

앞으로 귀찮더라도 GRANT ALL은 하면 안될것 같다.
또한 유저이름, 비밀번호 등도 프로덕션과 테스트를 항상 다르게 하면 좋겠다.

Sentry 를 통한 디버깅

서비스를 배포하고 보면 개발단계에서 생각지도 못한 오류가 끊임없이 발생한다. 처음 배포한 후에는 오류가 발생했다는 사실을 알 방법이 스토어 댓글밖에 없었다.

위처럼 오류가 계속 나는데 알람 같은게 따로 없으니 오류가 오래 지속되는 경우가 많다. 로깅도 따로 하지 않아서 왜 오류가 났는지 확인하기도 어려웠다.

그래서 해결책으로 Sentry 라는 에러 모니터링 툴을 사용해보기로 했다.
NestJS의 interceptor를 써서 간단하게 적용할 수 있다.

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import * as Sentry from '@sentry/node';

@Injectable()
export class SentryExceptionInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      catchError((error) => {
        Sentry.captureException(error);
        throw error;
      }),
    );
  }
}
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new SentryExceptionInterceptor());

이후 Sentry 앱에서 에러 발생시 메일로 알람을 보내도록 설정한다.

발생한 에러

적용한 후 알람이 계속 오길래 확인해 봤더니 task를 생성하지 못하는 오류가 있었다. 로컬에서 똑같은 오류를 발생시키려 했는데 아무리 해도 안되서 일단 보류해놨었다.

그런데 알람이 계속 온다, 방치하면 안되겠어서 다시 확인해 봤더니 실패한 요청의 OS가 다 안드로이드였다. 그래서 안드로이드 vm을 띄우고 삽질을 잠깐 했는데 잘 생각해보니 OS의 문제가 아니였다.

task 는 항상 부모 섹션에 종속되고 섹션은 항상 프로젝트에 종속된다. 그래서 최초 유저 생성시 기본 프로젝트와 기본 섹션이 생성되도록 되어있다. 그런데 언젠가 코드 수정을 하면서 기본 섹션을 생성하는 부분이 누락된 것이었다. 바로 수정을 하고 테스트코드도 업데이트 하였다.

테스트케이스를 좀 더 주의깊게 작성하면 이런 오류는 예방할 수 있을 것 같다.

post-custom-banner

0개의 댓글