묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
상품 상세 컨트롤러 내 서비스 호출 질문
강의에서 상품 상세 컨트롤러에서 여러 개의 서비스를 직접 참조해 하나의 응답으로 반환하고 있는데요이 경우, 단일 서비스에서 데이터를 묶어 응답하지 않고 각 서비스를 개별적으로 호출하는 이유가 궁금합니다.이런 구조가 모듈을 분리했을 때 Aggregation 성격의 서비스가 여러 서비스에 의존하게 되는 문제를 피하기 위한 설계인가요?또, 여러 서비스를 호출하면 하나의 API 요청 내에서 여러 트랜잭션 커넥션이 열릴 수 있는데, 이를 설계 상 트레이드오프로 봐야 할까요?추가로, 강의에서는 productId 하나만 받아서 여러 서비스를 독립적으로 호출하고 있는 것 같았는데,서비스 간 호출 순서가 없으므로 각각을 독립적인 유즈케이스로 보는 게 맞을까요?아니면 컨트롤러가 여러 서비스를 조합하는 역할을 가져도 되는 걸까요?마지막으로, 저는 조회 시 실무에서는 모듈별 유즈케이스가 각각 존재하고, 이를 묶어주는 별도의 서비스가 로직과 조합을 포함하여 담당하고 있습니다.예를 들어 상품 조회 API 응답 시 상품내용과 함께 회원 이름/생년월일 등등 포함, 쿠폰 정보 포함 요구사항이 주어졌을 때두 가지 방식으로 구현할 수 있을 것 같은데요어떻게 바라보시는지 궁금합니다.# 방법1 # 특정 서비스에서 조합하여 호출 상품 API 모듈(컨트롤러) → 상품 Service 모듈 → 회원 모듈 서비스1, 쿠폰 모듈 서비스2, ...# 방법2 # 각 서비스를 컨트롤러에서 호출 상품 API 모듈(컨트롤러) → 회원 모듈 서비스1, 쿠폰 모듈 서비스2강의에서는 방법2 와 비슷하게 처리하신 것 같습니다.강의 중 여러가지 패턴을 소개해 주신다고 했지만 급하게 질문드리는 점 죄송합니다.
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
Domain Expert가 정확히 어떤 역할을 하는 사람인가요?
도메인 모델을 만들기 위해서는 Domain Expert에게서 듣고 배워야 한다고 말씀하셨는데, 이들의 정확한 역할이 잘 이해가 가지 않습니다.온라인 서점을 예로 들자면 제 머리속에 상상되는 Domain Expert는 실제 서점을 운영하는 사장님이 떠오르는데 강의에서는 회사에서 해당 일을 오랫동안 해 오신 분이나, 관련된 시스템을 개발해 본 경험이 있는 시니어 개발자 같은 사람을 Domain Expert라고 말씀 주셨습니다.그렇다는건 Domain Expert 라는 역할은 이 회사가 개발하고 있는 서비스를 가장 잘 알고 있는 사람 (그것이 개발자가 되었든, 디자이너, po와 같은 비 개발자가 되었든)이라고 이해해도 되는 것일까요?
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
날짜 수정
안녕하세요! 날짜 수정 관련해서minusDays를 변경하는게 어째서 불편한건가요?안에 들어가는 파라미터만 바꿔주면 되는데 불편해지는 부분이라는게 잘 이해가 안되네요
-
미해결알면 칼퇴하는 Spring Boot 백엔드 바이브 코딩 맛보기
소리가 잘 들리지 않는 부분이 있습니다.
중간중간 소리가 잘 들리지 않는 구간이 있습니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
오타(?) 발견
킬구형 3장. 작전1: 관계형 데이터베이스 읽고 쓰기 (테이블의 심장에 처형장을 세우다 ☠) 읽고있는데 뭔가 오타같은거 발견한거같아
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
OrderService에서 조회에 트랜잭션 걸어준 이유가 있을까요?
올려주신 다른 주요 개념들에서 조회에는 트랜잭션이 별도로 걸려있지 않았었는데, Order 쪽은 getOrders 와 getOrder 모두 트랜잭션이 걸려있더라구요! 혹시 이쪽에만 특별히 트랜잭션을 걸어주신 이유가 있나요? 감사합니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
학습 방향
코드를 한줄 한줄 같이 치면서 학습을 하는데요, 강사님께서도 코드 한줄 한줄 같이 치신다고 하셨으나 이번 , 다음 강의에서는 yml, controller, service, vo등 모든 것이 작성이 되어있더라고요. 따로 설명 하는 부분 없이 바로 서버 실행 하시는 거 보고 당황했습니다. 코드를 직접 쳐가면서 학습을 하고 싶은데 그러지 못한거 같아 아쉽고, 어디 까지 깃허브에서 코드를 가져와서 사용해야 하나 궁금합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
findSections질문
안녕하세요!findSections의 return부분을 떼어다가 ProductSectionSevice에 옮기는 부분이 있는데옮기기 전과 후의 차이가 어떤 차이가 있는건지 알 수 있을까요? 저의 실력이 부족해 잘 이해가 되지 않아 질문드립니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
카프카 커넥터 사용 목적 문의
127, 128 섹션 관련 문의드립니다.2개의 오더 마이크로서비스 각각에 연결된 데이터베이스로 인한 동기화 문제를 위해 카프카 커넥터를 활용하여 하나의 단일 디비로 문제를 처리한다고 하셨는데, 결국 2개의 오더 마이크로서비스에 카프카 커넥터를 사용하지 않고 동일한 디비 1개를 직접 연결해서 사용하면 동기화 문제가 발생하지 않는건 마찬가지아닌가요? 동일한 오더 마이크로서비스를 스케일아웃 하는 상황에서 카프카 커넥터를 사용하는게 목적에 맞는지 의아해서 질문드립니다.
-
미해결스프링 부트 - 핵심 원리와 활용
@Configuration 질문드립니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]publicclass ImportSelectorTest { @Test void staticConfig() { AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(StaticConfig.class); HelloBean bean = appContext.getBean(HelloBean.class); assertThat(bean).isNotNull(); } @Test void selectConfig() { AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(SelectorConfig.class); HelloBean bean = appContext.getBean(HelloBean.class); assertThat(bean).isNotNull(); } @Configuration @Import(HelloConfig.class) publicstaticclass StaticConfig {} @Configuration @Import(HelloImportSelector.class) publicstaticclass SelectorConfig {}}안녕하세요. StaticConfig, SelectorConfig 클래스에 @Configuration 애노테이션은 어떤 모질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용]public class ImportSelectorTest { @Test void staticConfig() { AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(StaticConfig.class); HelloBean bean = appContext.getBean(HelloBean.class); assertThat(bean).isNotNull(); } @Test void selectConfig() { AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(SelectorConfig.class); HelloBean bean = appContext.getBean(HelloBean.class); assertThat(bean).isNotNull(); } @Configuration @Import(HelloConfig.class) public static class StaticConfig {} @Configuration @Import(HelloImportSelector.class) public static class SelectorConfig {}} 안녕하세요. StaticConfig, SelectorConfig 클래스에 @Configuration 애노테이션은 어떤 역할을 하나요? @Configuration 애노테이션을 주석 후 테스트를 해봤을 때 정상 동작하는 것까진 확인하였습니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
게시글 테스트 데이터 삽입 - @PersistenceContext 에 관하여
DataInitializer 와 관련하여, EntityManager 를 @Autowired 가 아닌, @PersistenceContent 로 가져온 까닭이 궁금합니다. 제가 이해한 바에 따르면, initialize 메서드에서 정의된 ExecutorService 의 스레드 풀은 트랜잭션 전파가 이뤄지지 않으니, TransactionTemplate 을 사용하여 명시적으로 트랜잭션 블록을 지정해주고, 영속화를 위한 과정에서, entityManager 의 프록시 객체가 트랜잭션 내부에서 적절한 객체를 가져와 수행한다고 알고 있습니다. 이 과정에서, EntityManager 의 프록시 객체를 위해 @PersistenceContext 를 사용하여 선언함은 알겠으나, @Autowired 를 사용하여 스프링에서 관리하는 것 역시도 SharedEntityManager 에서 파생된, 동일한 프록시 객체를 반환하는 걸로 알고 있습니다. PersistenceContext 로 em 을 가져온 이유가 있나요? 아니면 선호하시는 방식이라 채택한 방법인가요? 물론 제가 이해한 바에서 틀린 부분이 있을 수도 있으니 잘못 이해한 바가 있으면 정정도 부탁드립니다. 강의 잘 보고 있습니다~
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
댓글 테이블 설계
안녕하십니까 선생님,댓글 테이블의 parent_comment_id 컬럼에 외래키 제약조건을 걸지 않고 설계를 하셨는데 이러한 선택의 구체적인 이유가 있을까요?? 저는 무결성 보장을 위해 셀프 조인 + FK제약조건을 생각했었습니다.
-
미해결[TEST] MD파트 스탠드업 챌린지
린다는 무엇을 먹고 싶은가요?
린다린다
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
샤딩의 기준
안녕하세요 쿠케님 강의 잘 보고 있습니다!강의를 보다가 갑자기 궁금한 점이 생겨서 질문 드립니다. 샤딩의 기준이 현재는 article_id로 되어 있는데, 특정 샤드에 댓글 데이터가 엄청 생성되어서 불균형하게 저장이 되는 경우도 있을까요?? 있다면 샤딩의 기준을 다시 정의하는 일도 있는지 궁금합니다.항상 잘 보고 있습니다. 감사합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
CouponService에서 이미 다운로드 한 쿠폰 안 내려주기
안녕하세요! 수업 중에 재민 님이 말씀해주신 이미 다운로드 한 쿠폰은 내려주지 않는 것과 관련해서 질문이 있습니다.제 나름대로 생각해 본 코드는 이렇습니다.fun getCouponsForProducts(productIds: Collection<Long>): List<Coupon> { val productTargets = couponTargetRepository.findByTargetTypeAndTargetIdInAndStatus( CouponTargetType.PRODUCT, productIds, EntityStatus.ACTIVE, ) val categoryTargets = couponTargetRepository.findByTargetTypeAndTargetIdInAndStatus( CouponTargetType.PRODUCT_CATEGORY, productCategoryRepository.findByProductIdInAndStatus(productIds, EntityStatus.ACTIVE).map { it.categoryId }, EntityStatus.ACTIVE, ) val applicableCouponIds = (productTargets + categoryTargets).map { it.id }.toSet() val downloadedCouponIds = ownedCouponRepository.findByUserIdAndState(userId, OwnedCouponState.USED) # userId 어디서 받아오지? .map { it.couponId } .toSet() val finalCouponIds = applicableCouponIds - downloadedCouponIds if (finalCouponIds.isEmpty()) { return emptyList() } return couponRepository.findByIdInAndStatus(finalCouponIds, EntityStatus.ACTIVE) .map { Coupon( id = it.id, name = it.name, type = it.type, discount = it.discount, expiredAt = it.expiredAt, ) } }여기서 고민됐던 부분은 findByUserIdAndState 에서 userId 를 어디서, 어떻게 받는 것이 좋을지 입니다. getCouponsForProducts 함수가 호출되는 ProductController의 findProduct 메서드에서는 별도의 User 관련된 정보를 받아오지 않기 때문에 userId 를 받아올 수 없는 상황인 것 같습니다. 그런데 유저가 자신이 이미 다운로드 한 쿠폰을 중복해서 '다운로드 가능 쿠폰' 목록에서 보이지 않게 하는 소위 '개인 맞춤' 작업은 User가 꼭 필요한 정보라고 생각 되는데요.이런 경우에 findProduct에 CouponController에서 처럼 User를 바로 넘겨주면 간단(?)하게 userId를 알 수는 있지만 이게 최선인 것 같진 않습니다. User를 파라미터로 넘겨주는 것을 인증 절차를 거친다고 생각해본다면 상품 상세 정보 보는 것은 꼭 인증을 하지 않더라도 볼 수 있어야 할테니까요. (그런데 User를 파라미터로 넘겨주는 것이 인증이 된 사용자만 이 API를 사용할 수 있다고 이해하는 것이 옳은 이해인지는 제가 잘 모르겠습니다🥹)그래서 또 다른 접근법으로는 재민 님이 ProductController의 findProduct 메서드에서 쿠폰을 불러오는 부분 위에 주석으로 처리해놓으신 것처럼 별도의 API를 만들고 해당 API에서 User를 활용해서 진행하면 어떨까 하는 생각도 해봤습니다. 재민 님은 어떤 식으로 푸실지 궁금합니다! 감사합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
프로덕트와 카테고리에 대한 질문
안녕하세요!강의 중 잘 이해가 안되는 부분이 있어 질문드립니다.카테고리에 상품이 있는 방향으로 설명을 진행하다가 실제 구현에선 프로덕트의 카테고리이다 라고 정의를 하셨다고 말씀해주셨는데설명과 실제 구현이 다른 이유가 있을까요?
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
lockType 오류 및 카운트 체크 안 됨
안녕하세요! 강의 잘 듣고 있습니다. 좋은 강의 감사합니다.실습하다가 오류가 생겨 문의 드립니다. void like(Long articleId, Long userId, String lockType) { restClient.post() .uri("/v1/article-likes/articles/{articleId}/users/{userId}/" + lockType, articleId, userId) .retrieve(); } @Test void likePerformanceTest() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(100); // 100개의 스레드 풀 생성 // 각 lock type별로 테스트 likePerformanceTest(executorService, 1111L, "pessimistic-lock-1"); likePerformanceTest(executorService, 2222L, "pessimistic-lock-2"); likePerformanceTest(executorService, 3333L, "optimistic-lock"); } void likePerformanceTest(ExecutorService executorService, Long articleId, String lockType) throws InterruptedException { CountDownLatch latch = new CountDownLatch(3000); System.out.println(lockType = " start"); like(articleId, 1L, lockType); long start = System.nanoTime(); for (int i = 0; i < 3000; i++) { long userId = i + 2; // String finalLockType = lockType; executorService.submit(() -> { like(articleId, userId, lockType); latch.countDown(); }); } latch.await(); long end = System.nanoTime(); System.out.println("lockType = " + lockType + ", time = " + (end - start) / 1_000_000 + " ms"); System.out.println(lockType + " end"); Long count = restClient.get() .uri("/v1/article-likes/articles/{articleId}/count", articleId) .retrieve() .body(Long.class); System.out.println("count = " + count); }여기서 '람다 식에 사용되는 변수는 final 또는 유사 final이어야 합니다' 라는 오류가 뜨더라고요. // String finalLockType = lockType; 부분 주석 해제하고 람다 내부에 like(articleId, userId, finalLockType); 으로 하면 startlockType = start, time = 914 ms start endcount = 0 startlockType = start, time = 589 ms start endcount = 0 startlockType = start, time = 567 ms start endcount = 0 으로 출력도 잘 안 나옵니다. 애플리케이션 콘솔에는 아래 로고만 찍히고 나머지는 안 나옵니다.Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=?Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=?Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=? 어느 부분이 문제일까요? ArticleLikeController에서 count 경로는 테스트처럼 뒤에 /count 추가했습니다.
-
미해결서버개발자 과제전형 완벽가이드 - 1편
Kotlin 테스트 프레임워크
안녕하세요🙂실무에서 만약 Spring과 Kotlin으로 프로젝트를 진행 했을 때 Spock로 테스트 코드를 짜도 상관이 없을까요?이번에 Kotlin으로 프로젝트를 진행해야하는 일이 생겼는데, 저 또한 강의에서 사용하신 Spock가 익숙해서 사용을 하려고 했는데, 보통 Kotest를 많이 사용하는 것 같아서요. 실무 관점에서 Java 대신 Kotlin을 사용한다면, 어떤 테스트 프레임워크를 선택하는것이 좋을지 궁금해서 질문드립니다. 감사합니다.
-
해결됨제미니의 개발실무 - 커머스 백엔드 기본편
강의를 보고 궁금한 것 질문 드립니다!
안녕하세요 🙂 지난번에 이어 질문을 또 남기게 되었습니다 ㅎㅎ 1. Point 라는 개념을 다룰 때 PointService에서 로직을 처리하지 않고 별도의 PointHandler라는 객체를 만들어서 처리하는게 Point 개념 자체가 다른 개념에서도 많이 사용하는 개념이다보니 PointService에서 처리하게 되면 Service 간 참조가 생기는 것을 방지(?) 하고자 이런 전략으로 처리한 것일까요? 이런 식으로 격벽을 넘어서 여러 개념에 걸쳐 있는 개념을 다룰 때는 별도로 분리해놓는 것이 재사용성, 응집 측면에서 좋은 전략인지 궁금합니다! 2. 지금 Point 변화를 주는 것을 PointBalanceEntity 에서 처리하고 있는데 만약 추후에 복잡한 포인트 적립 정책이 생긴다면 별도의 PointPolicy 를 Object 클래스로 만들어 해당 클래스에 포인트 적립 관련 로직을 응집 시키는 식으로 PointPolicy 라는 개념을 추가하는 건 어떻게 생각하시는지 궁금합니다! 감사합니다😀
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
회원 애플리케이션 서비스 테스트 (1)
회원 애플리케이션 서비스 테스트 (1) 12:46초 부분EmailSenderMock에 getter 어노테이션이나 메서드가 없는데 어떻게 getTos를 사용하신 걸까요..?