묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
- 
      
        
    미해결견고한 결제 시스템 구축confirm 로직에서 amount를 검증하는 부분에서 질문이 있습니다.현재는 클라이언트에서 넘어온 amount를 검증하고 있는데 이는 조작 위험이 있지 않은지 궁금합니다.예를 들어 1원만 결제하고 서버에는 10000원을 결제했다고 보내면 서버에서는 결제 승인 API를 호출하여 totalAmount를 확인하기 전까지는 알 수 없는걸까요?결제 승인 API에서 반환되는 Paymet 객체에 totalAmount 필드가 있기는 하지만 결제를 승인하기 전에 toss 서버에서 실제 결제된 금액을 조회하는 방법이 따로 없는건지 궁금합니다 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편findSections 메서드 위치에 관련하여 질문 드립니다강의를 듣고 재민 님이 말씀해주신대로 코드를 옮겨 봤는데요.ProductFinder에 findSections 메서드가 있지 않고 ProductSectionService에서 ProductSectionRepository를 통해 바로 조회하는 것도 꽤 자연스럽고 괜찮다고 느껴졌습니다.그런데 여기서 궁금한게 있습니다. Product 관련한 건 ProductFinder 라는 별도의 객체가 책임을 갖게 해서 코드를 짜다가, ProductSection에서 갑자기 바로 Repository에 접근해서 조회를 하도록 하면 코드 통일성 측면에서 바람직한가? 하는 의문이 문득 들더라구요.그렇다고 ProductSectionFinder를 또 만들어서 하자니 너무 과한가? 싶은 생각도 들었습니다. 추가로 ProductSection 조회에 다른 요구사항이 생기거나, 복잡한 구현을 해야 된다면 ProductSectionFinder 같은 걸 만들어도 좋을 것 같은데, 현재 시점에서 만드는 것이 좋은 접근인지 확신이 안 생긴달까요 ㅎ만약 이런 고민이 들 때는 어떤 것에 우선순위를 두어서 결정하는 것이 좋을 지 재민 님의 의견이 궁금합니다. 좀 더 자연스러운 흐름대로 짜는 것이 나을지, 혹은 코드 통일성 유지를 위해서 바로 Repository에 접근하는 것은 지양 하면 좋을지 등등 말이죠!이건 회사나 팀마다 정해진 규칙이 있을 가능성이 높지만 공부하는 입장에서 궁금증이 들어 이렇게 질문을 드립니다. 감사합니다😀 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편쿠폰 관련 부분에서 질문있습니다.쿠폰 챕터 부분에서 "코드 느끼기" 강의의 7~8분대에 CouponController 부분에 getOwnedCoupons 에 대해 강의에서는 "내가 받을 수 있는 쿠폰 목록 전체를 내려준다"고 말씀하셨습니다. 그런데 제가 이해하기로는 "다운로드 받은 쿠폰(들)을 전체 조회한다"로 생각했습니다.그 이유는 download(다운로드)를 해야만 ownedCoupon 엔티티로부터 데이터를 가져오기 때문입니다.혹시 제가 이해한 것처럼 getOwnedCoupons 의 역할이 "내가 받을 수 있는 쿠폰을 조회한다"가 아닌 "다운로드 받고 난 쿠폰을 조회한다"와 같은 API인지, 혹은 그게 아니라면 무슨 의미인지 알려주시면 감사하겠습니다!강의 내용을 듣다보면, "다운로드 받을 수 있는 쿠폰을 조회한다" , "다운로드 받은 쿠폰을 조회한다"와 같이 의미가 비슷하지만 이해하기 헷갈려서 그렇습니다 ㅜㅜ 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편Entity에 대해 질문이 있습니다.먼저 재미있게 강의 잘보고 있습니다. 감사합니다.프로젝트에서 storage 모듈을 보다가 모든 entity가 status를 갖는다는 것을 알게되었습니다.class xxEntity():BaseEntity() // base entity가 status를 갖고 있고 // 위의 코드는 상속이라고 알고있습니다(AI로 확인해봤는데 만약 아니라면 민망할것같네요...)모든 entity가 상태가 필요한가? 하는 생각이 들어서요. 아니면 status를 기본으로 설정하면서 어떤 장점을 의도하려고 하신건지 궁금합니다. 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편Review에서 ReviewKey에 대하여안녕하세요 제미니님 강의를 보다 궁금한 점이 생겨 질문드립니다.리뷰 작성 시 주문아이템 건에 대해 한 건의 리뷰만 작성 가능하도록 요구사항을 잡고 작성하셨습니다.따라서 새로운 리뷰를 작성할 때 해당 상품에 대한 주문아이템 리스트를 조회하여 아직 기간 내에 작성하지 않은 주문아이템이 있을 시 작성이 가능하도록 하셨는데요.이런 경우 ReviewKey없이 바로 주문아이템 건에 대한 FK를 잡아도 될거 같은데 FK를 잡지 않고 ReviewKey를 별도로 만드신 이유가 궁금합니다 ! 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편서비스의 테스트에 관하여...안녕하세요!리뷰 쪽 강의를 듣다가 궁금한 점이 있어 질문드립니다.강의에서는 findReviews를 제외하고 나머지 기능은 Implement Layer를 통해 각각 값을 전달하는 구조로 되어 있는 것 같습니다.저도 코드 응집도를 높이기 위해 비슷한 구조를 사용 할때가 있는데 실제로는 ReviewService가 여러 작은 서비스에 위임하는 퍼사드 역할을 하게 되는 경우가 있습니다.이런 퍼사드 서비스는 테스트를 어떻게 하는 것이 좋을지 고민입니다. 제가 생각하기에는,1. 통합 테스트를 통해 전체 흐름을 검증하거나2. 각 작은 서비스들을 목(Mock) 혹은 페이크로 대체하여 호출만 검증하는 방법이 가능할 것 같은데 어느 방법이 더 적합한지 확신이 없어 질문드립니다. 
- 
      
        
    해결됨모든 웹 개발자가 봐야 할 단 한 장의 지도강의내용 질문드립니다안녕하세요!강의를 새로 구매했는데, 이전에 구매했던 강의 내용과 겹치는 것 같아수강하기 전에 미리 여쭤봅니다! [이전에 구매했던 강의]면접 전에 알고 가면 좋을 것들 - 신입 Java 백엔드 개발자편 [새롭게 구매한 강의]모든 웹 개발자가 봐야 할 단 한 장의 지도 혹시 새롭게 구매한 강의가 기존에 있던 강의 내용과중첩되는 내용일까요? 감사합니다. 
- 
      
        
    미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.동시 접근 시 lock을 통한 성능 저하 문제강의를 보다보니 궁금한 점이 있어 질문 남깁니다. 첫번째로 궁금한 점은 AbstractPagingItemReader의 코드를 doRead 함수 안에서 lock을 잡고 있으며, doReadPage가 끝난 후 lock을 푸는 것을 확인할 수 있었습니다..doReadPage에 실제로 paging 로직이 존재하니 사실상 paging 로직은 직렬로 수행되는 것과 다를 바 없을 것이며, 성능적으로 크게 증가하지 않을 것 같다는 생각이 드는데요.. (거의 직렬 처리와 유사할 것 같다는 생각이 드네요..) 사실상 병렬 처리라해도 Reader쪽에서 성능 향상이 거의 없다고 보면 될까요? 두번째로 궁금한 점은 AbstractPagingItemReader 상위 클래스인 AbstractItemCountingItemStreamItemReader의 read 함수를 보니 멤버 변수인 currentItemCount를 증가시키는 로직이 존재하더라구요.. 이 부분도 병렬처리에 문제가 될 것 같다는 생각이 들고 해당 클래스의 주석에도 "Subclasses are inherently <b>not</b> thread-safe." 라고 적혀있는 것으로 봐서는 문제가 존재하는 것 같은데요.. 그럼에도 불구하고 기능상 영향이 없으니 하위 클래스인 AbstractPagingItemReader는 thread-safe하다고 나와있는 것이라고 생각하면될까요?? 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편초기 서버 스펙·인프라 가정 및 ProductCategory 설계 기준 관련 질문안녕하세요. 섹션 2까지 수강한 뒤, 몇 가지 궁금한 점이 있어 질문드립니다. 1. 섹션 1 상황 정의 관련섹션 1 상황 정의에서 다음 이미지와 같이 상황을 정의했습니다. 이러한 초기 시스템과 비즈니스 상황을 가정할 때, 다음 두 가지 사항이 궁금합니다.서버 스펙: 현재 두 대의 서비스 서버에 대해 강의에서 가정한 하드웨어 스펙(CPU 코어 수, 메모리 용량 등)은 어느 정도일까요?인프라 예상 투자 비용: 초기 시스템 구성(서버, DB, 로드 밸런서 등)을 위해 현실적으로 투자 가능하다고 설정한 예상 비용 규모는 어느 정도였는지 궁금합니다. 2. 섹션 2 상품과 카테고리 개념도 관련섹션 2에서 다루신 상품과 카테고리 개념도에서 ProductCategory를 Product의 하위 개념으로 이해했습니다. 이 경우, Category와의 의존성만 끊고, 객체를 직접 참조하도록 설계하는 것이 더 직관적일 수도 있을 것 같다는 생각이 들었습니다. 혹시 실제 설계에서는 ProductCategory 엔티티가 Product 엔티티를 직접 참조하는 대신, productId만을 참조하도록 설계하신 이유나 의도가 있을까요?또한, 일반적으로 엔티티 간의 관계를 설계할 때, 객체를 직접 참조할지 아니면 식별자(ID)만을 참조할지를 어떤 기준으로 판단하시는지도 궁금합니다. 좋은 강의 제공해주셔서 감사합니다. 남은 강의도 열심히 수강하겠습니다! 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편"응집도를 높이기 위해 Product 객체는 Review 객체를 의존 하지 않는다" 에서 질문이 있습니다.말씀해주신 부분에서 Product 객체 응집도를 높이기 위해 서로 Review 객체를 모르는 것이 좋다고 말씀 해주셨는데요. 그럼 코드 내용을 보면 Controller 객체에 Product 객체 하고 Review 객체를 알고 있다는 것 인데요.만약 요구 사항이 Product 데이터 하고 Review 데이터를 가공해서 계산된 데이터를 Client 에게 내려줘야 하는 상황이 있다고 가정 하겠습니다. 그럼 Controller 객체에는 Product 데이터 하고 Review 데이터를 가공해서 계산 하는 비지니스 로직이 분명 있을 것 같습니다. 이것을 Controller 객체에 비지니스 로직이 있으면 Controller 에 대한 역할이 더 분담 되는 것 같아서요. 그래서 제가 생각 한 것은 ProductReview 객체를 만들어서 (어떻게 보면 퍼사드 패턴 이겠네요...)ProductReview 객체가 Product 하고 Review 객체를 알고 Product 하고 Review 객체는 서로 모르는 것이 좋지 않을까 생각 됩니다. 이 방법은 어떻게 생각하시는 궁금 합니다. 굳이 Product 하고 Review 로 대표적으로 설명 해주셨는데 보통 실전에서는 이와 같은 비슷한 상황이 많이 발생 될 것 같습니다. 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편core-enum 모듈에 대하여안녕하세요 제미니님코드를 보다가 core-enum 모듈에 대해 궁금점이 생겨 질문드립니다.core-enum의 경우 core-api와 db-core에서 의존성을 받아 쓰고 있는데요.core-api가 db-core를 의존성 받아 사용하고 있고 core-enum에 있는 값들은 모두 db-core에서 사용하고 있습니다. 이런 경우 그냥 db-core에 enum 값들이 있어도 될거 같은데 굳이 따로 모듈로 빼신 이유가 궁금합니다 !최대한 생각해본 바로는 db-core를 사용하지 않는 또 다른 모듈에서 사용한다는 가정 밖에 떠오르지 않습니다.혹시 다른 이유가 있을까요? 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편블로그에 정리공부한 내용을 블로그에 정리하려 하는데, 혹시 예제 사용해도 괜찮을까요? 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편섹션2에서 Product와 Category 간 개념 정리에 대해 질문이 있습니다 !제미니님 안녕하세요 !강의 수강 중 Product와 Category간 개념 정리네 대해 질문이 있습니다 ! 강의를 들으면서 Product와 Category에서 Product가 상위의 개념이라고 선택하시고 매핑 테이블을 네이밍을 ProductCategory을 사용하셨다고 이해하고있습니다 !그런데 개념도를 봤을때.. 개념 간 매핑해주는 ProductCategory가 Product 개념 영역에 있는게 맞는지 의문이 들었습니다 ! Category가 Product 하위의 부가적인 정보로서 ProductCategory가 Product 개념 영역에 존재할 수도 있지만.. 강의에서 설계하는데 있어 Product가 상위 개념으로 판단을 했고, ProductCategory는 Category에 대한 부가정보인데 상위 개념이 하위 개념에 대한 것을 모르도록하는게 맞지 않나 라는 생각이 들어서 질문드립니다 ! 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편도메인 계층에서 Page 사용 질문안녕하세요! 평범한 대학생 백엔드 개발자 입니다!저희 대학생에게 맞는 강의 영상 찍어주셔서 감사합니다 :) 다름이 아니라 도메인 계층에서 Page를 사용해도 되는지 의문이 발생했습니다.제가 인지한바로는 도메인 계층은 순수한 로직이 이루어져야한다고 알고 있습니다.그래서 저는 도메인 계층에서 Page에 관한 DTO를 하나 생성하고 스토리지 모듈에서 해당 DTO로 반환하게 코드를 작성하였습니다. 그런데 강사님의 코드를 보니까 도메인 계층에서 Page를 사용하고 있더라고요... 단순한 트레이드 오프일까요? 클린 아키텍처와 회사 내 규칙을 따를 것이냐 아니면 개발 편의성을 위해 Page만 허락한다는 등... 그런 것들이 존재할까요? 그렇지만 도메인 계층에서 스프링 프레임워크에 대한 의존성을 갖는게 되지 않을까요... 잘 모르겠습니다! 이렇게 생각하는게 좋은 방향일까요? ㅠㅠ(추가로 도메인 계층에서 Page를 사용할 시 테스트 코드는 어떻게 작성하나요?) 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편이상적인 공부 방법강사님이 추구하시는 생각하는 공부에 대해서 많이 고민해보게 되었습니다.그렇다면 강사님이 생각하셨을 때, 이 강의를 보고 공부하는 이상적인 방법은 어떤게 있다고 생각하시나요?예를 들면, 하나의 섹션을 먼저 다 보고 요구 사항 정리부터 다시 시작해보기 아니면 각 강의마다 끝나고 요구사항을 정리해보고 다음 넘어가기.. 등등 강사님도 커리큘럼을 만드실 때 이런식으로 하면 좋을 것 같다가 있으셨을 것 같은데 궁금합니다. 
- 
      
        
    해결됨제미니의 개발실무 - 커머스 백엔드 기본편Controller에서 비즈니스 로직 흐름이 나타나는 것에 대하여..안녕하세요.결제 부분 강의를 보니 payments API를 보면 컨트롤러에서 주문을 조회하고, 사용 할 쿠폰을 조회하고, 포인트를 조회하고, 조회 된 데이터를 PaymentService로 전달하는 스타일이더라구요. 제가 진행중인 사이드 프로젝트도 커머스가 주제입니다. 제 프로젝트도 처음에는 강의 코드 스타일대로 컨트롤러에서 필요한 데이터를 조합하고, 결제를 처리하는 Service 쪽으로 넘기는 형식이었는데, 이게 점점 결제 기능이 고도화되면서 뭔가 컨트롤러에서 비즈니스 로직의 흐름이 보이는게 맞나? 라는 생각이 들게 되었고 어느 순간부터 웬만한 Controller에서는 1개의 xxxService.method()만 호출하고 이 method가 요청에 대한 비즈니스 로직을 전부 담당하게 되었습니다.@Service class QuestionPaymentService( private val questionOrderGenerator: QuestionOrderGenerator, private val promotionApplier: PromotionApplier, private val orderCouponApplier: OrderCouponApplier, private val paymentCouponApplier: PaymentCouponApplier, private val questionPaymentRecorder: QuestionPaymentRecorder, private val pointCommandAPI: PointCommandAPI, private val eventPublisher: EventPublisher, ) { @Transactional fun payment(command: QuestionPaymentCommand): QuestionPayment { val order = questionOrderGenerator.generateQuestionOrder(command.userId, command.questionIds) val questionPayment = QuestionPayment.create(command.userId, order) promotionApplier.apply(order) orderCouponApplier.apply(questionPayment, command) paymentCouponApplier.apply(questionPayment, command) pointCommandAPI.usePoint(questionPayment.userId, questionPayment.realAmount) questionPaymentRecorder.record(questionPayment) eventPublisher.publish(toEvent(questionPayment)) return questionPayment } }위 코드는 제 프로젝트의 결제 부분인데요. 강의에서 말씀하신 것처럼 Service가 너무 많은 걸 알게되더라구요.(주문도 생성하고, 쿠폰도 적용하고, 프로모션도 적용하고...)지금 이 글을 작성하다보니, 갑자기 제 코드가 못생겨보이네요..강의 코드와 비슷한 방식으로 위 코드를 바꿔본다면, 컨트롤러에서는 orderService를 이용해서 주문을 생성하고, couponService, promotionService 등을 이용해서 전처리를 한 뒤 PaymentService을 이용해 실 결제 금액만큼 금액을 지불하도록 하는 로직과 결제 내역을 저장하는 로직만 있을 것 같아요. 반대로 제 프로젝트 방식대로 강의 코드의 payments API를 만들어본다면, Payment를 만들기 위해서PaymentCreateService와 같은 곳에서, orderReader, ownedCouponReader, pointReader 등을 조합해서 Payment를 생성하는 방식이 될 것 같아요.결국 Service가 적은 책임만 가지게 된다면, Controller 입장에서는 복잡한 요청을 처리하기 위해선 다양한 Service를 조합하게 되고 Controller가 비즈니스 로직의 흐름을 보여주는 형태가 될 수 있다고 생각이 드는데요.(사실 Controller가 비즈니스 로직의 흐름을 보여주면 안된다는 걸 어디서도 듣지 않았지만 뭔가 어색한 것 같아요.)물론 계속 말씀하시는것 처럼 정답은 없다는 것은 알지만, 그냥 단순히 재민님은 주로 많은 책임을 가지는 Service보다는 Controller에서 작은 단위의 Service로 조합해서 처리하는 것을 선호하시는지 궁금합니다.재민님을 지속 성장 가능한 소프트웨어 포스팅으로 알게되었고, 유튜브에서도 많은 도움이 되었어요.그렇게 얻은 다양한 인사이트들을 개인 프로젝트에도 적용해보면서 다양한 시도를 하고 있는데 마침 제 관심사인 커머스 주제로 강의가 나와서 정말 행복합니다. 
- 
      
        
    미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.미스터 KILL-9 Processor 단 질문이 있다안녕하신가 미스터 KILL-9항상 빠르고 친절한 답변 고맙다 이번에 회사 로직 작성중에 조금 막막한 부분이 있어 질문 하러 왔다 reader 엑셀 파일 읽어오고processor 에서 해당 엑셀 데이터 값을 가지고 dao 호출해서 검증하고, 깍고(가공)마지막으로 쓰기 처형하는데 작업을 하는데문제는 가공 단계에서 dao 를 직접 호출하면ExecutorType 이 simple 로 호출되고 쓰기 단계에서 batch 로 ExecutorType 실행되어 에러가 발생한다Cannot change the ExecutorType… 이렇게 말이다..그래서 일단 아래 코드 처럼 해결은 했어 우선 기존 코드는 PoiItemReader -> ItemProcessor<> (여기서 mybatis dao 호출 해서 검증작업도 함) -> MyBatisBatchItemWriter -> 에러 Cannot change the ExecutorType… 해결한 코드 PoiItemReader -> ItemProcessor<> (여기서 mybatis dao 호출 해서 검증작업도 함) -> JdbcBatchItemWriter-> (해결)그런데 이렇게 작성해도 되려나 싶네.. 그리고 String 문으로 쿼리 짜는것도 맘에 안들고..ㅠㅠ 
- 
      
        
    미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.오타발견- 명백한 한계점 (단점): - 네트워크 대역폭 소모: 실제 데이터를 전송하므로 네트워크 부하가 극심하다. 데이터 건수가 많거나 크기가 크면 통신 자체가 병목이 될 수 있다. ("핵탄두 데이터 전송에 따른 통신망 과부하 주의!") - Manager 읽기 병목: Manager 혼자 모든 데이터를 읽어야 하므로, 읽기 자체가 느리다면 원격 청킹은 효과가 없다. ("중앙 정찰 위성의 스캔 속도 한계!") - 복잡성(감시와 디버깅의 지옥문): 역시 미들웨어(Kafka 등)와 프링 인티그레이션 설정이 필수적이다.프링 인티그레이션 ->스프링 인티그레이션 
- 
      
        
    미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.예제 빠진부분?KILL-9: "이 구성이 매우 중요하다. Job 설정을 보면, logFileManagerStep()이 먼저 실행되고, 그 다음에 mergeOutputFilesStep()이 실행되도록 .next() 메서드로 연결되어 있다.없어도 뻔해서 이해되긴하는데,위의 예제에서 Job빈이랑 LogFileManagerStep빈(이건 일부러?) 빼먹은듯?KILL-9: "이 구성이 매우 중요하다.로 검색하면될거야------그리고 그냥 궁금한건데,이번강의챕터가 컨셉자체는 맘에드는데(코드랑 내용이랑 같이 스토리넣어서 말하는거)인프런 강의 시스템상 너무 보기힘들지않아?부록 2: 전장 구축 - Redis to MongoDB 데이터 이관 작전 환경 설정같은거보면,나는 가로휠이 있어서 괜찮았는데 가로휠마우스가 없으면 마우스 드래그로 컨트롤하거나 키보드 화살표로 조금씩 밀어야하는데 이거 너무 보기 힘들거같아스크롤바도 내용화면이 한페이지를 넘어가면 안보이고 그래서다음거 스카이넷보고서인지 그런식으로 개행을 넣던가 하면될거같긴해킬구<스카이넷 ?다음거 원격 파티셔닝 강의 대부분 그냥 서두보고 다 스킵할거같은데,@ConditionalOnProperty로 조건부 빈생성 관리하는거 스킵되는거 아까운데 이거나 줏어가라고 마지막 부록에 넣어줄만하지않음?나도 그냥 내용 대충 훑어만봤는데 저거하나는 건진거같아서 
- 
      
        
    미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Coresocket connect 오류안녕하세요.nestJS강의를 잘 시청하고있습니다.진행하는 과정에서 Socket Connect 연결 요청시 Error: socket hang up 오류가 발생하며 연결이 되지 않는 문제가 발생 하였습니다.저는 현재 NestJS최신버전인 11.1.6버전을 이용해 진행중입니다.PostMan에서 Connect 시도시 아무런 로그가 남지 않습니다.혹시 아래 문제에 대해서 도움을 받을 수 있을까요? 
