로그 기깔나게 잘 디자인하는 법
흔히 만나는 실제 사례를 중심으로
라인게임즈
백정상
로그를 통해
• 비즈니스 의사결정에 필요한
• 객관적이고
• 명확한
• 지표를 얻을 수 있음
하지만 로그 기록은
로그 대충 쌓으면
• 지표가 부정확하거나 생성 불가능
• 잘못된 결정
• 운영 실수
• 유저 이탈
• 매출 하락
• 인센티브 못 받음
• 집 대출금은 어쩌지??
흔히 일어나는 사례 : #1
뭘 봐야할 지 애매해서 일단 뭐
든 쌓아봤어요
보고싶은 지표를 먼저 명확하게 설정하자
예) 보고싶은 지표
• DAU (Daily Active Users)
• 일자/레벨 별 스테이지 클리어 정보
• 일자 별 골드 획득 소비량 / 획득 사유
DAU
• 이벤트 : 유저 로그인
• 유저 식별자
• 기기 : 광고 아이디 (ADID, IDFA)
• 유저 : 유저 아이디 (Nickname, etc.)
• 기기 정보
• 모델명, OS, 언어, 스토어 타입 등
• 기타
• 연령, 성별
• 유저 레벨
• 타임스탬프
일자 / 레벨 별 스테이지 클리어
• 이벤트 : 스테이지 클리어
• 유저 식별자
• 스테이지 인덱스
• 스테이지 클리어 여부
• 플레이 한 캐릭터 정보
• 유저 레벨
• 타임스탬프
일자 / 레벨 별 골드 획득 및 사유
• 이벤트 : 골드 획득
• 유저 식별자
• 유료 / 무료 재화 변동수치
• 유료 / 무료 재화 변동 결과
• 유저 레벨
• 재화 획득 사유
• 타임스탬프
어라 이런 것도 볼 수 있네?
• 시간대별 로그인 횟수
• 유저들이 가장 많이 플레이하는 캐릭터
• 로그인 횟수와 스테이지 클리어 간의 상관관계
• 스테이지별 골드 획득량
• 유저 레벨 별 로그인 횟수
로그를 제대로 디자인하면
보고 싶은 지표에 대한 아이디어가 새록새록
로그를 디자인하는 시점
• 앱 릴리즈 전
• 릴리즈 전 최종 기능 확정
• 확정된 기능에 대한 지표 확정
• 지표에 필요한 로그 수집
• 앱 릴리즈 후
• 업데이트 기능 기획 시점 지표 확정
• 지표에 필요한 로그 수집
잘 디자인 된 로그는 기록하기 편합니다
흔히 일어나는 사례 : #2
로그인 해야 로비에 들어가니까,
로비에 들어갈 때 로그인 로그를
찍었어요
근데 튜토리얼 지나야 로비에
들어가긴 해요
로그인
튜토리얼
진행
광고 시청 로비 입장
오 이 게임 재미있네?
내 스타일이야 좋았으~
한번 달려본다!
로그인 기록 시점
기록
로그인
튜토리얼
진행
광고 시청 로비 입장
아이고 애미야!
돈 준다길래 시키는 대로 했더니
이상한 게 켜진다~
로그인 기록 시점
이탈
정확한 로그의 기준을 설정
• 앱 실행 - 로그인
• 액티브 유저로 볼 수 있음
• 앱 실행 – 로그인 – 튜토리얼 – 로비
• 좀 더 깊이 플레이 한 유저
• 인게이지드 유저로 볼 수 있음
• 다시 로그를 심어봐야…
• 전체 기간 액티브 유저는 확인 불가
로그가 정확히 쌓이는지 매번 검증
• 앱 릴리즈 전 / 기능 업데이트 시
• QA 시점에 수집된 로그 검증
• 검증 안 해서 이상한 데이터 쌓이면
• 무엇이 오염된 것인지 정확하게 구분하기 진짜 어려움
• 한번 오염된 로그는 전체 로그의 효용가치를 파괴
정확하게 기록된 로그는 귀한 자원이 됩니다
흔히 일어나는 사례 : #3
리스펀스 저장하면 로그 아니
에요?
용량 줄이려고 JSON 이차원 배
열에 값 밀어 넣었어요
예) 스테이지 클리어 시 아이템 획득
{
user_id:”hackest”,
stage_id:1
is_clear:1
play_char_id:3920,
user_level:11,
ts:”2017-10-13 07:00:00.392Z”,
rewards:[[0,15,300], [1,20802,1500]]
}
예) 스테이지 클리어 시 아이템 획득
{
user_id:”hackest”,
stage_id:2
is_clear:1
play_char_id:3920,
user_level:11,
ts:”2017-10-13 07:11:30.392Z”,
rewards:[[3,15,3], [12,2082,1], [0,15,400]]
}
쿼리를 작성해보려고 하니
SELECT user_id, rewards…
보상 아이템 위치가 계속 바뀌네???
WITH temp_stage_reward_item AS (SELECT …)
보상 아이템 갯수가 가변이네???
… json_extract_array_element_text(’rewards', pos)…
엄청나게 느리네???
파서 작성해야 함
def process(record):
parsed = {‘user_id’:record.user_id, ‘stage_id’:record.stage_id …}
parsed[‘rewards’] = []
for reward in rewards:
parsed.rewards.push(
{‘type’:reward[0], ‘id’:reward[1], ‘value’:reward[2]}
)
log_writer.write(parsed)
이렇게 파서 짜면 되지 않나요?
• 되긴 함
• 하지만 로그 종류가 200여 가지라면
• 파서 짜고 검증하는데 시간 너무 오래 걸림
• 하루에 10억 행이 쌓인다면
• 대부분 파서는 복잡한 일을 하고
• 로그 스트림에 사용되는 워커 스케일 업 요구
예제 개선
{
user_id:”hackest”,
stage_id:1
is_clear:1
…
rewards:[
{type:0, id:15, value:300},
{type:1, id:20802, value:1500}
]
}
데이터는 테이블 형태로 기록하자
• 대부분의 빅데이터 솔루션은 스키마 정의만 해주면
• SQL 질의가 가능
• 행/열 형태로 저장되는 게 제일 좋음
• CSV
• Key-value paired JSON Object
용량 및 저장비용 이슈
• 좋은 압축 알고리즘 적용하자
• Gz, lzo, zstd, parquet
• 클라우드 스토리지는 비싸지 않음
• S3 1TB 저장비용 = 약 월 $25
• 스탠다드, 스탠다드-IA
흔히 일어나는 사례 : #4
로우 데이터를 레드시프트에
다 넣어요
1TB 노드 2개 쓰는데 하루에
100기가씩 쌓여요. 어떡하죠?
그래도 되긴 하는데…
• 레드시프트는 2PB까지 저장 가능
• 하지만 꺼둘 수가 없음
• 그 로그를 과연 상시 쿼리할까?
• 의도 이상으로 컴퓨팅 비용이 너무 높음
방안
• 핫 / 콜드 데이터를 구분
• 핫 : 데이터 분석가가 주로 쿼리 날리는 데이터
• 콜드 : 1년에 한번 쿼리 할까 말까 한 데이터
• 핫 데이터는 데이터 웨어하우스에
• 콜드 데이터는 저렴한 스토리지에
• 콜드 데이터 검색은 빅쿼리 / 아테나 /프레스토로
핫 데이터를 더 정제하자
• Star / Snowflake Schema
• Fact, Dimension으로 디자인
• 데이터 최적화
데이터 워크플로우를 관리하자
• 정제 작업은 데이터 워크플로우 툴을 사용
• 정제한 데이터만 데이터 웨어하우스에 저장
• 노드 / 비용 절감
• 쿼리 퍼포먼스 향상
정리
• 보고싶은 지표를 명확히 설정하고
• 기록할 데이터의 형식과 시점을 매번 검증하고
• 테이블 형태로 기록해주시고
• 핫 / 콜드 데이터 잘 분리해주시고
• 데이터 워크플로우 잘 관리해주시면
• 어느 플랫폼에서나
• 데이터 분석 쉽고 빠르게 시작하실 수 있습니다
끝
jsbaek @ line.games

로그 기깔나게 잘 디자인하는 법

  • 1.
    로그 기깔나게 잘디자인하는 법 흔히 만나는 실제 사례를 중심으로 라인게임즈 백정상
  • 2.
    로그를 통해 • 비즈니스의사결정에 필요한 • 객관적이고 • 명확한 • 지표를 얻을 수 있음
  • 3.
  • 7.
    로그 대충 쌓으면 •지표가 부정확하거나 생성 불가능 • 잘못된 결정 • 운영 실수 • 유저 이탈 • 매출 하락 • 인센티브 못 받음 • 집 대출금은 어쩌지??
  • 9.
  • 10.
    뭘 봐야할 지애매해서 일단 뭐 든 쌓아봤어요
  • 12.
    보고싶은 지표를 먼저명확하게 설정하자
  • 13.
    예) 보고싶은 지표 •DAU (Daily Active Users) • 일자/레벨 별 스테이지 클리어 정보 • 일자 별 골드 획득 소비량 / 획득 사유
  • 14.
    DAU • 이벤트 :유저 로그인 • 유저 식별자 • 기기 : 광고 아이디 (ADID, IDFA) • 유저 : 유저 아이디 (Nickname, etc.) • 기기 정보 • 모델명, OS, 언어, 스토어 타입 등 • 기타 • 연령, 성별 • 유저 레벨 • 타임스탬프
  • 15.
    일자 / 레벨별 스테이지 클리어 • 이벤트 : 스테이지 클리어 • 유저 식별자 • 스테이지 인덱스 • 스테이지 클리어 여부 • 플레이 한 캐릭터 정보 • 유저 레벨 • 타임스탬프
  • 16.
    일자 / 레벨별 골드 획득 및 사유 • 이벤트 : 골드 획득 • 유저 식별자 • 유료 / 무료 재화 변동수치 • 유료 / 무료 재화 변동 결과 • 유저 레벨 • 재화 획득 사유 • 타임스탬프
  • 18.
    어라 이런 것도볼 수 있네? • 시간대별 로그인 횟수 • 유저들이 가장 많이 플레이하는 캐릭터 • 로그인 횟수와 스테이지 클리어 간의 상관관계 • 스테이지별 골드 획득량 • 유저 레벨 별 로그인 횟수 로그를 제대로 디자인하면 보고 싶은 지표에 대한 아이디어가 새록새록
  • 19.
    로그를 디자인하는 시점 •앱 릴리즈 전 • 릴리즈 전 최종 기능 확정 • 확정된 기능에 대한 지표 확정 • 지표에 필요한 로그 수집 • 앱 릴리즈 후 • 업데이트 기능 기획 시점 지표 확정 • 지표에 필요한 로그 수집
  • 20.
    잘 디자인 된로그는 기록하기 편합니다
  • 21.
  • 22.
    로그인 해야 로비에들어가니까, 로비에 들어갈 때 로그인 로그를 찍었어요
  • 23.
    근데 튜토리얼 지나야로비에 들어가긴 해요
  • 24.
    로그인 튜토리얼 진행 광고 시청 로비입장 오 이 게임 재미있네? 내 스타일이야 좋았으~ 한번 달려본다! 로그인 기록 시점 기록
  • 25.
    로그인 튜토리얼 진행 광고 시청 로비입장 아이고 애미야! 돈 준다길래 시키는 대로 했더니 이상한 게 켜진다~ 로그인 기록 시점 이탈
  • 26.
    정확한 로그의 기준을설정 • 앱 실행 - 로그인 • 액티브 유저로 볼 수 있음 • 앱 실행 – 로그인 – 튜토리얼 – 로비 • 좀 더 깊이 플레이 한 유저 • 인게이지드 유저로 볼 수 있음 • 다시 로그를 심어봐야… • 전체 기간 액티브 유저는 확인 불가
  • 27.
    로그가 정확히 쌓이는지매번 검증 • 앱 릴리즈 전 / 기능 업데이트 시 • QA 시점에 수집된 로그 검증 • 검증 안 해서 이상한 데이터 쌓이면 • 무엇이 오염된 것인지 정확하게 구분하기 진짜 어려움 • 한번 오염된 로그는 전체 로그의 효용가치를 파괴
  • 28.
    정확하게 기록된 로그는귀한 자원이 됩니다
  • 29.
  • 30.
  • 31.
    용량 줄이려고 JSON이차원 배 열에 값 밀어 넣었어요
  • 32.
    예) 스테이지 클리어시 아이템 획득 { user_id:”hackest”, stage_id:1 is_clear:1 play_char_id:3920, user_level:11, ts:”2017-10-13 07:00:00.392Z”, rewards:[[0,15,300], [1,20802,1500]] }
  • 33.
    예) 스테이지 클리어시 아이템 획득 { user_id:”hackest”, stage_id:2 is_clear:1 play_char_id:3920, user_level:11, ts:”2017-10-13 07:11:30.392Z”, rewards:[[3,15,3], [12,2082,1], [0,15,400]] }
  • 34.
    쿼리를 작성해보려고 하니 SELECTuser_id, rewards… 보상 아이템 위치가 계속 바뀌네??? WITH temp_stage_reward_item AS (SELECT …) 보상 아이템 갯수가 가변이네??? … json_extract_array_element_text(’rewards', pos)… 엄청나게 느리네???
  • 35.
    파서 작성해야 함 defprocess(record): parsed = {‘user_id’:record.user_id, ‘stage_id’:record.stage_id …} parsed[‘rewards’] = [] for reward in rewards: parsed.rewards.push( {‘type’:reward[0], ‘id’:reward[1], ‘value’:reward[2]} ) log_writer.write(parsed)
  • 36.
    이렇게 파서 짜면되지 않나요? • 되긴 함 • 하지만 로그 종류가 200여 가지라면 • 파서 짜고 검증하는데 시간 너무 오래 걸림 • 하루에 10억 행이 쌓인다면 • 대부분 파서는 복잡한 일을 하고 • 로그 스트림에 사용되는 워커 스케일 업 요구
  • 37.
  • 38.
    데이터는 테이블 형태로기록하자 • 대부분의 빅데이터 솔루션은 스키마 정의만 해주면 • SQL 질의가 가능 • 행/열 형태로 저장되는 게 제일 좋음 • CSV • Key-value paired JSON Object
  • 39.
    용량 및 저장비용이슈 • 좋은 압축 알고리즘 적용하자 • Gz, lzo, zstd, parquet • 클라우드 스토리지는 비싸지 않음 • S3 1TB 저장비용 = 약 월 $25 • 스탠다드, 스탠다드-IA
  • 40.
  • 41.
  • 42.
    1TB 노드 2개쓰는데 하루에 100기가씩 쌓여요. 어떡하죠?
  • 43.
    그래도 되긴 하는데… •레드시프트는 2PB까지 저장 가능 • 하지만 꺼둘 수가 없음 • 그 로그를 과연 상시 쿼리할까? • 의도 이상으로 컴퓨팅 비용이 너무 높음
  • 44.
    방안 • 핫 /콜드 데이터를 구분 • 핫 : 데이터 분석가가 주로 쿼리 날리는 데이터 • 콜드 : 1년에 한번 쿼리 할까 말까 한 데이터 • 핫 데이터는 데이터 웨어하우스에 • 콜드 데이터는 저렴한 스토리지에 • 콜드 데이터 검색은 빅쿼리 / 아테나 /프레스토로
  • 45.
    핫 데이터를 더정제하자 • Star / Snowflake Schema • Fact, Dimension으로 디자인 • 데이터 최적화
  • 48.
    데이터 워크플로우를 관리하자 •정제 작업은 데이터 워크플로우 툴을 사용 • 정제한 데이터만 데이터 웨어하우스에 저장 • 노드 / 비용 절감 • 쿼리 퍼포먼스 향상
  • 51.
    정리 • 보고싶은 지표를명확히 설정하고 • 기록할 데이터의 형식과 시점을 매번 검증하고 • 테이블 형태로 기록해주시고 • 핫 / 콜드 데이터 잘 분리해주시고 • 데이터 워크플로우 잘 관리해주시면 • 어느 플랫폼에서나 • 데이터 분석 쉽고 빠르게 시작하실 수 있습니다
  • 52.

Editor's Notes

  • #5 하지만 로그 기록은 귀찮은 작업 컨텐츠 제작 막바지에 하는 작업 그래서 대충하고, 실수를 많이 하게 됨 그리고 그래도 된다고 생각하는 경우 많음 뭐 어떻게 쌓든 나중에 분석해주겠지
  • #6 하지만 로그 기록은 귀찮은 작업 컨텐츠 제작 막바지에 하는 작업 그래서 대충하고, 실수를 많이 하게 됨 그리고 그래도 된다고 생각하는 경우 많음 뭐 어떻게 쌓든 나중에 분석해주겠지
  • #7 하지만 로그 기록은 귀찮은 작업 컨텐츠 제작 막바지에 하는 작업 그래서 대충하고, 실수를 많이 하게 됨 그리고 그래도 된다고 생각하는 경우 많음 뭐 어떻게 쌓든 나중에 분석해주겠지
  • #8 그럼 이제 어떻게 해야하느냐.. 하면
  • #9 이미 망한거죠 ㅋㅋ 답 없습니다. 이번 생애는 망했다고 생각하고 대충 살면 되죠 뭐.. ㅋ 계속 망할 수는 없잖아요? 이렇게 망하는 흔한 사례와 이런 상황을 해결하기 위한 솔루션들을 지금부터 소개해 드리려고 합니다.
  • #12 이유가 없이 쌓인 로그는 쓰레기에 불과한 데이터 그런 로그 더미에서 인사이트를 찾아내는 과정은 쓰레기 더미에서 보물을 캐듯 어려운 작업 쌓인 로그에 따라 못 찾을 수도 있다
  • #13 어떤 로그를 기록해야 하는지를 판단하는 중요한 기준
  • #14 그럼 실제 디자인하는 걸 예로 들어볼게요
  • #19 큐브를 이리 돌리고 저리 돌리듯
  • #21 기왕 로그를 쌓아야 한다면 이유가 있는 로그만 쌓자는 겁니다
  • #29 기왕 로그를 쌓아야 한다면 이유가 있는 로그만 쌓자는 겁니다
  • #35 아.. 복잡하고 성능 나빠지네 ㅜㅜ