제목은 좀 거창하게 적었지만, 데이터 분석을 편하게 하기 위해서 원본 로그를 어떻게 적제할 것인가?에 대해서 간략히 글을 적으려 합니다. 오래 전부터 적고 싶었지만 기회가 나지 않아서 미루던 것인데, 완벽하지는 않겠지만 떠오르는대로 적겠습니다. 더 필요한 사항은 추후에 업데이트하겠습니다.
새로운 서비스를 오픈하면 다양한 시스템 히스토리나 사용자 사용 이력이 남습니다. 이를 로그 log라고 부릅니다. 그런데 이런 로그들은 대부분 그냥 시스템의 안정성/성능을 측정하거나 단순히 장애가 발생했을 때 어떤 원인으로 발생했는지 등과 같은 1차원적인 기록 및 대응을 위한 경우가 많습니다. 최근 데이터 분석이 주목을 받으면서 원본 데이터, 즉 로그에 대한 관심도 많습니다. 그런데 실상 로그를 분석해보려고 하면 당장 사용하기에 어려운 경우가 많습니다. 정작 필요한 데이터가 없는 경우도 많고, 있더라도 이상한 형태로 존재하거나 찾기가 어렵게 숨겨진 경우가 많습니다. 그래서 서비스를 준비하면서 처음부터 데이터 분석을 고려해서 로그 시스템도 설계할 필요가 있습니다.
데이터 분석에서 70~80%, 떄로는 90% 이상이 데이터를 정의하고 원하는 형태로 가공하는 작업입니다. 그런데 애초에 데이터 분석에 맞는 데이터만 로그에 남기로, 쉽게 읽을 수 있는 형태로 저장해둔다면 불필요한 초기 작업의 상당수를 줄일 수 있고, 데이터 분석이라는 핵심 역량에 더 집중할 수 있습니다.
가장 먼저 고려될 것은 데이터 포맷입니다. 데이터/로그를 남기는 것만으로 충분치 않고, 사람과 컴퓨터가 읽고 이해할 수 있는 형태로 남겨야 합니다. 가장 먼저 고려되는 형태는 단순히 탭으로 구분된 ASCII 문서입니다. 형태도 가장 간단하고 대부분의 분석 도구에서 바로 읽을 수 있기 때문에 가장 편한 포맷입니다. 불필요한 태그도 없기 때문에 적제된 로그 사이즈도 최소화할 수 있습니다. 그러나 한번 정의된 필드가 변경되면 관련된 모든 시스템을 변경해야 합니다. 그런 필드들의 속성 및 순서는 사전에 합의되야 합니다.
그래서 최근에는 XML, JSON, AVRO 등과 같이 태그(속성)과 값을 매핑한 형태의 구조화된 포맷으로 로그를 남기는 경우가 많습니다. 컴퓨터가 태그를 확인해서 필요한 필드를 따로 불러오면 됩니다. 스키마만 잘 정의되있다면 그것에 따라서 자유롭게 데이터를 추가/삭제/변경할 수 있습니다. 그러나 이런 구조화된 데이터를 컴퓨터가 읽기 위해서 별도의 파싱 parsing 프로그램을 구현해야 합니다. 그리고 태그=값 형태의 페어로 데이터가 저장되기 때문에 불필요하게 로그 사이즈가 커질 수도 있습니다.
요즘 스토리지 사이즈가 문제가 되지도 않고, 다양한 오픈소스로 데이터를 입출력하는 것이 간단하기 때문에 구조화된 형태로 저장하는 경우가 많습니다. 그러나 많은 서비스에서는 여전히 텍스트 문서로 된 로그가 가장 일반적입니다. 대부분의 웹서버로 사용되는 Apache의 로그도 탭 구분 텍스트로 저장되고 있기 때문에, 이 로깅시스템을 개선해서 부가정보를 남기면 됩니다. 그런데 이런 텍스트 로그는 어떻게 남길 것인가?에 대해서도 데이터 분석을 위해서 좀더 고민을 해야 합니다. 그냥 생각나는대로 온갓 정보를 순서대로 정렬해둔다면 서두에서 말했듯이 데이터를 해석하고 필요한 것만 추려내는데 불필요한 수고가 소요됩니다.
데이터 적제의 원칙이라면 ‘중요하고 필수적인 것은 앞쪽에, 덜 중요하고 부가적인 것은 뒤쪽에’ 놓는다로 요약할 수 있습니다. 파일 스트림을 앞쪽부터 읽기 때문에 필요한 데이터까지만 읽은 후에 멈추면 되기 때문에 빈번히 필요한 것은 앞쪽에 두면 불필요하게 뒤쪽의 데이터를 읽을 이유가 없기 때문입니다.
그러면 어떤 것이 중요한 데이터일까요? 몇 가지 생각나는 것을 나열하겠습니다.
- Identifiable 필드. 보통 데이터/로그가 한 행씩 누적되기 때문에 그 행(데이터)를 식별해줄 수 있는 값이 앞쪽에 오면 좋습니다. 필요한 데이터를 조회하기 위해서 전체 행을 스캔해서 필요한 데이터인지 여부를 확인할 것이 아니라, 앞쪽의 몇몇 필드만 확인해서 맞드면 전체를 불러오면 되기 때문입니다. Identifiable 필드는 예를들어 사용자의 접속 IP도 될 수 있고, 쿠키값이 될 수도 있고, 때로는 접속/로깅 일시가 될 수도 있습니다.
- Null이 가급적 없는 필드. 로그에 Null값 또는 공백이 포함되면 간혹 문제를 일으키기도 합니다. 예를들어, 프로그래밍 전에 사람이 눈으로 로그를 대강 훑어보는 경우가 많습니다. 그런데 특정 필드의 대부분의 값이 Null/공백인 경우도 종종 있습니다. 그런데, 여기에 공백이 포함됐다는 것을 인지하지 못하고 특정 필드를 생략하고 데이터를 읽어서 다른 속성에 값을 매핑하는 경우도 발생합니다. 그러면 당연히 제대로 된 분석이 이뤄질 수가 없습니다. 가급적 공백이 없는 데이터를 앞쪽에 저장하는 것이 좋겠지만, 어쩔 수 없는 경우에는 — 실수를 방지하기 위해서 — 공백 여부도 별도로 확인가능하도록 해두는 것이 좋습니다.
- 자주 사용되는 필드. 당연히 분석에서 자주 사용되는 필드가 있다면 앞쪽에 저장하는 것이 좋습니다. 예를들어, 사용자의 성별을 확인하는 작업이 빈번히 일어나는데 이 데이터를 로그의 뒤쪽에 심어둔다면 매번 전체 행을 모두 읽어와야 하는 불편함이 있습니다. 역으로 아주 가끔, 또는 거의 사용하지 않는 필드라면 뒤쪽에 남겨놔도 남겨놔도 관계는 없을 듯합니다.
- 정형화된 필드. 가급적이면 값이 정형화된 것들이 앞쪽에 있는 것이 좋습니다. 역으로 값 또는 포맷이 정형화되어있지 않다면 뒤쪽에 부가 필드에 기록하는 것이 좋습니다. 검색에서 쿼리 로그로 작업하는 경우가 종종 있습니다. 그런데 간혹 한글 키워드가 깨어졌거나 인코딩이 이상해서 전체 행에 문제가 발생하는 경우가 있습니다. 탭으로 구분된 로그에서 값에 탭 문자가 들어간 경우도 있습니다. 잘못된 필드값 하나 때문에 뒤쪽에 필요한 데이터를 읽어오지 못하는 경우는 가급적 없어야 합니다. 그래서 잘 정형화/정제된 값들이 앞쪽에 놓이는 것이 좋습니다.
- 값의 형태가 간단하고 짧은 필드. 비슷한 이유로 긴 스트링보다는 숫자나 짧은 단문/단어가 값인 필드가 앞쪽에 놓이는 것이 좋습니다.
- 시스템에서 자동으로 생성되는 것이라면 가급적 앞쪽에 둬서 불필요한 작업을 줄일 필요도 있습니다. 예를들어, 아파치 로그를 확장한다고 하면 아파치 서버에서 기본 제공되는 필드는 앞에 동일하게 적제하고 나머지 사용자 정의 필드를 뒤쪽에 쌓아두는 것이 여러 모로 맞습니다.
그리고 단순 변환만을 데이터를 추출할 수 있는 경우라면 굳이 중복해서 데이터를 나눠서 저장할 필요는 없을 듯합니다. 예를들어, 일시 ‘2014.11.10.13:14:20’라는 데이터가 있다면 여기서 날짜나 시간은 substring으로 바로 구할 수 있습니다. 그런데 굳이, 일시, 년, 월, 일, 시, 분, 초 등으로 세분화하거나 중복해서 기록할 필요는 없을 듯합니다. 데이터 사용성을 높이기 위해서 더 다양한 데이터를 저장한다고는 하지만, 간단한 변환으로 해결되는 것 때문에 불필요하게 데이터 필드를 늘려서 사이즈를 증가시키고 데이터 포맷만 복잡하게 만들 가능성도 있습니다. 로그 데이터의 포맷에서 KISS, 즉 Keep It Short & Simple 원칙이 적용됩니다.
==
페이스북 페이지: https://www.facebook.com/unexperienced
반응형