묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨350개의 개인 앱을 만들어 월급의 7배 수익을 달성한 방법
강의 들으면서 생긴 궁금한 부분들에 대해서 질문드립니다.
안녕하세요.강의 잘 들었습니다. 감사합니다.다양한 인사이트들이 들어있어서 아주 뜻깊었습니다. 듣다보니 궁금한 부분들이 여려개 생겨서 이렇게 질문드려요. 질문1. 시즌성 앱의 경우 시즌마다 같은 코드 베이스에 신규 앱을 출시하는 건가요? 아니면 기존 앱을 보강해서 업데이트를 하는건가요??질문2. 광고 배치 전략에서, 스플래시 이후 전면광고는 동영상 광고인가요??질문3. 다작의 클라이언트 환경울 구축했을 때, 주로 디자인과 데이터 부분을 묶음으로 제공하는 것 같은데, 클라 고유의 기능적인 부분은 클라 코드에서 직접 작성하시는걸까요?? 그런 세부적인것도 서버에서 컨트롤 하시나요??질문4. 소개해주신 방향성을 들었을 때, 로그인의 중요성이 덜한 앱들이 많은데, 로그인 기능도 필요하다면 도입하시나요? 도입한다면 어떤 기준으로 필요 여부를 판단하시나요??감사합니다!
-
미해결모든 개발자를 위한 HTTP 웹 기본 지식
HTTP와 HTTP API의 차이점
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요. HTTP와 HTTP API의 차이점을 잘 이해하지 못하고 있습니다 ..! HTTP는 클라이언트와 서버와 데이터를 주고 받기 위한 통신 규약이라고 이해하고 있고, HTTP API는 HTTP를 사용해서 클라이언트와 서버가 데이터를 주고 받기 위한 인터페이스로 알고 있습니다. 하지만 글로서는 이렇게 정의를 내렸는데 명확한 차이점을 잘 모르겠습니다. HTTP와 HTTP API 모두 HTTP 메서드를 사용할 수 있고,POST를 사용한다면 둘 다 메서드 바디에 데이터를 담아서 전달이 가능하고... 사용에는 차이점이 없는 것 같은데, 왜 구분을 짓는지 잘 모르겠습니다 ㅠㅠ 그리고 HTTP API에서 말하는 인터페이스란 무엇을 뜻할까요..? 자료를 더 찾아보면 HTTP는 정적 리소스를 요청하기 위함이고 HTTP API는 동적으로 데이터를 주고받기 위함이라고 합니다... HTTP, HTTP API 모두 정적, 동적 리소스를 주고 받을 수 있는게 아닌가요..?
-
해결됨3D 모델링 입문을 위한 라이노(Rhino) '꿀팁' Part.1
레고반지 수업중 질문.
레고반지 만들때양쪽으로 돌출 만들어서 SHELL 이후에 합집합 하잖아요.그 이후에는 필렛이 선택이 안되고 서피스 형태로만 선택이 되는데,제가 뭘 잘못한건지 설명이 너무 빨라서제가 왜 안되는지에 대한 피드백을 할수가 없네요.
-
미해결비전공 IT 사업 발주 및 관리 업무 담당자를 위한 필수지식
섹션2-마. 개발비용 산정 방법 질의
안녕하세요,꼭 필요했던 강의였는데 개설해주셔서 감사합니다. 잘 수강 하고 있습니다. ' 발주 비용 산출 엑셀' 관련 문의 드릴게 있습니다. 1) 기초 자료에서, 등록/목록/ 등 '화면'은 "단위 프로세스(기능)" 을 의미 하는건가요?아니면 "화면 전체" 를 의미하는건가요?- 후자라면 한개 화면에는 등록, 조회 등이 모두 있을 수 있는데이 경우는 각각 해당하는 것들을 한개 화면씩으로 카운팅 하면 될까요? 2) "DB 조회" 화면이란 어떤 것일까요?- '목록 화면' 도 DB를 조회해서 목록을 조회할 수 있을 텐데특정 수치, 계산값, 고객 정보 등의 '정보 조회' 를 의미하는걸까요? 이상입니다.감사합니다.
-
해결됨Flutter 앱 개발 기초
1회차 문법 퀴즈가 전부 동일하게 hello 출력입니다.
1회차 문법 퀴즈가 전부 동일하게 hello 출력입니다. 퀴즈 10까지 확인했는데 퀴즈도, 답도 전부 hello 10개 출력문입니다. 지난번 dartpad 의 업그레이드로 인한 한글 깨짐도 있는듯하고지식공유자님께서 한 번 검토를 부탁드리겠습니다. 너무 좋은 강의 잘 듣고 있습니다.지식 공유 감사합니다.
-
해결됨한 입 크기로 잘라먹는 타입스크립트(TypeScript)
protected 접근제어자 사용에 관한 질문
Typescript에서 접근제어자로 private, protected, public이 있다고 배웠습니다.Javascript에서는 #를 사용해서 private, public 으로 만 설정 가는한것으로 알고 있습니다.만약 타입스크립트를 사용해서 부모 클래스에서 protected로 설정한 필드를 상속받아 자식 클래스의 특정 메서드에서 사용하도록 코드를 작성한 경우,인스턴스에서 해당 메서드를 사용사고자 할때Javascript로 트랜스파일링이 되어도 문제가 없는지 궁금합니다.
-
해결됨[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
작업형 2 모의고사 3에서 평가 값이 강의내용이랑 달라요
강의 내용 그대로 코딩했는데 평가 값이 다를 수 있나요?강의에서는 xgb에서 max_depth 값을 키울수록 평가값이 커졌는데 제가 했을 땐 값을 키울수록 평가결과가 작아져서요
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 4주차] 최종 과제
노션 링크 첨부합니다.https://focapa.notion.site/4-141094a2b89980b080c6e19f8b5c4a48?pvs=4
-
미해결[유니티 레벨 업!] 모듈식으로 개발하는 스킬 시스템
Dead 애니메이션 출력 오류입니다.
현재 이렇게 되어있는 상태인데 왜인지 Dead 애니메이션만 실행이 안돼요... 코드는 그대로 복붙한 상태라 애니메이터 쪽이 문제인 것 같은데 뭐가 문제인 걸까요??
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
em.getTransaction하면
10분쯤에em.getTransaction()을 하면 자동으로EntityTransaction transaction = em.getTransaction();이게 나오는 것 같은데 저는 안 나오더라구요어떻게 저게 자동으로 나오는건가요?
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝 스터디 최종 과제] 6-1의 최종 과제
https://www.notion.so/yijin87/Foodie-4-1430181a6e9b808c9426fb5475909a23?pvs=4 노션링크로 대체합니다.
-
해결됨
find함수 사용해서 다수의 데이터 가져오기
async getAllPosts() { return this.postsRepository.find(); } post맨으로 http://localhost:3000/posts 조회 했더니[]로 안뜨고 위에 코드처럼뜹니다. 왜그러죠?
-
미해결Readable Code: 읽기 좋은 코드를 작성하는 사고법
JPA 를 사용하면 원래 객체지지향적인 설계를 가져가기 어렵나요?
오랜만에 인사드립니다 강사님. 저는 수강한 강의내용을 토대로 현재 진행하고있는 프로젝트를 리팩토링하고 있습니다. 본론으로 들어가자면, 일단 아래와 같이 특정 비지니스 로직을 검증하는 코드가 있습니다.======== BEFORE =========private void checkCrewInfoIsMatch(Long requestCrewId, Squad squad) { if (!squad.getCrew().getId().equals(requestCrewId)) { throw new SquadBusinessException.NotMatchCrewInfo(NOTMATCH_CREWINFO); } } private void checkDifferenceSquadCreator(Squad squad, CrewMember crewMember) { if (squad.getCrewMember().equals(crewMember)) { throw new SquadBusinessException.OwnerCantParticipant(OWNER_CANT_PARTICIPANT); } } 그리고 위 코드를 리팩토링하고나서 아래와 같은 코드가 나오게 되었습니다. ========== AFTER =========== private void checkCrewInfoIsMatch(Long requestCrewId, Squad squad) { if (squad.hasNotSameCrewId(requestCrewId)) { throw new SquadBusinessException.NotMatchCrewInfo(NOTMATCH_CREWINFO); } } private void checkDifferenceSquadCreator(Squad squad, CrewMember crewMember) { if (squad.isSameOwner(crewMember)) { throw new SquadBusinessException.OwnerCantParticipant(OWNER_CANT_PARTICIPANT); } } 이렇게 Getter 로 값을 꺼내 직접 값을 비교했던 (Before) 에서, 값의 비교를 객체에게 위임하는 형태인 (After) 로 리팩통해보았습니다. 하지만 값의 비교를 객체에게 위임하는 After 방식으로 리팩토링했더니, 엔티티와 연관된 다른 프록시 객체들의 초기화로 인해 불필요한 쿼리가 나가는 문제를 확인하게 되었습니다. 물론 fetchJoin 을 통해 해결하긴 했습니다. 정리하면 아래와 같습니다. 기존에는 Service Layer 에서 직접 특정 엔티티와 연관된 엔티티를 직접 Getter 로 꺼내 값을 비교했었고, N + 1 이 터지지 않았습니다. (Before) 하지만 남용된 Getter 를 개선하기 위해 값의 비교를 엔티티 내부에서 진행하는 방식으로 리팩토링했을때는 N + 1 이 터졌고, 이를 fetchJoin 으로 해결했습니다. (After) 물론 지금은 fetchJoin 으로 N + 1 문제를 해결하였지만, After 와 같은 방식으로 리팩토링을 하려면 "연관된 엔티티를 모두 fetchJoin 미리 땡겨와야하는건가? (column 들을 너무 많이 땡겨오면 성능문제 걱정)" 라는 생각이 들게되었습니다. JPA 를 사용할때, 강사님은 어떠한 방식으로 연관된 엔티티들의 값 비교를 어떤 방식으로 진행하는지 매우 궁금 합니다. 원래 JPA 를 사용하면 객체지향적인 설계를 가져가기 어려운건지도 궁금합니다. (깃헙에서 다른 사람이 한 프로젝트를 분석하다보면, 가끔 연관관계 자체를 맺지 않고, FK 를 Long 으로 가져가버리는 Case 도 본것 같은데 흠.. 나중에 질문)
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 4주차 과제] 강의 6-1의 최종 과제
노션으로 작성하여 링크 첨부합니다.https://sapphire-spade-aa6.notion.site/1435677c375480a997e3d8bf961008dd
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 3주차 과제] 리텐션 연습 문제
6주차 과제 - 1) Weekly Retention을 구하는 쿼리를 바닥부터 스스로 작성해보세요 with base as ( select distinct user_pseudo_id , event_name , date(datetime(timestamp_micros(event_timestamp),'Asia/Seoul')) AS event_date from advanced.app_logs where event_date between '2022-08-01' and '2022-11-01' ) , retention_base as ( select distinct date_trunc(event_date, week(monday)) as event_week , min(date_trunc(event_date , week(monday)) ) over(partition by user_pseudo_id order by event_date)as first_week , user_pseudo_id from base ) , middle as ( select event_week , first_week , date_diff(event_week, first_week, day) as diff , user_pseudo_id from retention_base ) , final as ( select diff , count(distinct user_pseudo_id) as user_cnt from middle group by all ) select diff , first_value(user_cnt) over(order by diff asc) as first_visit_users , user_cnt , round((user_cnt/first_value(user_cnt) over(order by diff asc)), 2) from final - 2) Retain User를 New + Current + Resurrected + Dormant User로 나누는 쿼리를 작성해보세요. --한달내 유저가 얼마나 많은 이벤트를 발생시키는지? --지속적으로 사용한다의 정의를 이벤트를 고려할 것인지 아니면 방문만 볼것인지 신규 유저(New) : 제품을 처음 사용하는 유저 --각 달에 첫 로그를 남긴 유저 기존 유저(Current) : 제품을 지속적으로 사용하는 유저 --한달내에 복귀 유저(Resurrected) : 과거에 사용 -> 비활성 -> 다시 제품을 사용한 유저 휴면 유저(Dormant) : 일정 기간 제품을 사용하지 않은 비활성화 사용자 --해당 주 이외에 - 3) 주어진 데이터에서 어떤 사람들이 리텐션이 그나마 높을까요? 찾아보세요 --함께 고민해보면 좋을 가이드라인 - 휴면 유저를 어떻게 복귀 유저로 부활시킬 수 있을까? - 어떻게 신규 유저를 계속 늘릴 수 있을까? - 기존 유저가 감소하지 않으려면 어떻게 해야할까? - 4) Core Event를 “click_payment”라고 설정하고 Weekly Retention을 구해주세요 with base as ( select distinct user_pseudo_id , event_name , date(datetime(timestamp_micros(event_timestamp),'Asia/Seoul')) AS event_date , min(date_trunc(datetime(timestamp_micros(event_timestamp),'Asia/Seoul') , week(monday)) ) over(partition by user_pseudo_id order by event_week)as first_all_week from advanced.app_logs where event_date between '2022-08-01' and '2022-11-01' ) , retention_base as ( select distinct -- extract(event_date from week) as event_week , min(date_trunc(event_date , week(monday)) ) over(partition by user_pseudo_id order by event_week)as first_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 , user_pseudo_id from base where event_name = “click_payment” ) , middle as ( select event_week , first_week , date_diff(event_week, first_week, day) as diff , user_pseudo_id from retention_base ) , weeks as ( select distinct first_week from base ) , final as ( select diff , min(first_week) as first_Week , count(distinct user_pseudo_id) as user_cnt from middle group by all ) select diff , first_value(user_cnt) over(order by diff asc) as first_visit_users , user_cnt , round((user_cnt/first_value(user_cnt) over(order by diff asc)). , 2) --safe_divide() 사용하면 좋음 from final1번 문제(15분)주차별 각 카테고리별 평균 할인율이 가장 높았던 기간과 할인율을 구하는 쿼리를 작성해주세요단, 날짜 데이터를 YYYY-MM-DD 23:59:39 이런 형태로 변경해주세요with raw as (select a.user_id , a.item_id , a.actual_price 90 , b.category , b.list_price 100 , (b.list_price-a.actual_price)/ b.list_price as discount , a.transaction_date from transaction_data a left join item_info b on a.item_id=b.item_id ) select FORMAT_TIMESTAMP('%Y-%m-%d 23:59:59', TIMESTAMP(DATE_TRUNC(DATE(transaction_date), WEEK(MONDAY)))) AS week_start_date, -- 주차의 월요일 날짜를 “YYYY-MM-DD 23:59:59” 형식으로 변환 , category , avg(discount) as avg_discount from raw group by 1,2 order 3 desc limit 1 2번 문제(10분)2024년 1월에 가장 많은 매출을 기록한 카테고리를 구하는 쿼리를 작성해주세요with raw as (select a.user_id , a.item_id , a.actual_price 90 , b.category , b.list_price 100 , (b.list_price-a.actual_price)/ b.list_price as discount , a.transaction_date from transaction_data a left join item_info b on a.item_id=b.item_id where extract(month from a.transaction_date) = 1 and extract(year from a.transaction_date) = 2024 ) select category , sum(actual_price) as gmv from raw group by 1 order gmv desc limit 1 3번 문제(10분)유저별 총 구매 금액이 200만원 이상인 유저들이 가장 많이 구매한 카테고리를 찾는 쿼리를 작성해주세요with raw as (select a.user_id , a.item_id , a.actual_price , b.category , b.list_price , a.transaction_date , sum(a.actual_price) over(partition by user_id) as user_gmv from transaction_data a left join item_info b on a.item_id=b.item_id where ) select category , count(item_id) as cnt_item , count(distinct item_id) as cnt_item , sum(actual_price) as gmv from raw where user_gmv group by 1 order 2 desc --가장많이의 정의가 구매건수라면 order 3 desc --가장많이의 정의가 유니크한 상품수라면 order 4 desc --가장많이의 정의가 gmv 매출이라면 limit 1
-
미해결[Rookiss University] UE5 Lyra 클론 코딩 (Haker)
HandleChangeInitState
HandleChangeInitState 함수로 디버깅을 진행할 떄마다, 이전에 넣었던 매개변수 중 FGameplayTag 들 모두 illegal_Name으로 받아와 인식을 못하는 오류가 있는데, 어디서부터 봐야할지 막막합니다
-
해결됨[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)
회귀분석 및 사후검정
안녕하세요 선생님,회귀분석 ols(종속변수~독립변수, data=df).fit()위 코드에서 fit()은 반드시 넣어줘야 하는 부분인가요? 머신러닝이 아닌 회귀분석을 실시할 때 학습(fit)을 시키는 것이 생소하기도 하고... R과 코드가 유사하다고 하셨는데 R에서는 fit()을 사용하지 않았던 것 같아서 조금 헷갈립니다. 챗gpt에 물어보니 fit()을 호출하지 않으면 회귀모델을 정의만 할 뿐 실제 계산이나 검정이 되지 않는다고 설명하던데.. 그럼 여기에서는 fit을 '학습'보다는 '분석'이라고 이해해도 될까요? 분산분석사후검정(투키와 본페로니)은 df_melt(데이터 재구조화)에서만 작동하나요? 아래와 같이 df['A'] 등 집단을 쭉 입력하면 안되는 것 같아서요tukey_result = pairwise_tukeyhsd(df['A'], df['B'], df['C'], df['D'], alpha=0.05)
-
미해결코딩테스트 [ ALL IN ONE ]
notion 초대 주세요
안녕하세요 강의 수강해서 보고 있는데 노션 워크스페이스 공유가 안오네요제 이메일은 wowls1227@icloud.com 입니다.
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 4주차 과제] 강의 6-1의 최종과제
https://ambiguous-serpent-eb1.notion.site/4-6-1-10208045473b80789c2ccd0823506890
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[인프런 빅쿼리 빠짝스터디 3주차] 리텐션 연습문제
1. Weekly RetentionWITH base AS ( SELECT DISTINCT DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) 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, user_id, user_pseudo_id, event_name, platform, event_params FROM advanced.app_logs ), user_visit_base AS ( SELECT user_pseudo_id, MIN(event_week) OVER (PARTITION BY user_pseudo_id) AS first_visit_week, event_week AS visit_week FROM base ), user_visit_weekdiff AS ( SELECT first_visit_week, DATE_DIFF(visit_week, first_visit_week, week) AS week_diff, COUNT(DISTINCT user_pseudo_id) AS visit_users FROM user_visit_base GROUP BY ALL ) SELECT first_visit_week, week_diff, visit_users, SAFE_DIVIDE(visit_users, FIRST_VALUE(visit_users) OVER (PARTITION BY first_visit_week ORDER BY week_diff ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) AS retention FROM user_visit_weekdiff 2. Retain User → New User, Current User, Resurrected User, Dormant User-- 한 달(30일)을 기준으로 구분하였다. -- 신규 유저: 최근 한 달 이내 새로 방문 -- 기존 유저: 최근 한 달 이내 재방문, 그 이전 한달에도 방문 -- 복귀 유저: 최근 한 달 이내 재방문, 그 이전 한달에는 방문 X -- 휴먼 유저: 최근 한 달 이내 재방문 X WITH base AS ( SELECT DISTINCT DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date, user_pseudo_id FROM advanced.app_logs ), user_first_last AS ( SELECT user_pseudo_id, MIN(event_date) AS first_date, MAX(event_date) AS last_date FROM base GROUP BY user_pseudo_id ), last_event_date AS ( SELECT MAX(event_date) AS current_date FROM base ), user_activity AS ( SELECT user_pseudo_id, event_date, LEAD(event_date) OVER (PARTITION BY user_pseudo_id ORDER BY event_date) AS next_event_date, CASE WHEN DATE_DIFF(LEAD(event_date) OVER (PARTITION BY user_pseudo_id ORDER BY event_date), event_date, DAY) > 30 THEN 1 ELSE 0 END AS dormant_history FROM base ), user_types AS ( SELECT u.user_pseudo_id, u.first_date, u.last_date, led.current_date, MAX(us.dormant_history) AS dormant_history, CASE WHEN DATE_DIFF(led.current_date, u.last_date, DAY) > 30 THEN 'dormant_user' WHEN DATE_DIFF(u.last_date, u.first_date, DAY) <= 30 THEN 'new_user' WHEN MAX(us.dormant_history) = 1 THEN 'resurrected_user' ELSE 'current_user' END AS user_type FROM user_first_last AS u CROSS JOIN last_event_date AS led LEFT JOIN user_activity AS us ON u.user_pseudo_id = us.user_pseudo_id GROUP BY u.user_pseudo_id, u.first_date, u.last_date, led.current_date ), first_week_and_diff AS ( SELECT ut.user_type, fw.user_pseudo_id, fw.event_date, DATE_DIFF(DATE_TRUNC(fw.event_date, WEEK(MONDAY)), DATE_TRUNC(ut.first_date, WEEK(MONDAY)), WEEK) AS diff_of_week FROM base AS fw JOIN user_types AS ut ON fw.user_pseudo_id = ut.user_pseudo_id ), user_cnt_by_type_and_week AS ( SELECT user_type, diff_of_week, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM first_week_and_diff GROUP BY user_type, diff_of_week ), retention_base AS ( SELECT user_type, diff_of_week, user_cnt, FIRST_VALUE(user_cnt) OVER (PARTITION BY user_type ORDER BY diff_of_week) AS first_user_cnt FROM user_cnt_by_type_and_week ) SELECT user_type, diff_of_week, ROUND(SAFE_DIVIDE(user_cnt, first_user_cnt), 2) AS retention_rate FROM retention_base ORDER BY user_type, diff_of_week 3. retention이 높은 그룹?current user: 최고 0.41 (4~5주차)new user: 최고 0.11 (1,3주차)resurrected user: 최고 0.14 (9~12주차)dormant user: 최고 0.09 (3주차)리텐션이 그나마 높은 그룹: current usercurrent user, resurrected user 리텐션 분포의 경우 상승세 → 하강세 경향성을 보여 피크를 찍을 때 즈음 어떤 이벤트가 있었다고도 추측할 수 있다. 4. click_payment 이벤트를 중점으로 본 Weekly Retention?WITH base AS ( SELECT DISTINCT DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime, event_name, user_id, user_pseudo_id FROM advanced.app_logs WHERE 1=1 AND event_name = "click_payment" ), event_week_and_first_week AS ( SELECT DISTINCT DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week, user_pseudo_id, DATE_TRUNC(MIN(event_date) OVER(PARTITION BY user_pseudo_id ORDER BY event_date), WEEK(MONDAY)) AS first_week FROM base ), retention_base AS ( SELECT *, FIRST_VALUE(user_cnt) OVER(ORDER BY day_of_week) AS total_user FROM ( SELECT DATE_DIFF(event_week, first_week, WEEK) AS day_of_week, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM event_week_and_first_week GROUP BY day_of_week ) ) SELECT day_of_week, ROUND(SAFE_DIVIDE(user_cnt, total_user), 2) AS retention FROM retention_base ORDER BY day_of_week