addReview()를 보면 리뷰 저장 이후에 포인트를 지급하는 로직이 함께 들어가 있는데, 제 기준에서는 포인트 지급이 리뷰 작성의 핵심 기능이라기보다 부가 기능처럼 느껴졌습니다. 그래서 이런 부분은 서비스 내부에서 직접 호출하기보다 이벤트를 발행하고, 별도의 핸들러에서 처리하는 방식으로 분리해도 괜찮지 않을까 궁금했습니다. (다만 제가 이걸 정말 "부가적인 책임"으로 봐도 되는지 조금 헷갈리기도 합니다.) 만약 실무에서는 이런 부가적인 로직을 서비스 메서드 안에 함께 둘지, 아니면 이벤트/이벤트 핸들러 형태로 분리할지를 어떤 기준으로 판단하시는지 궁금합니다. 또는 이런 경우 이벤트 외에 다른 방식으로 설계하시는 경우도 있는지 궁금합니다.
자바에서 클래스 필드 타입을 참조타입과 원시타입의 차이를 공부하던 중에 둘의 차이가 null 값이 필요하냐 필요하지 않냐로 배웠습니다.. 그런데 엔티티 pk의 경우에는 jpa에서 새 객체와 저장된객체를 구분할 때 null 을 본다고 들었습니다. 그래서 참조형 Long을 쓰는 구나 라고 생각을 정리했어요!! 헌데 코틀린으로 쓰신 코드에서는 Long타입을 선언하시고 0으로 초기화해주시는 이유가 궁금합니다! 코틀린에서는 nullable하게 할순있지만 기본적으로 null이 불가능하다고 들었긴한데.. 조금 헷갈립니다! 언어적인 부분에서 jpa가 다르게 동작하는것인지 아니면 제가 좀 미숙하게 이해한건지 궁금합니다!
제미니님 이커머스 강의와 프로젝트 코드들을 참고하면서 게시판을 만들어보고 있는 중입니다! 현재는 게시물 정보만 페이징 방식으로 구현해놓았습니다. 근데 게시글 목록을 보여줄 때 한 게시글 당 조회수, 좋아요수, 댓글 수, 유저닉네임 등.. 표시가 되야해서 좀 헷갈립니다. 한 API에서 전부 조합해서 내려준다고하면 페이징된 게시글 10개를 먼저 조회하고 조회한 게시글의 ID를 기반으로 조회수와 좋아요를 따로 조회한 뒤에 같이 내려주는 방식이 좋을까요?
지금 클로드 데스크탑연동에 계속 실패하고 있습니다. 설정파일을 건들면 클로드가 아예 실행되지 않고있고있어요... 윈도우 10 환경에서 인텔리제이 2025.2.6.1 사용중이고, npx, npm 등 필요한것들은 설치완료했습니다. 우선 변경된 설정처럼 아예 목록에 표시되지 않고있는데, 윈도우버전 사용자들도 연동하는 가이드내용을 좀 상세하게 알려주실수있을까요?
제미니님 안녕하세요. 강의를 통해 각 개념 간의 응집성을 높이고, 불필요한 의존성을 줄여 격벽을 세우는 설계를 깊이 있게 연습하고 있습니다. 강의에서 배운 원칙을 적용하여 '리뷰'나 '찜' 같은 개념들이 '상품' 개념을 단방향으로 참조하도록 구조를 잡고 있습니다. 하지만 실제 상품 목록 조회 기능을 구현하다 보니, 설계의 일관성을 유지하기 어려운 상황을 마주하게 되어 조언을 구하고자 합니다. 개념 간 의존성의 역전: 목록 화면에서 '리뷰 수'나 '찜 수'를 함께 보여주거나, 이를 기준으로 상품을 정렬해야 하는 요구사항이 생겼습니다. 이 경우 상품 개념이 본래 몰라야 할 하위 개념(리뷰, 찜 등)의 상태를 알아야만 하는 상황이 발생합니다. API 구성의 어려움: 상세 페이지는 API를 잘게 나누어 클라이언트에서 합성함으로써 개념 간의 독립성을 지킬 수 있지만, 목록의 경우 수십 개의 상품에 대해 매번 각각의 리뷰 수 API를 호출하여 클라이언트가 매핑하는 방식은 어딘가 어색하고 성능과 구현 효율 면에서 의문이 듭니다. 결국 조회를 위해 상품이 다시 리뷰나 찜을 알게 되면, 처음 설계한 개념 간의 단방향 참조 구조가 깨지거나 서로를 참조하는 순환 참조가 발생할 것 같아 우려됩니다. 이처럼 개념 간의 격벽을 유지하려는 설계 원칙과, 여러 개념의 데이터가 한꺼번에 필요한 조회 요구사항이 충돌할 때 어떤 식으로 접근하는 것이 현명할까요? 원칙을 고수하며 우회할 방법이 있을지, 혹은 이런 조회 상황에서는 설계적 타협이 필요한 것인지 견해를 듣고 싶습니다.
누구보다 빠르게 배우는 Nginx + Docker + Springboot 서버 무중단 배포
강의에선 컨테이너 이미지를 DockerHub에 등록해서 사용하셨고, 리버스 프록시를 위해 EC2에 Nginx를 띄워서 사용하셨는데요! AWS 인프라를 활용하는 환경이라면 AWS ALB나 AWS ECR을 쓰고, Terraform 같은 IaC 기술을 활용하면 인프라 구축에 필요한 비용을 많이 줄일 수 있을 것 같다는 생각이 들었습니다. 그럼에도 Docker Hub나 Nginx 인프라를 추가하여 사용한다면 어떤 장점이 있는지 궁금합니다. 실무에선 주로 인프라 구성을 어떻게 하는지도 궁금합니다!
안녕하세요, 선생님! 좋은 강의 제공해주셔서 감사합니다. 덕분에 단순히 구현에만 집중하기보다, 설계와 개념에 대해 더 고민하면서 코드를 작성하게 되었습니다. 섹션 2의 ‘개념 느끼기’ 부분에서 Product가 Product Category보다 더 상위의 개념이라고 말씀해주셨던 것으로 기억합니다. 저도 그렇게 이해했습니다. 그런데 코드 구현 파트에서 Product와 Product Category 사이의 삭제 정책을 두 가지 예시로 설명해주셨는데, 그 부분에서 한 가지 궁금증이 생겼습니다. 제 생각에는 개념적으로 Product가 더 상위 개념이라면, Product가 삭제될 때 Product Category도 함께 삭제되는 정책이 조금 더 자연스러운 흐름처럼 느껴졌습니다. 이 부분에 대해 제가 개념을 잘못 이해한 것인지, 아니면 실무적인 관점에서 추가로 고려해야 할 부분이 있는지 궁금합니다. 혹시 제가 놓치고 있는 관점이 있다면 조언 부탁드립니다!
CLAUDE 에서 json 파일 수정하였고, { "mcpServers": { "jetbrains": { "command": "npx", "args": ["-y", "@jetbrains/mcp-proxy"] } }} 인텔리제이는 2025.2.6.1 버전 다운로드 후, MCP 서버 활성화 해둔 상태입니다. 하지만 계속 프로그램 재실행 하여도, Claude 부분이 활성화되지 않네요. 윈도우 10 사용중입니다. 추가로 어디를 확인하면 될까요?
안녕하세요 강사님. 서비스 계층을 설계할 때 인터페이스를 두고 구현체를 만드는 패턴을 사용하는 이유가 궁금합니다. 현재 프로젝트에서는 구현체가 하나뿐인데, 이런 상황에서도 인터페이스를 분리하는 것이 가지는 실질적인 이점이 무엇인지 알고 싶습니다. 특히 구현이 하나로 고정되어 있다면, 바로 구현 클래스를 빈으로 등록해도 되지 않을지 고민이 되었는데요. 설계 관점에서 인터페이스를 미리 분리해두는 이유와, 실무에서 어떤 장점이 있는지 설명해주시면 감사하겠습니다
Kotlin 2.3버전에서 달라진 점을 하나 더 말씀드릴려고 합니다. 기존 KClass.createType() 은 제네릭 인자(Arguments)를 명시적으로 전달해야 하는 등 사용이 번거로웠습니다. 구 방식: List::class.createType(arguments = listOf(KTypeProjection.invariant(String::class.createType()))) 신 방식 (권장): typeOf<List<String>>() import kotlin.reflect.KType import kotlin.reflect.typeOf // 1. 단순 타입 val intType: KType = typeOf<Int>() // 2. 제네릭 타입 (중첩 제네릭 가능) val listType: KType = typeOf<List<String>>() val mapType: KType = typeOf<Map<Int, List<String>>>() // 3. 널러블 타입 val nullableType: KType = typeOf<String?>() 혹시나 안되시는 분들은 참고하면 좋을 것 같아요!
Kotlin에서 Java의 함수형 인터페이스(SAM Interface)를 사용할 때, 이전 버전과 2.0 이후 버전에서 동작이 달라진 부분을 발견해서 공유합니다. @FunctionalInterface public interface StringFilter { boolean filter(String s); } 위와 같은 함수형 인터페이스가 있다고 하면은 Kotlin 1.x (구 컴파일러) 에서는 다음과 같이 SAM 생성자를 명시적으로 사용해야만 했습니다. val filter = StringFilter { s -> s.startsWith("A") } Kotlin 2.0+ (K2 컴파일러) 에서는 아래와 같은 방식이 정상 동작 됩니다. val filter: StringFilter = { s -> s.startsWith("A") } 왜 바뀌었는지 찾아보니 Kotlin 2.0에서 정식 도입된 K2 컴파일러는 프론트엔드를 완전히 새로 작성하면서, 타입 추론(Type Inference)과 호출 해석(Call Resolution) 시스템이 크게 개선되었습니다. K2 컴파일러 마이그레이션 가이드에서는 이를 다음과 같이 설명합니다. "Improved call resolution and type inference." The compiler behaves more consistently and understands your code better. 구체적으로 K2 컴파일러는 기대 타입(Expected Type)이 Java SAM 인터페이스인 모든 위치에서 람다의 암시적 SAM 변환을 지원하도록 확장되었습니다. 이전에는 SAM 변환이 함수 인자 전달 등 제한된 위치에서만 적용됐지만, K2에서는 변수 대입을 포함한 더 넓은 범위에서 일관되게 동작합니다. 실습하다가 너무 잘 되어서 한번 찾아본 결과를 한번 정리해서 드립니다! https://kotlinlang.org/docs/k2-compiler-migration-guide.html https://kotlinlang.org/docs/whatsnew20.html https://kotlinlang.org/docs/fun-interfaces.html https://kotlinlang.org/docs/compatibility-guide-20.html
Debezium이 데이터베이스 트랜잭션 로그(binlog, WAL 등)를 읽어서 변경사항을 Kafka로 발행한다는 것은 이해했습니다. 그런데 혼란스러운 부분이.... 일반적인 CRUD API 요청도 결국 DB에 변경을 가하는데, Debezium이 이를 어떻게 구분하는지 궁금합니다. 예를 들어 주문 생성 API → DB INSERT → 이건 CDC 이벤트로 발행해야 함 사용자 세션 저장 API → DB INSERT → 이건 CDC 불필요 이런 경우에는 어떻게 구분되나요?
안녕하세요, 안드로이드 스튜디오는 설치했는데 애뮬레이터 실행이 안 됩니다.. otter3를 설치했고 android 31을 받았고 AVD는 Pixel 7a를 받았습니다. 다른 pc에서 똑같이 받아보니 실행이 잘 됩니다. 예상되는 문제는 AVD를 생성하면 생성되는 폴더인 .android 경로에 한글이 들어가서 그런 것 같습니다. 그런데 환경 변수에 사용자, 시스템 각각 ANDROID_AVD_HOME 등과 같은 이름으로 변수명에 넣고 제가 C드라이브 바로 아래에 생성한 AVD라는 폴더 경로를 변수값에 넣어주었습니다. 그리고 pc를 껐다 다시 켜서 실행시켜보면 아래와 같이 새로 생성한 폴더에 파일이 생성 되지만 아래 이미지처럼 기존에 한글이 포함된 경로에 .android가 생성되고 그 안에 다른 파일들이 생성됩니다. 시스템 환경 변수에는 제가 예전에 새로 만들었던거 같은 영어로된 user가 상단에 적혀있고 c드라이브 user에 들어가면 한글로 된 user와 영어로된 user 이렇게 2개가 있는 것 같습니다. 무엇이 문제일까요?? 제발 도와주세요ㅠ