[빠짝스터디] 3주차 과제 - 리텐션
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
노션으로 과제 진행하여 링크 복사합니다!! 웹 게시로 수정했습니다 :) https://jypack788.notion.site/3-14-888ecbcf244f42dc9a4e5640fe0fa8dd
- sql
- Google-Analytics
- firebase
- google-sheets
- bigquery
172만명의 커뮤니티!! 함께 토론해봐요.
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
노션으로 과제 진행하여 링크 복사합니다!! 웹 게시로 수정했습니다 :) https://jypack788.notion.site/3-14-888ecbcf244f42dc9a4e5640fe0fa8dd
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
노션 링크 : https://www.notion.so/3-13a3dc9851a680cda683e39c64a8dc91?pvs=4
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
# RandomForestRegressor from sklearn.ensemble import RandomForestRegressor model = RandomForestRegressor() model.fit(X_tr, y_tr) pred = model.predict(X_val) rmse(y_val, pred) 머신러닝 회귀 모델에서 스케일링 해둔걸 주석처리하고 이전 셀 실행 후 위 코드를 실행해서 베이스라인 값을 체크하려는데, 강의와 다른 값이 나와서 한번 더 실행했더니 값이 또 바뀌는데 원인이 뭘까요? 이후에도 계속 실행할수록 값이 매번 바뀝니다!
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
여러 검정들마다 alternative를 어떤것은 붙이고, 어떤것은 안붙이는 것이 헷갈립니다. 기억을 쉽게 하는 방법이 있을까요
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
1번 with base as ( select user_pseudo_id, DATE_TRUNC(MIN(event_date) OVER (PARTITION BY user_pseudo_id), WEEK(MONDAY)) as event_first_week, DATE_TRUNC(event_date,WEEK(monday)) as event_week, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') as event_time from advanced.app_logs ) , diff_date_tbl as ( select user_pseudo_id, event_first_week, event_week, DATE_DIFF(event_week, event_first_week, WEEK) as diff_date from base order by diff_date ) , user_counts as ( select event_first_week, diff_date, count(distinct user_pseudo_id) as user_count from diff_date_tbl group by all order by diff_date ) select * , ROUND(SAFE_DIVIDE(user_count, first_user_count), 2) as retention_rate from ( select * , FIRST_VALUE(user_count) OVER (PARTITION BY event_first_week ORDER BY diff_date) as first_user_count from user_counts ) 2번 with base as ( select user_pseudo_id, MIN(event_date) OVER (PARTITION BY user_pseudo_id) as event_first_day, event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') as event_time from advanced.app_logs ) , period as ( select user_pseudo_id, event_date, LAG(event_date) OVER (PARTITION BY user_pseudo_id ORDER BY event_date) as before_event_date from base GROUP BY ALL ORDER BY user_pseudo_id ) -- 평균주기 구하기 SELECT AVG(diff_day) as avg_diff_period FROM ( select *, DATE_DIFF(event_date, before_event_date, DAY ) as diff_day from period ) -- 접속 주기 분포도 확인 SELECT diff_day, COUNT(distinct user_pseudo_id) as user_count FROM ( select *, DATE_DIFF(event_date, before_event_date, DAY ) as diff_day from period ) GROUP BY ALL ORDER BY diff_day 1) new 유저 = (최근월 - 1)월 = 첫접속일자(event_first_month) 2) current 유저 = (최근월 -1)월 , (최근월 -2)월 모두 활동 o 3) dormant 유저 = (최근월 - 1)월 , (최근월 -2)월 모두 활동 x 4) resurrected 유저 = (최근월 -2)월 활동 x, (최근월 -1)월 에는 활동 with base as ( select user_pseudo_id, event_date, DATE_TRUNC(event_date, MONTH) as event_month from advanced.app_logs order by 1 ) , min_max_month as ( SELECT *, MIN(event_month) over (partition by user_pseudo_id order by event_month) as first_month, MAX(DATE_TRUNC(event_date, MONTH)) OVER () as lastest_month from base ) , filter_month as ( SELECT user_pseudo_id, first_month, lastest_month, COUNT(CASE WHEN event_month = DATE_SUB(lastest_month, INTERVAL 1 MONTH) THEN 1 END) AS previous_1_lastest_month, COUNT(CASE WHEN event_month = DATE_SUB(lastest_month, INTERVAL 2 MONTH) THEN 1 END) AS previous_2_lastest_month FROM min_max_month group by ALL ) , user_classification as ( SELECT *, CASE WHEN first_month = DATE_SUB(lastest_month, INTERVAL 1 MONTH ) THEN 'New' WHEN previous_1_lastest_month > 0 and previous_2_lastest_month >= 0 THEN 'Current' WHEN previous_1_lastest_month = 0 and previous_2_lastest_month = 0 THEN 'Dormant' WHEN previous_1_lastest_month = 0 and previous_2_lastest_month > 0 THEN 'Resurrected' ELSE 'Others' END AS user_category FROM filter_month ) select user_category, count(distinct user_pseudo_id) from user_classification group by all 4번 WITH base AS ( SELECT user_pseudo_id , first_value(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul')) over(partition by user_pseudo_id order by event_timestamp) as first_visit , last_value(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul')) over(partition by user_pseudo_id order by event_timestamp) as last_visit , datetime(timestamp_micros(event_timestamp), 'Asia/Seoul') as event_datetime , date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), day) as event_date , date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), week(monday)) as event_week , date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), month) as event_month , event_name FROM advanced.app_logs ), click_payment AS ( SELECT DISTINCT user_pseudo_id , min(event_week) over(partition by user_pseudo_id) as first_week , event_week as week_date FROM base WHERE event_name = 'click_payment' ), diff_week AS ( SELECT first_week, date_diff(week_date, first_week, week) as week_diff, count(distinct user_pseudo_id) as users_cnt FROM click_payment GROUP BY ALL ) SELECT first_week , week_diff , users_cnt , safe_divide(users_cnt, first_value(users_cnt) over(partition by first_week order by week_diff)) as retention_rate FROM diff_week order by 1, 2 ;
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
노션 링크로 과제 업로드 합니다. 과제 풀이 노션 링크 : [인프런 빅쿼리 빠짝스터디 3주차] 리텐션 분석
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
과제풀이를 노션에 하여서 노션링크 업로드 하여 제출합니다 노션링크: https://canyon-king-6a2.notion.site/3-13ce4e3151278004b5abe5e38e5268b8?pvs=4
해결됨
2주만에 통과하는 알고리즘 코딩테스트 (2024년)
for x in range ( 1 , k + 1 ): # 가방 무게가 x일 때 # 물건을 담을 수 있을 때 (x보다 무게가 작거나 같을 때) if x < weight : dp [ y ][ x ] = dp [ y - 1 ][ x ] # 물건을 담을 수 없을 때 ( 전에 넣어뒀던 무게로 유지) else: dp [ y ][ x ] = max ( dp [ y - 1 ][ x ], dp [ y - 1 ][ x - weight ] + value ) 이렇게 나와있는데, x < weight이면 물건을 못담을때 아닌가요??
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
df['f3'] = df['f3'].replace(np.nan, '0').replace('silver', '1').replace('gold', '2').replace('vip', '3') print(df['f3'].sum()) 이렇게 코드 작성 시, 202003010232022222222222221220231112102221022220222223101200121202012002200221032202021220121202라고 값이 뜨는데, 정수로 바꾼 다음에 합을 구할 때는 어떻게 하나요?
미해결
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
적어주신 링크 적어서 들어가면 오류가 뜨는데 왜이러는걸까요ㅠㅠ
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
이것은 수강 안해도 되는건지요?
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
데이터 전처리 전 타켓변수를 만들때 마다 오류메세지가 뜹니다. 그리고 train의 'id' 를 삭제할 때에도 비슷한 오류가 뜨는데 도와주세 요
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
과제 풀이를 노션에 작성하여, 노션 링크 업로드 합니다. 과제 풀이 노션 링크 : https://sapphire-lotus-719.notion.site/3-1-3-13571425e28d8056afe1c68dd7efaa6e?pvs=4
해결됨
직장인에게 꼭 필요한 파이썬-아래아한글 자동화 레시피
2-4. [응용] 엑셀문서 값을 필드에 입력하기 관련입니다. # 1. 함수 정의 def 필드삽입(index, value): # 2. 필드 목록 만들기 field_list = ["이름", "성별", "생일", "취미"] # 3. 반복문으로 필드에 데이터 넣기 for idx, field in enumerate(field_list): # 4. 한글 문서에 데이터 입력하기 hwp.PutFieldText(f"{field}{{{{{index}}}}}", value[idx]) 위의 코드에서 바로 이 부분.. hwp.PutFieldText(f"{field}{{{{{index}}}}}", value[idx]) 그중에서도 아래의 구문이 이해하기 어려웠습니다. f"{field}{{{{{index}}}}}" 이에 대하여 제가 최대한 이해하려고 풀어 써 본 것은 아래와 같습니다. ※ 아래는 엑셀(취미.xlsx)의 캡처 f"{field}{{{{{index}}}}}": 위 줄은 한글 문서 안에 있는 특정 필드를 가리키는 주소를 의미함. 예를 들어, 엑셀(취미.xlsx)의 첫 행인 2행의 이름 값을 넣고 싶다면, 한글 문서에서는 그 자리가 "이름{{0}}"에 해당할 것임. 또한, 엑셀의 3행의 이름 값을 넣을 자리라면 "이름{{1}}"이 될 것임. 그래서 f"{field}{{{{{index}}}}}"는, 여기서 field가 "이름", "성별", "생일", "취미" 중 하나이고, index는 몇 번째 데이터인지를 나타내는 숫자임. 예를 들어, 첫 행인 2행의 이름이면 "이름{{0}}", 두 번째 행인 3행의 생일이면 "생일{{1}}" 이런 식으로 만들어야 함. 그런데 여기서 왜 중괄호가 5쌍이나 있는 것인지 궁금했음. --- {{{{{index}}}}} 에 중괄호가 무려 5쌍 있음! f"{field}{{{{{index}}}}}"에서, {{ }} <----- 실제로 보여질 중괄호 { } 를 출력하기 위함 ..... ① {{ }} <----- 실제로 보여질 중괄호 { } 를 출력하기 위함 ..... ② {index} <----- 'index'라는 변수의 값 넣기 위한 부분임. 위의 ①, ②의 부분의 중첩 즉 총 4쌍의 중괄호에 의해 {{ }} 형태의 문자열이 만들어짐. 결과적으로 field = 이름이고 index = 0 이라면, f"{field}{{{{{index}}}}}" 코드는 "이름{{0}}" 이라는 문자열을 만들어 냄. "이름{{0}}" 이라는 형태의 문자열을 만들어 내야, 이것을 이용해서 한글 문서에 hwp.PutFieldText("이름{{0}}", value[idx]) 라는 식으로 작동되어 원하는 값을 입력할 수 있는 상태가 되기 때문임. 제가 이해한 내용이 맞을까요? 중괄호도 많고 복잡해서 이해하기 어려웠는데, 저와 같은 형태로 되어야 하는 이유를 추정해 보았습니다. 답변 부탁드립니다. 감사합니다. 근데 문외한의 입장에서는 이런 거 한 줄 이해하기가 원래 이렇게 어렵게 느껴지는 게 정상인가요? ㅜㅠ
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
안녕하세요 선생님 작업형 2유형 관련해서 질문이 있습니다. 2유형에서 고득점을 목표로 하지 않기 때문에 간단하게 기본 공식만 외워가려고 생각중인데요 target = train.pop("A") train = pd.get_dummies(train) test = pd.get_dummies(test) from sklearn.model_selection import train_test_split X_tr,X_val,y_tr,y_val = train_test_split(train,target,test_size = 0.2, random_state = 0) from sklearn.ensemble import RandomForestRegressor rf = RandomForestRegressor(random_state=0) rf.fit (X_tr,y_tr) pred = rf.predict(X_yal) pred = rf.predict(test) result = pd.DataFrame({'pred':pred}) result.to _csv("result.csv",index=False) print( pd.read _csv("result.csv").head()) print( pd.read _csv("result.csv").shape) 이런식으로 간단하게 문제에 맞춰 작성했을때 빨간색 하이라이트 부분을 제출을 하는건데 , 초록색 부분을 주석처리를 해줘야 하는걸까요? 아니면 주석처리 하지 않고 위에처럼 제출을 하면 될까요? 추가적으로 주석처리가 필요한 부분이 있으면 알려주십쇼!!
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
모델링 및 평가(분류) 강의에서 X_train 데이터의 15개의 칼럼 데이터 중 일부 수치 데이터만 활용하여 머신러닝에 사용하는데, 모든 데이터를 다 활용하지 않는 이유가 있을까요? 만약 모든 데이터를 다 활용한다면 roc_auc_score의 변화는 어떻게 되나요?
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
피처 엔지니어링 강의 중 분리한 데이터 다시 합침 부분에서 강의영상과 출력값이 달라서 질문드립니다. 강의화면에서는 107 컬럼, 103컬럼인데요, 같은 코드 결과인데 컬럼수가 15개로 나온이유가 궁금합니다.
해결됨
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
범주형 변수에 get.dummies를 이용하여 원핫인코딩 하는 작업 중 질문이 있습니다. train 데이터셋과 test 데이터셋의 컬럼수가 99개와 95개로 다릅니다. (다른 이유는 train 데이터셋과 test 데이터셋의 컬럼 중에 관측치가 다른 항목이 있기 때문이라고 하셨는데요, 그런 이유라면 다른 것이 정상인가요?) 그런데 영상에서는 100개로 나옵니다,, 강의 100개 vs 99개 컬럼 갯수가 다른 이유는 무엇일까요? 아래는 코드와 출력값 첨부드립니다. # 원핫 인코딩 n_train, n_test, c_train, c_test = get_nc_data() # 데이터 새로 불러오기 c_train = pd.get_dummies(c_train[cols]) c_test = pd.get_dummies(c_test[cols]) display(c_train.head()) display(c_test.head()) print(c_train.shape) print(c_test.shape)
미해결
[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! 질문과 관련된 영상 위치를 알려주면 더 빠르게 답변할 수 있어요 먼저 유사한 질문이 있었는지 검색해보세요
미해결
BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
✅ 연습문제 (1) weekly retention --1) weekly retention WITH base AS ( -- 날짜 데이터 전처리 -- DATE도 실제 날짜와 일치하지 않을 수 있으니, 다시 확인하기 -- DATETIME(TIMESTAMP_MICROS(timestamp데이터),'대륙/국가') 기억하고 사용하기 SELECT DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul') AS event_datetime, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul')) AS event_date, event_name, user_pseudo_id FROM `bigquery-432401.avdanced.app_logs_temp` ) -- 일자 간 차이 구하기 , cal_week AS ( SELECT DISTINCT user_pseudo_id, -- 최초일(week 단위로) 구하기 DATE_TRUNC(MIN(event_date) OVER(PARTITION BY user_pseudo_id), WEEK(MONDAY)) AS first_week, -- 원본 날짜 데이터에서 주차 데이터로 구하기 DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week FROM base ), cal_diff AS ( -- 주차데이터간 차이 구하기 SELECT *, DATE_DIFF(event_week, first_week,WEEK) AS diff_week FROM cal_week ), user_count AS ( -- 주차별 user 수 구하기 SELECT diff_week, COUNT(distinct user_pseudo_id) as user_cnt FROM cal_diff GROUP BY diff_week ) -- 출력 SELECT *, ROUND(SAFE_DIVIDE(user_cnt, first_week_user_cnt),2) AS retention_rate FROM ( SELECT diff_week, user_cnt, FIRST_VALUE(user_cnt) OVER(ORDER BY diff_week) AS first_week_user_cnt FROM user_count ) 아직 익숙하지 않아서 중간중간 다시 코드 보고 작성했다. 점점 더 익숙해지길! (2) Retain User WITH base AS ( -- 날짜 데이터 전처리 -- DATE도 실제 날짜와 일치하지 않을 수 있으니, 다시 확인하기 -- DATETIME(TIMESTAMP_MICROS(timestamp데이터),'대륙/국가') 기억하고 사용하기 SELECT DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul') AS event_datetime, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul')) AS event_date, event_name, user_pseudo_id FROM `bigquery-432401.avdanced.app_logs_temp` WHERE event_date BETWEEN "2022-08-01" AND "2022-11-03" ) , cal_diff AS ( -- 날짜데이터 간 차이 구하기 SELECT *, DATE_DIFF("2022-11-03", event_date,DAY) AS diff_date FROM base ), user_type AS ( -- user type 구하기 -- 0. 해당없음 -- 1. new : 첫번째 접속 --2. current : 최근 30일내에 접속 -- 3. resurrected : 30일 이상 활동이 없고, 최근 7일 이내 다시 접속한 사용자 -- 4. dormant : 최근 60일 간 접속기록 없음 SELECT *, CASE -- 첫 번째 접속 => 'new' WHEN diff_date = FIRST_VALUE(diff_date) OVER(PARTITION BY user_pseudo_id ORDER BY event_date) THEN 'new' -- 최근 30일 내에 접속한 사용자 => 'current' WHEN diff_date <= 30 THEN 'current' -- 30일 이상 활동이 없고, 최근 7일 이내 다시 접속한 사용자 => 'resurrected' WHEN diff_date > 30 AND diff_date <= 37 THEN 'resurrected' -- 60일 이상 접속하지 않은 사용자 => 'dormant' WHEN diff_date > 60 THEN 'dormant' ELSE 'none' END AS type FROM cal_diff GROUP BY all ORDER BY user_pseudo_id,diff_date ) SELECT * FROM user_type 나름 user를 나눈다고 나눴는데, 잘 못 나눠진 느낌이 든다! 현업에는 어떻게 나눌지 궁금하다 (3) 어떤 user가 많은가? WITH base AS ( -- 날짜 데이터 전처리 SELECT DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul') AS event_datetime, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp),'Asia/Seoul')) AS event_date, event_name, user_pseudo_id FROM `bigquery-432401.avdanced.app_logs_temp` WHERE event_date BETWEEN "2022-08-01" AND "2022-11-03" ), cal_diff AS ( -- 날짜데이터 간 차이 구하기 SELECT *, DATE_DIFF("2022-11-03", event_date, DAY) AS diff_date FROM base ), user_type AS ( -- user type 구하기 SELECT distinct user_pseudo_id, CASE WHEN diff_date = FIRST_VALUE(diff_date) OVER(PARTITION BY user_pseudo_id ORDER BY event_date) THEN 'new' WHEN diff_date <= 30 THEN 'current' WHEN diff_date > 30 AND diff_date <= 37 THEN 'resurrected' WHEN diff_date > 60 THEN 'dormant' ELSE 'none' END AS type FROM cal_diff ), cal_cnt AS ( -- 각 type별 사용자 수 계산 SELECT type, COUNT(user_pseudo_id) AS user_cnt FROM user_type GROUP BY type ) SELECT type, user_cnt, ROUND(user_cnt * 100.0 / (SELECT COUNT(*) FROM user_type), 2) AS ratio FROM cal_cnt ORDER BY ratio DESC new인 사용자가 69.87 %로 전체의 대다수를 차지한다. 그다음이 최근에 7일 내에 접속한 유저가 21.83%, resurrected : 30일 이상 활동이 없고, 최근 7일 이내 다시 접속한 사용자가 2.59%, 최근 60일 간 접속기록 없는 사용자가 1.25%를 차지하였다. 2022-11-03일 기준 "2022-08-01" 에서 "2022-11-03" 기간 동안 서비스를 이용하는 대다수의 사람들은 신규 가입자들이 많다는 것을 알 수 있다. 또한, current User가 많은 것으로 보아, 최근 7일이내에 서비스를 사용한 사람들의 비율이 두번째로 높다. 현재 신규이용자의 수가 대다수를 차지함으로 이 신규 사용자를 current user로 전환하기 위한 전략을 고안해야 할 것으로 보인다. none이 resurrected, dormant보다 많은데, type을 나누는 기준을 수정하면 더 효율적이게 나눌 수 있지 않을까 생각된다. (4) core event를 click_payment로 놓았을 때 Weekly retention WITH base AS ( SELECT event_name, user_pseudo_id, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_time FROM `bigquery-432401.avdanced.app_logs_temp` WHERE event_name = "click_payment" ), week_diff AS ( SELECT *, DATE_DIFF(event_week, first_week, WEEK) AS diff FROM ( SELECT DISTINCT user_pseudo_id, DATE_TRUNC(MIN(event_date) OVER(PARTITION BY user_pseudo_id), WEEK(MONDAY)) AS first_week, DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week FROM base ) ), user_counts AS ( SELECT diff, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM week_diff GROUP BY diff ) SELECT *, ROUND(SAFE_DIVIDE(user_cnt, first_week_user_cnt), 2) AS retention_rate FROM ( SELECT diff, user_cnt, FIRST_VALUE(user_cnt) OVER(ORDER BY diff ASC) AS first_week_user_cnt FROM user_counts ) 1주차 이후로 사용자의 수가 급감. 2주차 부터는 계속 0.01을 유지. 15주차부터 24주차까지는 0 retention rate를 유지. 사용자가 1주차 이후로 대거 이탈함을 볼 수 있음. 15주차부터 0.01에서 0.0으로 감소. 1주차에 이벤트 혹은 서비스 런칭으로 사용자수가 급격히 증가하였으나, 서비스 경험이 사용자에게 매력적으로 다가오지 못하여 바로 그 다음주부터 급격하게 감소하는 것을 볼 수 있음. 따라서, core_event에 대한 근본적인 개선이 필요할 것으로 보임. ✅ 배운점 및 느낀점 리텐션 분석에 대한 전반적인 지식을 얻을 수 있었다. 아직, 데이터에서 리텐션 분석을 하는 것이 익숙치 않아 학습을 더 해야 할 것 같다. user type을 나누는 부분에서 더 짜임새 있는? 기준이 뭔지, 현업에서는 어떤 기준으로 사용자를 나누는지 궁금하다! 고객을 분석하기 위해서는 어떤 부분을 더 봐야하는 지 아직 크게 감이 없는데, 다른 레퍼런스를 보는 것이 필요할 것 같다는 생각이 들었다