기술

1GB/일 원본을 81% 절감했습니다 — 운영 진입 전 로그 처리의 점진 진화

2026.05.2912분 읽기

"1GB/일 원본이 DB에 5-6GB로 쌓일 뻔했습니다"

AI 운영 플랫폼의 로그 처리 시스템이 운영 진입 직전이었습니다. 외부 시스템에서 흘려보낸 로그 파일을 받아서 적재하고 검색하는 인프라였어요.

운영 진입 전에 한 가지가 보였습니다. 1GB/일 원본 로그가 DB에 5-6GB/일로 쌓일 위험.

이유는 단순했어요. 파서가 형식 매칭되는 모든 라인을 level 무관하게 적재하고 있었습니다. INFO도 WARN도 ERROR도 다 들어가요. 게다가 격상 로직(특정 패턴이면 INFO를 ERROR로 격상)이 파서 안에 인라인으로 박혀 있어서, 파서마다 동작이 달랐습니다.

운영 시작 후에 이걸 잡으려고 하면 늦어요. 이미 데이터가 쌓이고 있는 상태에서 필터를 도입하면 마이그레이션 부담이 폭증합니다. 운영 진입 전이 마지막 적기였습니다.

같은 날 4가지 작업이 동시에 진행됐어요.

1. 적재 필터 — 81% 절감 (메인)
2. 적재 이력 화면 — 휘발성 결과를 영구화
3. UX 진단 — 0건일 때 사용자 추론 부담 제거
4. 데이터 모델 분리 Step 1 — 미래 흐름 분리의 첫 단계

이번 글은 그 중 메인이었던 적재 필터(81% 절감)와 점진 진화 패턴을 정리한 회고입니다.


적재 필터 — 89,280 라인을 16,576건으로

가장 무거운 작업이었습니다. 두 개의 필터를 도입했어요.

1. min_level — 최소 레벨 필터

LogSystem 테이블에 min_level 컬럼을 추가했습니다. 값은 ALL / INFO / WARN / ERROR 네 가지. 시스템별로 어느 레벨부터 적재할지 정합니다.

대부분의 시스템은 WARN 이상으로 잡았어요. INFO 라인은 디버깅 시에만 필요하고 운영에서는 노이즈입니다. WARN 이상만 적재해도 운영에 필요한 정보는 다 들어와요.

2. ingest_keyword_regex — 적재 키워드 whitelist

INFO 라인 중에도 보존하고 싶은 게 있습니다. "사용자 로그인 성공" 같은 패턴은 INFO지만 운영에서 추적이 필요해요. 이런 라인을 위해 ingest_keyword_regex whitelist를 추가했습니다.

min_level = WARN
ingest_keyword_regex = (login_success|payment_completed|user_registered)

위 설정이면 WARN 이상 + INFO 중 whitelist 매칭만 적재됩니다. 공격적 필터링과 운영 추적성을 동시에 잡았어요.

검증 결과

한 외부 시스템의 두 로그 파일로 검증해봤습니다.

파서가 형식 매칭한 라인: 89,280건

필터 통과 후 실제 적재: 16,576건 (18.6%)

절감률: 81.4%

1GB/일 원본이 DB에 약 1GB/일 적재로 떨어졌어요. 5-6GB 누적 위험이 사라졌습니다.

1.jpeg


격상 로직 위치 결정 — 파서 inline에서 ingest 단계로

필터 도입과 함께 한 가지 구조 결정이 있었습니다. 격상 로직을 어디에 둘 것인가예요.

기존 구조에서는 격상 로직(error_keyword_regex / warn_keyword_regex)이 파서 안에 인라인으로 박혀 있었습니다. 한 외부 시스템(idms 같은)의 파서에는 격상 룰이 있고, 다른 파서에는 없었어요.

문제가 두 가지였습니다.

1. 파서마다 동작 달라짐

같은 INFO 라인이라도 파서마다 격상 여부가 다릅니다. A 파서는 ERROR로 격상하고, B 파서는 그대로 INFO로 둬요. 운영자가 "왜 이건 ERROR로 잡혔는데 저건 안 잡혔지?"라고 혼란스러워집니다.

2. 단일 책임 위반

파서의 책임은 로그 라인을 파싱(디코드)하는 것입니다. 격상은 비즈니스 룰이에요. 파서 안에 격상 룰이 박히면 책임이 섞입니다.

결정: 격상 로직을 ingest 단계로 이전

[기존]
파서 (디코드 + 격상) → DB

[변경]
파서 (디코드만) → ingest (격상 + 필터) → DB

이제 모든 파서가 균일하게 동작합니다. 격상 룰은 ingest 단계 한 곳에서 관리돼요. 새 파서 추가 시 격상 룰을 똑같이 박을 필요가 없어졌습니다.

이 변경의 부작용 하나가 있었어요. 기존 시스템에 격상이 새로 적용됩니다. INFO였던 라인이 새 룰에 의해 ERROR/WARN으로 격상될 수 있어요. release note에 명시했습니다.


나머지 3가지 진화 — 간략 정리

같은 날 진행된 나머지 3가지 작업은 간략하게 정리하겠습니다.

1. 적재 이력 화면 — 휘발성 결과를 영구 이력으로

기존에는 스캔/업로드 후 결과가 휘발성 모달로만 보였어요. 사라지면 끝. log_ingestion 테이블 기반의 이력 표를 만들어서 영구 이력으로 전환했습니다. 시스템·파일명·라인·적재·필터스킵·상태·시각이 한 화면에 보이고, [이벤트보기] 버튼으로 log-explorer로 이동 가능합니다.

휘발성 결과가 영구 이력이 되면 운영 가시성이 크게 올라가요. 운영자가 "어제 이 시스템 적재 결과가 어땠지?"를 즉시 확인할 수 있습니다.

2. UX 진단 — 0건일 때 사용자 추론 부담 제거

log-explorer에서 검색 결과가 0건일 때, 단순 "결과 없음" 대신 진단 메시지 + [전체 X로 재검색] 액션 버튼을 추가했습니다. "데이터 자체가 없는지 vs 필터 때문인지" 사용자가 즉시 구분할 수 있어요.

적재 페이지에는 polling을 추가했어요. status=parsing row가 있으면 5초마다 자동 갱신, 모두 종료되면 자동 stop. 운영자가 새로고침 없이 진행 상태를 볼 수 있습니다.

3. 데이터 모델 분리 Step 1 — "추가만" 패턴

여기서 흥미로운 통찰 하나가 있었어요. 로그 처리 중에 한 가지 본질이 보였습니다. 로그는 두 가지 흐름이다.

rotated — 일/시간 단위로 완성되는 파일 (영구 보관, 대시보드용)

realtime — 실시간으로 append되는 스트림 (알람용, 소모성)

두 흐름은 retention 정책, 대시보드 사용, 알람 동작이 모두 달라요. 장기적으로는 데이터 모델 자체를 분리하는 게 맞았습니다.

다만 지금 한 번에 다 분리하면 위험이 컸어요. 운영 진입 직전이라 큰 리팩토링은 부담입니다. 그래서 "추가만" 패턴으로 갔습니다.

[Step 1 — 데이터 모델만 추가]
기존 log_event 유지 (= rotated 흐름)
신규 log_event_realtime + log_ingestion_realtime + watch_paths_realtime 추가

[Step 2 — 실시간 수집 메커니즘 별도 plan]
realtime 흐름 활성화는 다음 단계

기존 테이블은 건드리지 않고 신규만 추가합니다. Step 1이 안전하게 운영에 들어가면, Step 2(실시간 수집)는 시기를 자유롭게 정할 수 있어요. UI에서는 자동 수집 패널을 두 섹션(정기 스캔 + 실시간 추적)으로 분리하고, realtime은 비활성 안내로 처리했습니다.

84개 pytest 회귀 통과로 안전성을 검증했어요.

2.jpeg


점진 진화 + "추가만" 패턴의 가치

이번 4가지 작업을 정리하고 보니 두 가지 일반 패턴이 보였어요.

1. 점진 진화 — 한 번에 큰 리팩토링 대신 단계적

이번에 적재 필터·이력 화면·UX 진단·데이터 모델 분리 4가지를 동시에 진행했어요. 큰 작업처럼 보이지만, 각각이 작은 단위로 완결됩니다. 필터는 컬럼 2개 + ingest 로직 이동, 이력은 단일 파일 수정, UX는 진단 메시지 + polling, 데이터 모델은 "추가만" 패턴.

한 번에 큰 리팩토링은 위험이 큽니다. 각 변경의 영향 범위가 섞이고, 롤백이 어려워요. 작은 단위로 분리하면 각 변경을 독립적으로 검증할 수 있고, 문제 발생 시 그 단계만 되돌릴 수 있습니다.

2. "추가만" 패턴 — 데이터 모델 분리의 안전한 첫 단계

데이터 모델 진화는 위험한 영역이에요. 운영 중인 테이블 구조를 바꾸면 마이그레이션 부담이 폭증합니다. "추가만" 패턴은 이 위험을 회피해요.

[안전한 패턴]
기존 테이블 그대로 유지
신규 테이블 추가
점진적으로 신규 테이블 활용 확대

[위험한 패턴]
기존 테이블 구조 변경
데이터 마이그레이션
신구 코드 공존 기간 관리

"추가만" 패턴은 운영 진입 전이라 가능한 선택이었어요. 운영 시작 후에는 마이그레이션 비용이 폭증하니까, 미래 분리를 위한 데이터 모델 첫 단계는 운영 진입 전이 적기입니다.


로그 처리 시스템 검토 체크리스트

로그 처리·데이터 적재·운영 진입 준비를 검토하실 때 점검할 일반 체크리스트입니다.

1. 운영 진입 전 데이터 부하를 시뮬레이션합니다

원본 데이터 크기와 DB 누적 예상치를 미리 계산합니다. 1GB/일 원본이 DB에 어떻게 쌓일지 보면 필터 도입 필요성이 명확해져요. 운영 시작 후 잡으려면 마이그레이션 부담이 폭증합니다.

2. 필터 + whitelist 조합을 검토합니다

공격적 필터링만 하면 운영에서 필요한 정보가 빠집니다. min_level + keyword whitelist 조합으로 절감과 추적성을 동시에 잡을 수 있어요. WARN 이상 + INFO 일부 보존 패턴이 안전합니다.

3. 책임 위치를 점검합니다 — 단일 책임 원칙

격상 로직, 필터링 로직, 파싱 로직이 어디에 있는지 점검합니다. 파서마다 다른 동작이 있으면 책임이 섞인 신호예요. 한 곳에서 관리되게 정리하면 새 파서 추가 시 일관성이 자동 보장됩니다.

4. 데이터 모델 진화는 "추가만" 패턴으로 시작합니다

미래 분리가 필요하다고 판단되면, 운영 진입 전에 데이터 모델 첫 단계만 박아둡니다. 기존 테이블은 건드리지 않고 신규만 추가. 활성화는 별도 단계로 분리. 미래 시기를 자유롭게 정할 수 있고, 운영 시작 후 큰 리팩토링 위험이 사라집니다.

비슷한 발상이 다른 운영 결정에서도 흐릅니다. 운영 진입 전이 결정의 마지막 적기인 작업이 있다는 것, 큰 리팩토링 대신 점진 진화로 위험을 줄이는 것, "추가만" 패턴으로 미래 진화의 기반을 깔아두는 것. 운영 진입 준비의 핵심 기준입니다.


마무리

AI 운영 플랫폼의 로그 처리를 운영 진입 직전 정리했습니다. 적재 필터(min_level + keyword whitelist)로 81% 데이터 절감을 만들었고, 격상 로직을 파서 inline에서 ingest 단계로 이전해서 모든 파서 균일 동작을 확보했습니다. 같은 날 이력 화면 영구화, UX 진단 추가, 데이터 모델 분리 "추가만" Step 1까지 4가지 작업이 점진 진화로 진행됐어요.

운영 진입 전이 데이터 부하 잡는 마지막 적기 — 운영 후 마이그레이션 부담이 폭증

격상 로직은 단일 책임으로 한 곳에 둔다 — 파서 inline 대신 ingest 단계 → 모든 파서 균일

"추가만" 패턴이 데이터 모델 진화의 안전한 첫 단계 — 기존 테이블 변경 없이 신규만 추가

로그 처리·데이터 적재·운영 진입 준비를 검토하신다면, 이번 글의 4가지 체크리스트(데이터 부하 시뮬레이션 / 필터 + whitelist 조합 / 책임 위치 점검 / "추가만" 패턴)를 한 번 살펴보시길 추천합니다. 운영 진입 직전이 마지막 적기인 작업을 미루지 않으면, 운영 안정성이 처음부터 잡힙니다.

#로그처리#데이터필터#점진진화#데이터모델링#운영진입#AI전환기