회사 서비스의 로그는 서비스 내부에서 다음과 같은 목적으로 저장되고 있었다.
- 사용자의 행동이 발생할 때마다 OR 내부 서비스와 외부 ERP / API 인터페이스 호출마다
- Controller → Service → DAO 흐름 단위의 로그 데이터를 DB에 저장
그리고 관리자가 필요할 때 에러를 검색할 수 있는 관리 페이지에서 조회할 수 있도록 설계되어 있었다.
문제는 실제 운영 상황에서는 이 데이터를 거의 사용하지 않는다는 점이었다.
실제 운영 모니터링은 대부분
- DataDog
- Whatap
같은 APM 도구를 통해 이루어지고 있었고, DB 로그 테이블은 사실상 방치된 상태였다.
게다가 이 서비스는 오픈된 지 8년이 넘었지만 단 한 번도 삭제 작업이 이루어지지 않았다.

그 결과... 운영 DB 용량의 50% 이상이 로그 테이블이었다.
RDS 환경에서 커지는 비용 문제
DB는 AWS RDS를 사용하고 있었다.
RDS의 특징 중 하나는 스토리지 자동 확장이다.
데이터가 늘어나면 자동으로 저장 공간이 증가하고, 그만큼 운영 비용도 계속 증가한다.
즉,
- 사용하지 않는 로그 데이터가
- DB 용량의 대부분을 차지하고
- 그로 인해 운영 비용까지 증가하는 상황
이었다. 따라서 로그 데이터를 정리하는 작업이 필요했다.
삭제 전략
데이터를 줄이는 방법으로는 다음과 같은 방법도 고려할 수 있었다.
새로운 인스턴스를 만들고 마이그레이션
하지만 운영 중인 서비스에서 이 작업을 수행하기에는 부담이 컸다.
또한 로그 데이터는 고객사가 필요할 경우 조회할 수 있어야 했기 때문에 완전히 제거할 수는 없었다.
그래서 내부 정책에 따라 데이터 보존 기간을 설정하고 다음과 같은 방식으로 정리하기로 했다.
- 보존 기간보다 오래된 데이터를 일괄 삭제
- 이후에는 스케줄러를 통해 주기적으로 삭제
아무 생각 없이 DELETE 했다가 생긴 일
DELETE FROM LOG_TABLE
WHERE CREATE_DATE < SYSDATE - 보존기간;
개발 환경에서 테스트했을 때는 시간이 조금 걸리긴 했지만 정상적으로 삭제가 되었다.
그래서 그대로 운영 환경에서도 삭제 작업을 진행했다.
그런데 삭제 작업을 진행하던 중 인프라 팀에서 연락이 왔다.
'지금 삭제되는 데이터 때문에 Archive Log가 계속 쌓여서 DB 남은 용량이 급격히 줄어들고 있어요.'
DELETE는 생각보다 무거운 작업이다
SQLP 공부를 하면서 INSERT의 Redo 로깅 최소화 방법은 알고 있었다.
하지만 그때 깨달은 것이 하나 있었다.
DELETE는 Redo 로깅 최소화가 불가능하다.
대량 데이터를 한 번에 삭제하면 아래와 같은 일이 발생한다.
- Undo 생성
- Redo 생성
- Archive Log 증가
결국 내가 실행한 쿼리는 대량 Archive Log 생성기와 다름없었다.
해결 방법
그래서 삭제 방식을 다음과 같이 변경했다.
- Cursor + Fetch로 테이블을 한 번만 Full Scan
- 삭제는 작은 단위(batch) 로 수행
- 일정 건수마다 Commit
예시 구조는 대략 이런 형태였다.
CURSOR c_log IS
SELECT ROWID INTO ROWIDS
FROM LOG_TABLE
WHERE CREATE_DATE < SYSDATE - 보존기간;
FETCH ...
DELETE FROM LOG_TABLE
WHERE ROWID IN ROWIDS;
COMMIT;
이 방식의 장점은 다음과 같다.
- 테이블 Full Scan은 한 번만 수행
- DELETE는 소량 단위로 처리
- Undo / Redo 크기 감소
이 방법으로도 절대적인 삭제하는 용량 자체는 줄일 수 없기 때문에 한번 삭제 작업하고 쌓이는 Archive Log의 유지 기간인 7일 ~ 10일 이후에 지우는 방향으로 변경되어 두달이상은 간간히 삭제했던 것 같다.
Enterprise Edition이었다면..?
만약 DB가 Oracle Enterprise Edition이고 날짜 기준으로 Range 파티션이 나뉘어 있다면
ALTER TABLE LOG_TABLE DROP PARTITION P_2021;
같은 방식으로 거의 즉시 삭제가 가능하다.
장점은 다음과 같다.
- 빠른 삭제
- Undo / Redo 부담 감소
- 조회 성능 개선
하지만 회사에서 사용하는 DB는 Oracle Standard Edition이었기 때문에 이 방법은 사용할 수 없었다.
이번 작업을 하면서 느낀 점
SQLP를 공부할 때 종종 이런 이야기가 나온다.
대량 데이터를 삭제할 때는
임시 테이블을 만들고
삭제 대상 데이터를 제외하고 INSERT 한 뒤
테이블을 교체하는 방식이 더 빠르다.
이론적으로는 알고 있었지만 내가 쓸일이 있을까..? 싶었는데 하지만 이번 경험을 통해 대량 DELETE가 얼마나 위험할 수 있는지
그리고 왜 그런 방식이 권장되는지 조금은 체감할 수 있었다.