이번에 설계 1편에서 자연 키와 대리 키 부분을 학습하면서, 최근 구글이 이메일 변경을 부분적으로 검토하고 있다는 뉴스가 떠올랐습니다. 예전에는 이메일 변경이 거의 불가능했던 이유가 이메일을 자연 키처럼 사용해왔기 때문이라고 이해해도 될까요? 그리고 지금에 와서는 어떤 구조적 변화나 트레이드오프를 통해 이메일 변경이 가능해졌는지도 궁금합니다.
김영한의 실전 데이터베이스 입문 - 모든 IT인을 위한 SQL 첫걸음(SQL부터 차근차근)
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] insert into 할때 괄호로 열을 지정하지않고 생략한다면 table을 생성할때 작성한 열 순서대로만 넣어야하는건가요?? 강의에 열의 순서라는게 그걸 뜻하는게 궁금해요
안녕하세요. 좋은 강의 감사합니다. 강의와 직접적으로 관련 있는 내용은 아니지만 궁금한 점이 있어 질문드립니다. 클라이언트에서 MySQL 서버로 아래와 같이 요청할 텐데 BEGIN 쿼리 COMMIT 3번에서 MySQL 서버가 클라이언트의 Commit 요청을 받고 처리 완료 후, 클라이언트에게 응답하려는 순간 네트워크가 단절되면 Commit은 되었지만 클라이언트는 실패로 인지할 텐데 이런 경우 어떻게 대응해야 하는지 궁금합니다. 아니면 MySQL 서버에 네트워크 전송 실패를 감지하고 해당 트랜잭션을 보정하는 동작이 있을까요? 감사합니다.
SELECT u.name AS user_name, SUM(o.quantity * p.price) AS total_purchase_amount FROM orders o JOIN users u ON o.user_id = u.user_id JOIN products p ON o.product_id = p.product_id GROUP BY u.name ORDER BY total_purchase_amount DESC; 이구문에서 GROUP BY를 user_id로 묶는게 더 안전하지 않나 생각이 들어서 질문드립니다. name은 동명이인이 있다면 문제가 되지 않을까 궁금합니다 선생님 혹시 name으로 GROUP BY를 사용해야하는 이유가 있는지 궁금합니다!
안녕하세요 제미니님 유튜브랑 인프런 강의 잘 듣고 있습니다. 항상 감사합니다. 😃 다름이 아니라 강의를 보고 사이드 프로젝트를 해보고 있는데, 도메인과 엔티티를 분리해서 엔티티는 단순 DB 매핑용으로만 쓰고 모든 비즈니스 로직을 도메인에서 처리해보려 하고 있습니다. 그러다 보니 '수정'같은 경우(예를 들면 state를 예약에서 취소로 변경하는)에는 id로 엔티티를 찾고 도메인으로 매핑해서 도메인 내부에서 검증과 로직을 처리해야 하는데, 매핑하는 과정에서 수정하는 데 불필요한 List<같은 격벽 하위 도메인> 들도 다 조회를 해서 세팅을 해줘야 하더라구요. 1 : N 관계라 쿼리도 많이 나가게 되고 수정에 불필요한 필드들을 세팅하는 거라서 비효율적이라 생각해서 개선을 해보려 합니다. 강의 예제 코드에서는 단순 update는 entity 에서 처리하는 것 같던데, 저는 도메인과 엔티티 계층을 엄격히 분리해서 service 내에서 entity를 의존하는 것이 불가능한 상황입니다. 또한 비즈니스 로직도 엔티티가 아닌 도메인 내부에 놓고 싶습니다. 수정에 필요한 필드만 가지고 있는 수정용 도메인을 만들어서 처리할까 생각도 해보았는데, 비즈니스 로직이 흩어지는 것도 이상하고, 얕은 지식이지만 애그리거트 루트에서 데이터 변경이 이루어져야 한다는 생각이 있습니다. 그렇다고 도메인 내부의 하위 도메인 리스트를 nullable하게 가자니 제미니님이 OrderSummary 관련 강의 때 말씀하신 null을 허용하는 도메인을 웬만해서는 선호하지 않는다에 공감이 가서 고려를 안하고 있습니다. 조언을 주시면 정말 감사하겠습니다 ㅜ.ㅜ 😢
안녕하세요, 강의랑 유튜브 너무 잘 보고있습니다. 강의를 보면서 여러 인사이트를 얻었습니다! 궁금한 점은 코틀린이 아닌 자바를 사용할 경우엔 엔티티 객체를 도메인 객체로 변환해서 return 해줄 때 코드가 다소 지저분해지는데요 ㅠㅠ 어떤 방식이 가장 유효할지 의견 부탁드립니다! 엔티티 객체에 toDomain() 과 같은 도메인 객체 변환 메서드 생성 Mapper 클래스 생성 (ex. ProductMapper.toDomain(entity)) (생성 한다면 어느 모듈, 위치에..?) 추가적으로 도메인 객체를 사용한다면, 엔티티 -> 도메인 -> 클라이언트 응답 DTO 와 같은 변환 과정을 거의 필수적으로 거쳐가야하는데, 이 부분에 대해서 도메인 객체와 엔티티 객체의 분리 시점이 재미니님은 있으신건가요? 아니면 프로젝트 시작부터 도메인과 엔티티는 구분해서 사용할 것이다! 라고 정하고 시작하시는 편이신가요? 물론 프로젝트의 규모와 도메인의 복잡도 등에 따라 유연하게 변해야 한다고 생각하지만, 해당 경험이 없다시피 하다보니 현재 프로젝트 구조에서 구현 레이어 밖으로 나갈때 도메인 객체로 변환의 이점과 트레이드 오프에 대해 어떻게 생각하시는지 궁금합니다!
안녕하세요 강사님 덕분에 강의 잘 듣고 있습니다 table full scan과 index_ffs 성능 비교 시 index_ffs 가 크기가 작아서 무조건 더 빠를 것이라고 생각했는데요 table full scan 시 direct i/o가 발생하여 index_ffs 보다 더 빠른 경우도 생길 수 있는건가요?
상품 목록 조회가 복잡해질 때의 상황을 생각해보고 있는데요. 감이 오지 않는 부분들이 몇가지 있어 질문드립니다. 상품 목록 조회 시 옵션 개념이 있다면 재고는 어떻게 처리해야 할까요? 재고는 상품옵션들의 조합이 가지고 있는 것이 이상적일 것 같은데, 상품 목록 조회던, 상세 조회던 품절 여부와 최대 구매가능 수량을 나타내기 위해서는 재고 정보도 필요해보입니다. 따라서 Product 필드에 해당 상품의 전체재고수량(모든 조합의 실재고 합)을 필드로 가지고 있는게 맞나? 라는 생각이 들고... 필드로 가지고 있다면 상품 조회 시 조합을 전부 조회하고 매번 합해 주어야 하나? 그럼 Product 테이블 컬럼단에 미리 합한 값을 넣어두어야 하나? 여러 생각이 듭니다. 다음으로는 프로모션(타임세일) 적용가, 쿠폰적용가 등으로 보여줘야 한다면 이게 실질적으로 Product 도메인 객체의 가격을 변경해도 되는 건가? 라는 생각도 했습니다.프로모션(타임세일) 적용가, 쿠폰적용가 등으로 보여줘야 한다면 쿠폰적용가, 타임세일 적용가 등이 처음에는 보여주기만을 위한 정보이지 않을까 생각했는데, 실제 주문할 때 반영될 금액이기도 하고, 타임세일 같은 경우는 대부분 모두에게 적용되어 보이는 형태이기에... 뷰의 목적이 아니라 개념적으로 봐도 되는걸까? 라는 생각이 듭니다. 조금 고도화 하여 생각해보니 감이 잡히지 않는 부분들이 너무 많네요,,, 실무에서는 주로 어떤 구조를 추구하는지 제미니님은 어떻게 생각하시는지 궁금합니다. 긴 글 읽어주셔셔 감사드려요!
1분30초 ~ 2분 쯤에 말씀해 주시기를 "부하를 100만건을 받는 가상 환경에서", "카프카가 100% 이득인 상황은 언제지?" 등의 긍정적인 예시를 들어주셨습니다. 하지만 면접관의 입장에서 "왜 부하를 100만건 받는 가상 환경을 만드셨나요?" "실제 트래픽이 얼마정도 였길래 100만 건의 부하 테스트를 하신건가요?", "현실적인 목표에 부합하는 부하 테스트를 하신 게 맞을까요?" 등의 질문을 할 수 있지 않나요? 그럼 결국에 "학습 목적으로 사용한 kafka = 학습 목적으로 구성한 100만건의 부하 환경"이 된다고 생각합니다. 즉 100만건의 부하를 받는 가상 환경을 만든 당위성이 없다고 생각합니다. 그럼 결국 당위성이 만들어지기 위해서는 꽤 많은 유저 트래픽을 받고 있는 사이드 프로젝트를 만들어야 하지 않나 생각이 들어서 질문드립니다.
강의 내용에 실습 영역을 따라 스크립트를 작성하였는데 데이터베이스가 보여지지 않습니다. 맥, 윈도우 모두 동일한 상태라 별도로 db를 다운받아 워크벤치 넣어야되는 것인지 문의 드립니다. - 강의 영상에 대한 질문이 있으시면, 상세히 문의를 작성해주시면, 주말/휴일 제외, 2~3일 내에 답변드립니다 (이외의 문의는 평생 강의이므로 양해를 부탁드립니다.) - 강의 답변이 도움이 안되셨다면, dream@fun-coding.org 로 메일 주시면 24시간 내에 재검토하겠습니다. - 괜찮으시면 질문전에 챗GPT 와 구글 검색을 꼭 활용해보세요~ - 잠깐! 인프런 서비스 운영(다운로드 방법포함) 관련 문의는 1:1 문의하기를 이용해주세요.
안녕하세요 제미니님, 유튜브부터 계속 꾸준히 보다가 강의 릴리즈 하신 후 바로 구매하여 듣고 있는 사람입니다. 먼저, 생각할 거리를 많이 주는 좋은 강의 감사드립니다. 다름이 아니라, 일단은 ProductSerivce 안에서 Product라는 개념만을 명확히 다루고자 하였기에 Controller에 타 개념의 Service들도 혼재되는? 그런 상황이라고 이해했습니다. 물론 다 선택의 영역이겠지만, 개발자분들 중에선 Presentation 영역(Controller)을 최대한 가볍게 가지고 가시려는 분들도 많은것 같습니다. 그래서 대신에 여러 서비스들이 혼재되는 상황을 Facade 등을 도입해서 여러 개념의 서비스들에 대한 presentation 계층에서의 접근을 일원화하고 각 서비스단에서의 복잡성은 해결하고자 하는 케이스도 실무에서 종종 접했는데요. 이에 대해서는 제미니님께서 어떻게 생각하시는지 궁금합니다.
안녕하세요 제미니님 유투브때부터 잘 보고 있습니다! 그 25분쯤에 controller에 여러 service들을 주입받아서 사용하시는 부분에 대한 질문이 있습니다. 1. 그럼 격벽으로 넘어도 되는 개념 사이에서는 a service에서 b finder or b appender 를 호출해도 괜찮은건지..? 2. 격벽으로 넘어서 안돼는 개념 사이에서는 강의에 나온것처럼 여러 service를 controller에서 받아서 response를 만들어야 하는건지.....?또 그렇게 되면 controller에서 여러 service를 알아야하니까 그건 또 문제가 없는지.. 궁금합니다!! 제미니님은 주로 어떻게 하시나요!? 감사합니다
안녕하세요. 지난번에도 질문 남겼었는데 또 찾아뵙게 되었습니다. user 의 경우 많은 개념들이 참조하게 될 것 같습니다. 회원탈퇴라는 기능이 제공될 때, 회원이 탈퇴되면 관련된 개념들을 삭제해야된다고 할 경우 이를 어떻게 해결하는 것이 좋을까요? user 쪽에서 관련 개념들을 찾아서 삭제하기에는 개념 격벽간의 순환 참조(?)가 발생하게 될 것 같습니다. 카프카나 메시지 큐 등을 이용해서 처리할 수 있을 것 같은데 현재 이를 처리할 수 있는 별도의 인프라는 없다고 가정해보고 싶습니다. 그렇다면 어플리케이션 이벤트(ApplicationEventPublisher)를 사용하는 것이 방법이 생각납니다. 하지만 이벤트를 사용하게 되면 어플리케이션의 로직 흐름을 보기가 조금 어려우지는 것 같다는 생각도 들어서 괜찮은 방법인지 고민이 됩니다.
안녕하세요, 제미니님! 강의 완독 후, 결제 시스템의 안정성을 높이기 위해 개인 프로젝트에 외부 PG사 연동 구간에 장애 격리 처리를 직접 구현하며 경험하고 있습니다. 구현 과정에서 고민했던 설계 내용과 제 나름의 가설이 맞는지, 그리고 기존 강의 코드의 설정 의도에 대해 여쭤보고 싶습니다. 🙇🏻♂️ 1. 서킷 브레이커 도입 및 트랜잭션 분리 전략 @Component class BeeceptorPaymentClient( private val restClient: RestClient, private val circuitBreaker: CircuitBreaker, ) : PaymentClient { private val log = LoggerFactory.getLogger(javaClass) override fun requestPayment(command: PaymentCommand): PaymentResult { return circuitBreaker.run("beeceptor-payment") { executePayment(command) } .fallbackIfOpen { log.warn("[Circuit Open] Beeceptor 결제 서비스 차단됨. 잠시 후 재시도 필요.") throw CoreException(ErrorType.PAYMENT_EXTERNAL_API_UNAVAILABLE) } .getOrElse { e -> when (e) { is HttpClientErrorException -> { log.warn("[PAYMENT_REJECTED] 결제 거절: ${e.responseBodyAsString}") throw CoreException(ErrorType.PAYMENT_REJECTED) } is CoreException -> throw e else -> { log.error("[PAYMENT_FAILED] Beeceptor 결제 호출 실패", e) throw CoreException(ErrorType.PAYMENT_EXTERNAL_API_FAIL) } } } } } 외부 PG사 장애 전파를 막기 위해 Resilience4j 를 도입했고, 테스트를 위해 Beeceptor를 활용했습니다. 설정 전략: COUNT_BASED (최소 10회, 실패율 50% Open), 단순 비즈니스 에러(4xx)는 ignoreExceptions 로 제외하여 시스템 장애만 감지하도록 설정했습니다. 트랜잭션 분리 (Facade 패턴): 트랜잭션에 대한 DB 커넥션 점유 시간을 최소화하기 위해 아래와 같이 로직을 3단계로 분리했습니다. 1. 검증: DB 조회 (ReadOnly 트랜잭션) 2. 외부 요청: 외부 PG API 호출 (No 트랜잭션 + 서킷 브레이커 적용) 3. 상태 업데이트 : 결제 결과 저장 (Write 트랜잭션) @Component class PaymentConfirmFacade( private val paymentService: PaymentService, private val paymentClient: PaymentClient, ) { fun success(orderKey: String, externalPaymentKey: String, amount: BigDecimal): Long { // 1. [DB Transaction] 결제 검증 val command = paymentService.validatePayment(orderKey, externalPaymentKey, amount) // 2. [No Transaction] 외부 API 호출 val paymentResult = paymentClient.requestPayment(command) // 3. [DB Transaction] 결제 완료 처리 // 외부 API에서 받은 결과(transactionId 등)를 넘겨줌 return paymentService.completePayment(orderKey, paymentResult) } } [질문] Facade 패턴을 적용함에 따라 '외부 요청'(2번)은 성공했으나, '상태 업데이트 및 저장'(3번)에서 DB 장애 등으로 실패할 경우 데이터 불일치가 발생합니다. 현재 로직상 completePayment 가 실패하면 트랜잭션이 롤백되어 TransactionHistory 조차 남지 않고 Payment 상태는 READY 로 유지됩니다. 따라서 저는 배치/스케줄러 를 통해 일정 시간이 지나도 READY 상태로 남아있는 결제 건들을 조회한 뒤, PG사 결제 내역 조회 API와 크로스 체크 하여 누락된 결제를 보정하는 로직이 필요하다고 판단됩니다. 이러한 접근 방식이 실무에서사용하는 일반적인 보정 패턴인지 궁금합니다. 2. DB Connection/Socket Timeout 설정 의도와 Facade 적용 시의 상관관계 외부 API 타임아웃(Connect 3s, Read 30s)을 학습하며 적용하던 중, 기존 강의 프로젝트의 db-core.yml 설정이 눈에 들어왔습니다. connection-timeout: 1100 (1.1초) socketTimeout: 3000 (3초) [질문 1] 보통 DB 타임아웃을 넉넉하게 잡는 경우도 있는데, 이렇게 타이트하게 설정하신 의도가 "트래픽 급증 시 DB 커넥션을 얻지 못하면 빠르게 실패 처리 하여 스레드 풀 고갈을 막고 시스템 전체 장애를 방지 하기 위함" 인지, 혹은 다른 운영 노하우가 담겨 있는 것인지 궁금합니다. [질문 2] 저는 Facade 패턴을 적용하여 외부 API 호출 시점에는 트랜잭션(DB Connection)을 점유하지 않도록 분리 했습니다. 따라서 기술적으로는 DB 타임아웃과 서킷 브레이커(외부) 타임아웃을 서로 독립적인 관점으로 설정해도 된다고 판단했습니다. 다만, 실무 운영 관점에서는 결국 '전체 사용자 대기 시간(User Latency)' 이라는 제약이 존재할 텐데, 이때 전체 응답 시간 제한 내에서 DB와 외부 API 타임아웃 비중을 어떻게 배분하시는지 강사님만의 기준이나 노하우가 궁금합니다 ! 긴 글 읽어주셔서 감사합니다.
요즘 쇼핑몰 커머스등은 비회원 주문이 있는 경우가 거의 대부분인 것 같은데 비회원 주문,결제의 개념이 추가된다면 어떻게 개선될 수 있을까요? api가 복제되는 느낌으로 가야하는지.. 주문, 장바구니, 결제 등등 유저아이디 대신 게스트아이디로 조회하는 등과 같이 작은 부분만 바뀌고 나머지 로직은 동일 반복될 것 같습니다. 주문조회시에도 회원 비회원.. 서비스는하나를 쓰고 OrderFinder에서 함수로 나누는 방식도 생각납니다. 어떤 방식이 더 있을까요?
안녕하세요. DB 레이어를 다루는 것에 대해 몇가지 질문이 있습니다. 프로젝트 버전 1.1 포인트 적립 트랜잭션 리뷰 작성 ReviewService.addReview )에서 포인트 적립 PointHandler.earn )이 한 트랜잭션에서 이루어져야 될 것 같다고 생각했는데 분리되어 있습니다. 이렇게 처리해도 충분한지 여쭤보고 싶습니다. CancelService, PaymentService 에서는 같은 트랜잭션에 있음 낙관적 락 예외 처리 PointBalanceEntity 에는 동시성 처리를 위해 @Version (낙관적 락)을 두었다고 해주셨습니다. 현재는 낙관적 락 예외가 발생하면 500 에러가 발생할 것으로 보이는데, 저는 평소 최대한 이 낙관적 락 예외를 잡아서 적절히 다른 예외로 변환하여 던지도록 했었습니다. 낙관적 락 예외에 대해서 500에러가 발생하도록 처리하는 것으로 충분할지 고민됩니다. Repository, JpaRepository 분리 현재 프로젝트는 서비스 -> 컴포넌트(Finder, Handler, ...) -> JpaRepository 형태로 계층 관계가 있는 것 같습니다. 그런데 재미니님의 유튜브를 보면 서비스 -> 컴포넌트(Finder, Handler, ...) -> Repository(개념 객체를 다루는?) -> JpaRepository 형태의 계층을 이루고 있는 것으로 보입니다. 첫번째 계층구조를 보면 종종 서비스에서 단순히 컴포넌트를 한번 호출하는 정도인 경우가 많은 것 같습니다. 두번째 계층구조를 사용한다면 서비스에서 단순히 컴포넌트를 한번 호출하고, 그 컴포넌트에서도 단순히 Repository를 한번 호출하는 정도인 경우도 많이 생길 것 같습니다. 이러한 이유로 저는 첫번째 계층구조 정도로 충분한가? 라고도 생각했는데 두번째 계층구조를 선택하시게 되는 이유가 궁금합니다. 두번째 계층구조 관련해서 여러 영상들이 있겠지만 우선 저는 아래 영상 참고했습니다. https://www.youtube.com/watch?v=b5xWS8MYl0Q Repository 가 분리된 경우에서의 검증, 업데이트 로직 데이터를 검증, 업데이트할 때 어떤 재미니님과 같은 프로젝트 구조를 가져간다면 어떤 식으로 코드가 나오게 될 지 궁금합니다. 검증, 업데이트라 하면 제가 생각한 예시 상황은 리뷰가 7주일이 지나면 업데이트 할 수 없다는 요건이 있다고 가정해보겠습니다. 제가 생각한 것은 아래와 같습니다. public class ReviewService { private final ReviewFinder reviewFinder; private final ReviewProcessor reviewProcessor; public void update(ReviewUpdate reviewUpdate) { var review reviewFinder.get(reviewUpdate.id()); if (review.canUpdate()) { throw new CoreException(); } var updatedReview = review.update(reviewUpdate); reviewProcessor.update(updatedReview); } } 이전에 프로젝트 구조에 대해서 고민이 많이 되었을 때 재미니님의 유튜브를 보면서 프로젝트 구조를 잡는데 도움이 많이 되었습니다. 그런데 제가 그 의도나 스타일을 완전히 이해하지는 못하고 있는 것 같아서 재미니님의 스타일들을 한번 배워보고 싶습니다. 유튜브에서부터 정말 도움 많이 받고있습니다. 좋은 강의 감사합니다!!