묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
정적 팩토리 메서드 관련 질문드립니다!
안녕하세요 토비님 궁금한점이 생겨 질문을 남깁니다.예제를 진행하실때 정적팩토리 메서드를 통해 객체를 반환할때생성자를 통하지않고 바로 멤버변수에 값을 넣어 반환하는걸 사용하셨는데 public static Member register(MemberRegisterRequest createRequest, PasswordEncoder passwordEncoder) { Member member = new Member(); member.email = new Email(createRequest.email()); member.nickname = requireNonNull(createRequest.nickname()); member.passwordHash = requireNonNull(passwordEncoder.encode(createRequest.password())); member.status = MemberStatus.PENDING; member.detail = MemberDetail.create(); return member; }이게 가능한 원리는 이해를 했습니다만 AI와 이야기하다보니 아래와 같은 이유를 제시하면서 생성자를 통한 반환을 강력 추천하더라구요부분 초기화 위험: 생성 직후 한동안 불완전 상태일 수 있어요. (중간에 예외가 나면 더더욱)final 을 못 씀: 생성자 밖 대입이 필요하니 final로 못 고정합니다(불변성/스레드 가시성 이점 상실).검증 누락 가능성: 검증/정규화가 흩어지기 쉬움 → 생성자 경로에 모으는 게 안전. 토비님 생각은 어떠하신지 궁금합니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
메모리 누수 이슈
형 질문이 있어! 형 강의 너무 고마워! 배치에서 리모트 파티션 사용중인데 리모트 파티션을 전달에 쓰이는 내부 큐가 있는걸로 알고 있어!그 큐가 GC 가 안되어 1주일 정도 넘으면 OOM 이 떨어지는거 같아! 혹시 무언가 놓친게 있을까?? 설정이나 아니면 필요한 부분이? 답변 부탁해!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
금액 계산은 서버에서하고 클라이언트는 가격 정보를 주지 않았을 때
안녕하세요! 금액 계산은 클라이언트 조작 문제 떄문에 서버에서 담당해야한다고 말씀해주셨는데요, 그렇다면 클라이언트에서는 식별값만을 주고 가격정보는 주지 않았을 때 문제는 없을까요? 예를 들어 클라이언트가 한 화면에서 오래 머무르는 동안 상품 가격이나, 할인 등 총 결제 금액을 계산하는데 있어 변동 사항이 생겼을 때 클라이언트가 보고 있는 가격과 서버에서 요청 시점에서 계산한 가격이 일치하는지까지 봐야하지 않나라는 생각이 들어 질문드립니다..! 서버에서 현재 상태를 기준으로 가격을 계산하고 처리했을 때, 사용자 입장에선 자신이 본 가격과 다른 가격으로 계산될 수도 있지 않을까요??가격을 결정짓는 요소들이 변경되었는지를 서버에서 판단해서 요청 실패처리를 할 수 있겠지만, 요소들이 많다면 각각을 버저닝하고 확인해야 하는 형태가 될 거 같기도 해서.. 클라이언트에서 확인한 가격 정보를 서버에 넘기고, 서버에서 실시간으로 계산한 금액과 일치한다면 성공시키는 구현 형태는 실무에서 잘 쓰지 않는 것인지 궁금합니다!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
어떤 경우 도메인(개념)객체를, 어떤 경우 JPA 엔티티를 활용하나요?
서비스들을 보면 어떤 경우는 finder같은 서비스 하위 계층을 통해 도메인(개념)객체를 활용하기도 하고, 서비스에서 직접 repository를 의존해서 jpa entity를 활용해서 로직을 수행하는 케이스도 있어 보입니다! 혹시 서비스 단에서 도메인 객체를 가져와서 사용하는 것과 jpa entity를 직접 활용하는 것의 판단 기준이 따로 있으실까요?
-
미해결스프링 부트와 리액트로 구현하는 소셜 로그인
[소셜 로그인 33강] 일반 로그인 -> 소셜 로그인 관련 질문
33강에 27-30분대를 보면SecurityConfig 클래스에서 .formLogin을 .oauth2Login으로 바꾸고, TodoController 에서 CustomUserDetails로 받았던 사용자 정보를 CustomOAuth2User 로 바꾼 것으로 보이는데,,일반 로그인 시에 사용할 로직과 소셜 로그인 시에 사용할 로직을 둘 다 두지 않고, 소셜 로그인 하나만 사용하는 것으로 진행하려고 바꾸는건가요??
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
목록 조회에서 개념(도메인)객체를 반환할 때
현재 코드상으로 목록조회에서도 개념객체를 활용하는 것으로 확인했습니다! 하지만 한 개념 객체가 여러 개념 객체를 포함하는 경우가 있는 상태에서 페이지네이션 같이 모든 개념객체의 필드를 채워줄 필요가 없는 경우도 있을 거 같습니다. 이때, 필요한 컬럼만 추출한 데이터를 담는 별도 dto용 객체를 만든다개념 객체의 일부를 채운 값을 Page에 반환한다 실무에선 둘 중 어느 방식을 적용하는지 궁금합니다! 제 생각에는 개념(도메인) 객체는 항상 완전한 상태로 있어야 하므로 별도 프로젝션 dto용 객체를 만들어서 서비스단에서는 도메인 객체가 아닌 해당 dto 객체를 내려주는 것이 낫지 않을까 생각합니다. 또한 사용하지 않는 필드를 완전한 객체 상태로 만들어주기위해 불필요하게 많은 추가 쿼리가 발생할 수 있어서 이런 경우는 별도 값(dto)객체를 쓰는 게 나을 거 같은데 실무에서는 어떻게 하는지 궁금합니다!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
화면과 관련한 정보 처리 질문입니다
안녕하세요..! 네이티브 앱 환경에서 서버 개발을 하다보니, 여기 강의에서나오는 리뷰 수가 어떻게 보일지 같은 문제를 서버에서 컨트롤 하자는 얘기가 자주 나와 질문 드립니다. 예를들어, 15000건의 리뷰수를 100+ 였다가, 15k 같은식으로 변경 되는걸 서버에서 string으로 내려달라는 것이죠. 현재는 원본데이터를 도메인에서 처리하고, 보여질 데이터를 dto 단에서 처리하는 식인데요..매번 화면에 표현되는걸 실험이라고 계속 바꿔대는데, 조금 불편한 느낌이 생기더라구요. 이런 경우는 보통 어떻게 처리하는게 좋을까요? 화면을 제어하는 필드가 많아질 수록 더 관리가 안되는거 같아요. 특히 os 별 다르게 처리한다던가..
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
Service 간 의존하는 경우
안녕하세요! 너무 구현적인 질문을 드리는 걸 수도 있지만, 개념을 나누고 이를 결과적으로 코드로 구현해보려는 입장에서 어느정도 규칙이나 일관성을 두고 구현하면 더 좋겠다는 생각에 질문드립니다! 현재 구현상으로 1. 하나의 개념을 한 서비스로 만들고, 서비스간의 의존은 피하는 형태로 구현하신 게 맞을까요? 2. 만약 그렇다면, 예를 들어 ReviewService에서 현재는 pointHandler를 호출하고 있는데, 이 핸들러의 로직이 더욱 응집되어 PointService의 메서드 자체를 호출하는 것이 하나의 동작으로써 자연스럽다면, 이런 경우는 PointService를 ReivewService에서 의존해서 메서드를 호출하기보단, ReviewHandler 및 추가로직이 응집된 PointService 서비스 하위레이어(?)를 두어서 이를 의존하게 하는 형태로 구현하시는 건지 알고 싶습니다..!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
개념을 나타내는 객체 내에 로직이 들어있는 것은 좋지 않을까요?
ReviewService에서 addReview를 할 때, ReviewTarget 객체와 ReviewContent 객체를 넘겨주어서 Validator에서 이를 검증하는 코드를 봤습니다. 이와 같이 개념을 표현하기 위한 객체 내부에 검증 메서드(비즈니스 적인 요소 or 값 누락 등)를 두는 건 좋은 방법이 아닐까요? 예를 들어 validator에서는이러한 개념을 구성하는 요소간 복합 검증이 필요한 경우 이러한 내용을 구현하고, 각 요소 자체에서 할 수 있는 검증은 ReviewTarget같은 객체에서 validate()메서드를 두어, 해당 객체가 갖고있는 데이터에 대한 검증을 하게 한다면 어떨까 생각이 들었습니다.아직 강의를 끝까지 보지 못했지만, 개념 객체 역할을 하는 class가 단순 dto 처럼 값만을 들고 있는 역할을 하는 것 같아 질문드립니다..!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
격벽의 의미
안녕하세요! 격벽은 주요 개념을 나누고 가능한 직접 의존하지 않게 하는 판단 기준이라고 생각이 들었습니다! 그런데 예를 들어 복잡한 조회 쿼리의 경우에는 컨트롤러단에서 각 개념 간 조회를 하고 이를 어플리케이션 단에서 데이터를 필터링하는 것보다 join을 하는 경우가 성능적으로나 구현적으로 나은 방식이 될 수 있을 거 같습니다! 이런 경우 서로 다른 두 개념이 있을 때 한 개념 내 테이블과 다른 개념 내 테이블을 직접 join하는 경우가 있을 거 같은데요, 혹시 이런 경우도 가능한 지양하시는 편이실까요?? 벽을 침범하지 않는다는 것이 이런 경우에도 적용되어야 하는 것인지 궁금합니다!
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
개념 간 격벽을 침범하는 경우
안녕하세요! 보통 실무를 하다보면 여러 개념이 명확히 떨어지지 않는 경우도 있을 거 같습니다. 예를 들어 예약의 경우는 상품을 고르고, 여러 할인정책이 있고, 쿠폰, 포인트 등 여러 개념이 혼합되어 생기는 개념이라고 생각합니다! 혹시 이런 경우에는 예약도 한 개념이라고 볼 수 있을까요? 그리고 예약이 한 개념이라면 ReservationService를 만들었을 때 ReservationService는 godObject같은 형태가 만들어지기 쉬울 거 같은데, 이런 경우 재민님이라면 어떻게 예약과 다른 개념 간 격벽을 치고, 구현적으로는 어떻게 풀어나갈 것인지 알고 싶습니다!
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
spotbug + @NonNullApi 로만 Null 방어가 될까요?
안녕하세요, nullable 프라퍼티가 없다면 null를 방어하는 방식에 대해 궁금한 점이 있어 질문남깁니다.14. Member 도메인 로직 개발 - 생성자에 requireNonNull() 사용15. 스프링을 이용한 널(null) 안정성 확보 - SpitBugs 플러그인 - package-info 에서 @NonNullApi이렇게 세가지 방법을 배웠는데요, SpitBugs 플러그인이 "빌드과정에서 정적 분석을 하여 애노테이션 의미와 부합하지 않으면 에러를 내준다" 라는 말씀에 "그럼 도메인에 Nullable 프라퍼티가 없으면 requireNonNull() 사용 없이 단순히 @NonNullApi + SpotBug만 사용해도 되지 않을까..? "의문이 들었습니다.3가지 모두 사용하는게 Null 방어에 괜찮을까요? 아니면 제가 이해한 대로 SpotBug 플러그인 + @NonNullApi 로만 사용해도 충분할까요?
-
미해결Spring Boot TDD - 입문부터 실전까지 정확하게
테스트 시나리오 유효하지 않은 경우는 언제 도출하나요?
테스트 시나리오 유효하지 않은 경우는 언제 도출하나요?테스트 시나리오를 작성하기 전에 모든 경우의 수를 고려해서 작성해야할지 고민입니다.제가 개발하는 도메인을 명확하게 잘 모르면 이걸 도출해내기가 쉽지도 않고 시간이 너무 소요되더라구요. 어느정도 limit 시간을 잡으시고 점진적으로 못찾은 부분을 도출하시는지 의견이 궁금합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
도메인 및 dbcore 패키지 구조 질문있습니다
안녕하세요, 강의 보기 전 소스코드부터 보고 있는데 패키지 구조에 궁금증이 생겨 질문드립니다. 현재 domain 및 db core 패키지 하위에 도메인별 세부 패키지 분리 없이 모든 파일이 배치되어 있는데요, 추후 프로젝트 규모가 커져 파일 개수가 수백, 수천 개에 달하게 될 경우에도 이러한 구조(패키지 미분리)를 유지하시는 것을 선호하시는지 궁금합니다. 감사합니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
강의자료중 github 자료
학습 관련 질문을 최대한 상세히 남겨주세요!고민 과정도 같이 나열해주셔도 좋습니다.먼저 유사한 질문이 있었는지 검색해보세요.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 혹시 github 자료도 받아볼 수 있나요?
-
미해결실습으로 배우는 선착순 이벤트 시스템
consumer가 topic을 전부 사용하기 전에 사용자에게는 쿠폰이 발급된것으로 확인하는 과정에서 발생가능한 문제.
운영중인 서비스에서 선착순 100명 이벤트를 적용한다고 가정하겠습니다. redis를 통해 100명을 제한했고, kafka를 적용하여 부하를 줄여주는 것은 까지는 이해했습니다. 부하를 줄이는 방법이 kafka를 적용할때 때 provider가 topic을 생성하고 consumer가 topic을 가져와서 DB에 입력하는 작업을 하는 것으로 이해했는데요. 만약 이게 실제 운영 환경이라고 가정했을때 궁금한것은 다음과 같습니다.사용자가 이벤트 신청redis에서 쿠폰 생성 수량 확인 결과 생성 가능한 조건 임으로 새로운 쿠폰 발급provider가 새로운 토픽을 생성 토픽을 생성한 그 순간 바로 직후, 사용자는 새로운 쿠폰이 발급된 것으로 확인 해야함.그치만 consumer에서 topic을 가져오기 전으로 DB에는 새로운 쿠폰이 생성되지 않음.쿠폰을 사용(또는 확인) 하려고 DB에서 select해보니 쿠폰이 없음consumer가 이제서야 쿠폰 생성이 경우에서 보는 것과 같이.provider가 topic을 생성하고 consumer가 topic을 가져와서 DB에 넣는 과정 사이에 사용자가 select를 진행하는 케이스가 있을것같습니다.이 부분은 어떻게 해결할 수 있을까요?혹시 다음과 같이 해결 할 수 있을까요?provider가 topic을 생성하는 과정에서 발급 내역을 redis에 입력consumer가 모든 토픽을 전부 사용하여 DB에 입력하기 전까지 redis에 입력되어 있는 쿠폰 정보로 사용자에게 보여줌consumer가 모든 토픽을 사용했을때(= 생성된 모든 쿠폰정보를 DB에 입력했을때) redis에 있는 쿠폰정보는 삭제하고 DB에서 select해서 보여줌.궁금합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
삭제 기능 구현에 대한 질문입니다.
안녕하세요. 오늘도 재미있게 잘봤습니다. 감사합니다.// ReviewManager.kt @Transactional fun delete(user: User, reviewId: Long): Long { val found = reviewRepository.findByIdAndUserId(reviewId, user.id) ?: throw CoreException(ErrorType.NOT_FOUND_DATA) found.delete() return found.id }이 코드를 보면서 삭제를 구현할 때 두 가지 방식이 있겠다는 생각이 들었습니다. 첫번째는 조회 + 삭제, 두번째는 정확한 key를 넘겨주어서 한번에 삭제. 둘 가운데 어떤 방식을 선호하시는지 궁금합니다.처음에는 두 번째 방식으로 구현을 한다면 메서드 이름과 동작이 더 일치해서 좋고 코드도 한 줄에 끝나서 더 좋은게 아닌가? 라고 생각을 했었는데 그렇다면 첫번째 방식을 하면 좋은점이 무엇일까 다시 생각을 해보니 만약 삭제할 때 ORM 예외가 발생한다면 ReviewManager가 몰라도 된다는게 장점일 수 있겠다는 생각이 들었습니다.
-
미해결견고한 결제 시스템 구축
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인지, 혹은 그게 아니라면 무슨 의미인지 알려주시면 감사하겠습니다!강의 내용을 듣다보면, "다운로드 받을 수 있는 쿠폰을 조회한다" , "다운로드 받은 쿠폰을 조회한다"와 같이 의미가 비슷하지만 이해하기 헷갈려서 그렇습니다 ㅜㅜ