안녕하세요 한기용 지식공유자님. 좋은 강의 잘 듣고 있습니다. ELT를 구현할 때 SWAP 명령어를 사용한 정확한 이유가 궁금합니다. 제가 찾아본 바로는 SWAP 명령어는 포인터 교체 방식으로 '즉시' 데이터와 메타데이터가 교체되므로, 무중단 배포가 가능하다는 것이 장점인 것 같습니다. 사실, 트랜잭션을 활용해도 같은 기능을 구현할 수 있을 것 같은데 메타데이터 복제를 빠뜨리는 것을 예방하고, 트랜잭션을 활용하였을 때보다 성능이 우수하고, lock을 예방하기 때문에 SWAP 문법을 활용하는 걸까요?
카일스쿨님 매번 친절한 답변 감사드립니다 정말 많이 배웁니다!! 🙇 N day 리텐션 쿼리에 관한 질문이 3가지 있습니다. 1. 맨 처음에 base 테이블 만들 때 DISTINCT를 왜 써야하는 건지 궁금합니다. (B방법 기준) first_date_and_diff 임시테이블을 만들 때 DISTINCT를 쓰는 것은, '동일 유저가 하루에 여러번 접속한 것을 중복 제거하기 위해' 사용하는 것으로 이해했습니다. 그런데 맨 처음에 base 테이블은 timestamp 컬럼이 있는데 어떻게 중복이 있을 수 있는 건지 헷갈립니다. 완전히 동일한 마이크로초에 여러번의 행동 로그가 기록될 수 있는 건지, 아니면 전산오류로 로그가 중복 기록이 될 수 있다는 건지,, 이해가 잘 안 됩니다 😢 2. 강의에서 보여주신 결과 테이블(diff_of_day | user_cnt)은 교안 330p와 다른 것이라고 이해했는데, 제가 이해한 것이 맞는지 확인 부탁드립니다! a) 강의 결과 테이블: 유저마다 시작일은 다를 수 있지만, 어쨌든 궁금한 건 각 유저들이 첫 접속 이후에 계속 쓰는지가 궁금한 것 → 가입일 코호트별로 그룹화하지 않아도 그자체로 의미가 있음 b) 교안 330p 테이블 : 강의 결과에서 한 단계 더 나아가서, 가입일에 따라 리텐션 추이에 차이가 있는지 더 쪼개보는 것 c) 만약 교안 330p 테이블처럼 결과를 출력하고 싶으면 , COUNT 집계할 때 GROUP BY와 SELECT에 first_date만 추가로 넣어주면 된다. (아래 쿼리 및 사진 참고) -- a) 강의 결과 SELECT diff_of_day, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM first_date_and_diff GROUP BY diff_of_day ORDER BY diff_of_day -- c) 교안처럼 출력하고 싶을 경우 SELECT first_date, diff_of_day, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM first_date_and_diff GROUP BY first_date, diff_of_day ORDER BY first_date, diff_of_day 3. Weekly 리텐션 파트에서 설명해주신 WEEK 함수는 어떻게 쓰는 걸까요? 아래 쿼리처럼 썼더니 WEEK 함수가 없다고 오류가 나던데, EXTRACT를 말씀하시려던 걸까요? EXTRACT는 제대로 나오는 거 같긴 합니다..! SELECT user_pseudo_id, event_name, event_date, DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week, EXTRACT(WEEK FROM event_date) AS event_week2, WEEK(event_date) AS event_week3 FROM( SELECT DISTINCT -- event_timestamp 기반으로 중복 제거 user_id, event_name, -- event_date, -- Firebase의 형태(ex. '20220813')와 다르니까, 아래처럼 직접 추출 DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date, user_pseudo_id FROM advanced.app_logs WHERE event_date BETWEEN "2022-08-01" AND "2022-11-03") 항상 감사드립니다!! 완강까지 달려보겠습니다!
실제로 실행을 못해보는환경이라서 질문하는건데, JobLauncher를 활용한 REST API 구현 의 예제같은경우 컨트롤러 하나를 생략없이 다 표현한거같은데 jobRegistry 는 di받지않았는데 어떻게 실행하는거임? 빼먹은건가? job = jobRegistry.getJob(jobName);
질문1. 계정을 만들고 몇 가지 기능을 만들어 달라고 하니 크레디트가 종료되었습니다. 그래서 다계정을 만들어라라고 1주차에서 하셔서요. 그런데 제가 계정을 만들고 동일 프로젝트를 다시 이어서 하고 싶은데 초대를 해서 완성하려고 하는데 방법이 없더라구요. 어떻게 해야 하나요?
TransactionManager 분리 에 대해서 이해가 잘 가지 않는게 있어. 실제 운영 환경에서는 배치와 비즈니스 데이터 DB를 분리하는게 필수라고 했잖아? 근데 이 분리의 단위가 배치용 메타데이터 저장만 분리를 하는게 맞는거야? 현재 사이드 프로젝트에서 멀티모듈 구조에 (MSA는 아님) API 모듈과 배치 모듈을 따로 분리한 상태야. 유저 데이터에서 생일을 뽑아서 내일 생일인 유저에게 FCM 을 발송하는 배치를 만드는데, 이때 만들어준 예제처럼 @BatchDataSource와 비즈니스 로직용 @Primary DataSource를 분리하게 되면, API 모듈용 DB Connnection을 배치에서도 똑같이 갖다 쓰는거 아니야 ?? 즉, 배치에서 API 쪽 커넥션을 가져다 써서 배치가 돌 때 커넥션이 고갈날 수 있지 않을까? 라는 생각이 들었어 지금 이해한 바로는 @BatchDataSource, @BatchTransactionManager를 분리하고 주입해줘도 Reader -> Processor -> Writer 에는 @Primary 걸 쓰는것 같은데 맞아 ? 나는 DB 분리와 함께, 비즈니스 로직에 대한 커넥션, 트랜잭션도 배치용으로 분리하고 싶은데 이럴땐 어떻게 해야해? 특히나 배치에서도 JpaTransactionManager를 쓰고 싶은 경우에는 어떻게 해야해 ? 원하는 바는, API 처리용 DB 커넥션은 커넥션대로 있고, 배치 메타데이터용 커넥션 따로, 배치에서 라이브 DB에서 유저 데이터를 가져오는 커넥션 따로 구성하고 싶어 (배치가 API 모듈 에 영향을 주지 않았으면 해서,,,) 혹시 내가 강의를 제대로 이해를 못한거라면 알려줘
질문은 아니고 kafka 개발환경 세팅 시에 저랑 같은 문제 겪으신 분들 계시면 참고하시라고 공유 드립니다. macOS 15.6.1 버전(m4 Pro 칩)에서 도커로 kafka 컨테이너 띄울 때 아래와 같은 오류가 발생했어요. # A fatal error has been detected by the Java Runtime Environment: # # SIGILL (0x4) at pc=0x0000ffff9ad3fc5c, pid=1, tid=7 # # JRE version: (21.0.4+7) (build ) # Java VM: OpenJDK 64-Bit Server VM (21.0.4+7-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-aarch64) # Problematic frame: # j java.lang.System.registerNatives()V+0 java.base@21.0.4 https://issues.apache.org/jira/browse/KAFKA-19007 이래저래 찾아보다가 그냥 3.9.1 버전으로 받아서 띄워봤는데 잘 됐어요. 같은 문제 겪으신 분들도 그렇게 해보시기를 권해드립니다.
윈도우 함수 연습문제 6번 질문입니다. 카일스쿨님 쿼리와 다른 건 다 동일하게 작성했었는데, OVER() 안에 order by를 모르고 깜빡했었습니다. 그런데도 결과가 정답( moving_avg2 )과 같게 정상 출력이 되었습니다. (QUALIFY로 검증해봤는데 moving_avg 와 전부 같다고 나오더라구요) 원래 ORDER BY를 안 써줘도 프레임 설정이 자동으로 가능한 걸까요? ORDER BY에도 기본값 같은 게 있는지 궁금합니다. -- 윗부분은 생략 SELECT date, number_of_orders, AVG(num2) OVER(ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg, AVG(num2) OVER(ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg2 FROM filled_data -- QUALIFY moving_avg != moving_avg2 ORDER BY date
킬구형 강의 자료 중간에 이상한 문구 발견해서 제보해 강의 회차: 5장. 작전4: Flow - 배치의 흐름을 지배하라 (분기점에서 생사를 쥐락펴락하라 ☠ 🏴☠ ) 이상한 문장: 즉, Spring Batch의 암시적 전환 규칙 대상에서 제외된다는 뜻이다. 재시도 Claude는 실수를 할 수 있습니다. 응답을 반드시 다시 확인해 주세요. 강의 자료 중간에 LLM에서 가져온 내용을 잘못 편집한 것 같아.
안녕하세요. 10강에서 TaskMaster에서 복잡도를 사용하기 위해서 Perplexity API 를 입력해서 쓰셨는데, Cluade Code를 사용하면 자체 Provider를 사용하는 거 같은데 다른 이유가 있으신가요? https://github.com/eyaltoledano/claude-task-master/blob/main/docs/examples/claude-code-usage.md
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
안녕하세요! 올인원 자바와 스프링 부터로 생애 최초 서버 만들기 강좌 듣고 있는 수강생입니다. 강의 영상에 나온 것처럼 Java SE11 설치하고 IntelliJ Community Edition 설치한 후 새 프로젝트 눌렀을 때 Java SE 11 인식은 잘 하는 것 같은데, test 로 제목만 변경해서 생성했을 땐 샘플코드가 실행되지 않습니다.. 이럴 경우엔 어떻게 하면 좋을 지 궁금합니다!
실행 결과는 동일하게 나왔는데, COUNT를 다르게 쓴 것이 괜찮은지 궁금해서 질문 남깁니다! 상황 같은 날짜에 여러 번 쿼리 실행한 사용자들이 있어서 COUNT(*) 을 해야겠다고 판단했습니다. (어차피 Distinct가 없으면 같은 날짜라도 각각 카운트한다는 것을 깜빡했었습니다ㅠ) 카일스쿨님은 COUNT(query_date) 를 쓰셨고, 결과만 보면 제 쿼리와 동일하긴 합니다. 궁금한 점 제 쿼리처럼 COUNT(*)을 쓰는 경우에 문제가 될까요? 혹시 실무적으로 COUNT(*)은 잘 쓰지 않는지 궁금합니다! (Ex. 어떤 컬럼의 개수를 세는 것인지 가독성이 좋지 않다든가..) 제 쿼리는 아래와 같습니다. SELECT *, COUNT(*) OVER(PARTITION BY user) AS total_query_cnt FROM advanced.query_logs ORDER BY query_date, user
안녕하세요 코틀린으로 현재 강의를 수강하고 있는 수강생입니다. 현재 자바로 작성된 코드를 보고 설명과 함께 어떤 이유로 이런 코드를 작성한 것인지 생각하며, 코틀린으로 이 개념을 적용하면 어떻게 작성할 수 있을지 DDD와 클린 아키텍처를 코틀린 문법 활용하여 구상하는 연습 중입니다. 현재 Member 도메인 코드 개선 강의에서 value class 적용하여 필드의 값이 바뀌는 문제(email자리에 nickname이 오더라도 같은 String이라 컴파일 에러가 안 남)를 해결하려 시도했습니다 package org.example.splearn.domain @JvmInline value class Email( val value: String, ) @JvmInline value class Nickname( val value: String, ) @JvmInline value class PasswordHash( val value: String, ) class Member private constructor( val email: Email, var nickname: Nickname, var passwordHash: PasswordHash, var status: MemberStatus, ) { fun activate() { check(status == MemberStatus.PENDING) { "회원이 PENDING 상태가 아닙니다" } this.status = MemberStatus.ACTIVATE } fun deactivate() { check(status == MemberStatus.ACTIVATE) { "회원이 ACTIVE 상태가 아닙니다" } this.status = MemberStatus.DEACTIVATED } fun verifyPassword( password: String, passwordEncoder: PasswordEncoder, ): Boolean = passwordEncoder.matches(password, this.passwordHash.value) fun changeNickname(nickname: String) { this.nickname = Nickname(nickname) } fun changePassword( password: String, passwordEncoder: PasswordEncoder, ) { this.passwordHash = PasswordHash(passwordEncoder.encode(password)) } fun isActive(): Boolean = this.status == MemberStatus.ACTIVATE companion object { fun create( memberCreateRequest: MemberCreateRequest, passwordEncoder: PasswordEncoder, ): Member = Member( email = memberCreateRequest.email, nickname = memberCreateRequest.nickname, passwordHash = PasswordHash( passwordEncoder.encode(memberCreateRequest.password.value), ), status = MemberStatus.PENDING, ) } } 강의대에서는 static 메소드인 of에서 MemberCreateRequest를 파라미터로 사옹하고 있습니다. 코틀린이라 companion object를 사용했구요 그러던 중 "헥사고날 아키텍처의 특성을 고려하면 의존성 외부 로직인 dto가 내부로 향해야 하고 따라서 도메인이 dto에 의존하는 것이 괜찮을까" 하는 의문이 들었습니다. companion object { fun create( email: Email, nickname: Nickname, password: String, passwordEncoder: PasswordEncoder, ): Member = Member( email = email, nickname = nickname, passwordHash = PasswordHash( passwordEncoder.encode(password), ), status = MemberStatus.PENDING, ) } 그래서 코드를 수정해 보면 이런 식으로 수정해 볼 수 있을 것 같습니다. 이에 대해서 토비님 의견이 어떠신지 여쭙고 싶습니다
다른 강의들이나 교재들 보면 prior 자식 = 부모 는 순방향 이라고 설명해 주시는데 이 강의에서만 역방향이라고 설명해 주시네요. 특히 노랭이 63번도 정답이 4번인 이유가 "connect by 절에만 사용 가능하다" 이 부분이 틀렸기 때문이라고 나오는데.. 보충 설명이 가능하실까요?