묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
filter가 작동되지 않습니다.
- 강의에 있는 거 그대로 사용했는데 log가 뜨지를 않습니다. 디버그를 찍어보니 필터를 거치지 않는데 어떻게 해결을 해야될까요??- 요청은 정상적으로 가고 응답도 first-service / second-serivIce에 맞게 잘 가져옵니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
RoutLocatortBuilder
안녕하세요 RouteLocateBuilder에 빨간 줄이 뜨는데무시하고 해도 되는건가요?
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
단위 테스트 작성 후 통합 테스트의 범위
안녕하세요! 강의에서 말씀해주신대로, 엔티티 레벨에서 단위테스트를 작성해보았는데 단위 테스트에서 이미 여러 케이스 별로 테스트를 작성했다고 했을 때 서비스 계층의 테스트(repository는 mock 사용)에서도 다시 한 번 모든 경계값 등을 고려하여 '빡빡한' 테스트를 작성할 필요 내지는 그럴 가치가 있다고 생각하시는지 궁금합니다.추가로, 서비스 테스트에서 repository는 mock을 사용한다고 했을 때 repository에 대한 테스트는 생략해도 괜찮은건지 궁금합니다!감사합니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
zuul 강의에서 gradle로 하시는 분들을 위해 공유합니다
zuul을 사용하기 위해서는 spring boot 버전이 2.4보다 낮아야 한다고 해서 2.3.9.RELEASE를 사용했습니다. (2.4 미만 버전은 RELEASE가 붙더라고요)또한, spring boot 버전이 2.4 미만일 경우 spring cloud 2020.0.0 (2.4.x, 2.5.x 에서만 사용 가능) 버전을 사용할 수 없고 Hoxton 버전을 사용해야 됨을 적용했습니다.아래와 같이 해서 실행 성공했습니다.plugins { id 'java' id 'org.springframework.boot' version '2.3.9.RELEASE' id 'io.spring.dependency-management' version '1.0.11.RELEASE' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:Hoxton.RELEASE" } } tasks.named('test') { useJUnitPlatform() }
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
spring boot 3.0.0 에서 p6spy 적용이 안됩니다.
[질문 내용]jpa 강의를 spring boot 3버전으로 진행중입니다.메뉴얼을 보고 쿼리 파라미터 로그 남기기 중에hibernate6org.hibernate.orm.jdbc.bind: trace로 수정 후 해결하였고, 외부 라이브러리인 p6spy는 적용이 안됩니다.p6spy 버전은 1.8.1을 사용했습니다. 해당 문제 해결방법이 있을까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@Transactional 질문있습니다
@Transactional 지정위치에대해 궁금합니다 6:17초 부분에서 JPA의 변경을 이용할때에는 트랜잭션을 사용하는게 좋다고 하셨는데 그러면 MemberService 레벨에서 @Transactional 를 지정하는게 아닌 직접적으로 JPA를 작동시키는 MemberRepository에서 어노테이션을 지정하는게 더 좋지않을까요
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
여러 테이블 fetch join 질문 드립니다!
안녕하세요!Event와 Member의 N : N 관계를 중간 테이블(EventMEmber)을 만들어서 풀어낼때Event <-> EventMember <-> Member에서Event를 리스트로 조회하려고 하는데 이때 EventDto에 Member의 String name 필드를 리스트로 가져오려고 합니다. 1. @Query("select distinct e from Event e " + "join fetch e.eventMember a " + "join fetch a.member")Event에 중간 엔티티인 EventMember를 fetch join하고 별칭을 사용해서 EventMember의 member를 fetch join 했습니다.fetch join에서 별칭 사용을 권장하지 않고, 컬렉션을 fetch join을 하면 추후 페이징에 문제가 생길 것 같습니다. 2.@Query(value = "select e from EventMember e " + "join fetch e.member " + "join fetch e.event")List<EventMember> eventMembers = eventMemberRepository.findAllEventArtist(); Map<Event, List<String>> events = new HashMap<>(); for (EventMember eventMember : eventMembers) { if (!events.containsKey(eventMember.getEvent())) { events.put(eventMember.getEvent(), new ArrayList<>()); } events.get(eventMember.getEvent()) .add(eventMember.getMember().getName()); } 중간 엔티티인 EventMember로 Event와 Member를 fetch join으로 가져오고 자바 코드로 원하는 응답을 만들었습니다. 혹시 둘중 더 나은 방법이나 더 좋은 방법, 제가 잘못 알고 있는 부분이 있으면 말씀 부탁드리겠습니다 ㅠㅠ
-
해결됨스프링과 JPA 기반 웹 애플리케이션 개발
Windows 환경에서 프로필 이미지 변경 Jdenticon 안보이는 현상 문의
안녕하세요.Windows 환경에서 프로필 이미지 변경 화면 접속 시, 아래와 같이 Jdenticon이 안보이는 현상이 발견되네요.IDE를 통해 로컬에서 실행하여 확인할때뿐만 아니라 프로젝트를 Dockerizing한 후, 외부 서버에 컨테이너 형태로 띄운 상태에서 접속하여 동작 확인을 해도 동일한 현상이 나옵니다. 이와 반대로, Mac OS 환경에서는 모두 정상적으로 나옵니다.위 현상과 관련하여 뭔가 Dependency가 있는 요소가 있는걸까요?? 브라우저 캐시 삭제를 해봤는데도 마찬가지네요. 구글링해봐도 관련 내용이 잘 나오지도 않고요. 어떻게 해결할 수 있을지 문의드립니다.
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
벌크 연산 11:09 em.clear()를 하지 않았는데.....
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]Team teamA = new Team(); teamA.setName("teamA"); em.persist(teamA); Team teamB = new Team(); teamB.setName("teamB"); em.persist(teamB); Member member1 = new Member(); member1.setUsername("member1"); member1.setAge(10); member1.changeTeam(teamA); em.persist(member1); Member member2 = new Member(); member2.setUsername("member2"); member2.setAge(20); member2.changeTeam(teamA); em.persist(member2); Member member3 = new Member(); member3.setUsername("member3"); member3.setAge(30); member3.changeTeam(teamB); em.persist(member3); em.flush(); em.clear(); int resultCount = em.createQuery("update Member m set m.age = 100") .executeUpdate(); Member findMember = em.find(Member.class, member1.getId()); System.out.println("findMember.getAge() = " + findMember.getAge());em.clear()를 하지 않으면 10이 나와야 할거 같은데 100이 변경된게 영속성 컨텍스트에 반영이 된거 처럼 나오는데.스펙이 바뀐걸까요? 아니면 제가 뭘 잘 못한걸까요?https://drive.google.com/file/d/1qzmIqCOXOeCdy5McL0_RzcbugxbmdyMV/view?usp=share_link
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
저만 이상하게 되나요? 21:36 join fetch 해도 2번만 나오는 이유가....
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team;Team teamA = new Team(); teamA.setName("teamA"); em.persist(teamA); Team teamB = new Team(); teamB.setName("teamB"); em.persist(teamB); Member member1 = new Member(); member1.setUsername("member1"); member1.setAge(10); member1.changeTeam(teamA); em.persist(member1); Member member2 = new Member(); member2.setUsername("member2"); member2.setAge(20); member2.changeTeam(teamA); em.persist(member2); Member member3 = new Member(); member3.setUsername("member3"); member3.setAge(30); member3.changeTeam(teamB); em.persist(member3); em.flush(); em.clear(); String query = "select t from Team t join fetch t.members"; List<Team> result = em.createQuery(query, Team.class) .getResultList(); System.out.println("result.size() = " + result.size());패치 조인을 해도 왜 2번만 나올까요?혹시나 해서 파일도 올려봅니다.https://drive.google.com/file/d/1nOHKHJdVRezwrNpd_1G_3-EyeD8Neymg/view?usp=share_link
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
[Junit5] 상품주문 재고수량초과 테스트코드 공유합니다
@Test @DisplayName("상품주문 재고 수량 초과") public void 상품주문_재고수량초과() throws Exception{ // given Member member = createMember(); Book book = createBook("시골JPA", 10000, 10); int orderCount = 11; // when // then assertThrows(NotEnoughStockException.class, () -> { orderService.order(member.getId(), book.getId(), orderCount); }); }
-
해결됨실전! Querydsl
Repository 메소드의 파라미터 질문드립니다.
안녕하세요 강의 잘 듣고 있습니다.강의를 듣는 도중에 궁금한 점이 있어서 이렇게 질문 드립니다.컨트롤러의 return타입은 entity를 캡슐화 하기 위해 DTO를 사용하고, 각 Layer 별로 데이터를 주고 받을 때 DTO 또는 Entity를 상황에 맞게 사용하고있습니다. 또한 Repository에서는(Service -> Repository) Entity를 넘겨주어서 사용하도록 하고 있습니다. 이유는 DTO는 Getter,Setter로 가변이지만 Entity는 불변객체이기에 영속 계층에서는 가변 객체를 파라미터로 넘겨준다면 위험하다고 생각해서입니다.그런데 강의에서는 DTO를 Repository 까지 전달하시는 것을 보고 DTO가 영속 계층까지 가는것에 문제가 없는가 궁금하여 질문드립니다.추가로 AEntity의 Repository에서 BEntity를 파라미터로 받아도 설계상?으로 괜찮은지도 궁금합니다.class MemberRepository{ //파라미터로 DTO 받기 List<Member> findMember(MemberDto memberDto){ ... } //파라미터로 다른 Entity 받기 Member doSomething(Team team){ ... } }
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
강의자료와 실제 생성 테이블이 다르고, Address가 값 객체일 수 없다고 생각합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요. 김영한님의 강의를 잘 보고 있습니다. 강의를 보던도중, 문득 의문점이 들어서 여쭤보고자 질문을 작성하게 되었습니다. 질문의 테마는 값 타입 컬렉션과 기본키라고 할 수 있겠네요.기본 지식테이블은 기본키가 있을수도, 없을수도 있다.제가 배운대로는, 테이블은 기본키가 존재할 수도 있고 존재하지 않을 수도 있다고 배웠습니다. 그리고 기본키를 두는 이유는 기본키가 겹치지 않도록 해서, 데이터 중복을 막고, 조회 시 효율 증가를 위해서라고 생각했습니다. 김영한님의 강의에서 말하는 값타입은 주소가 다르더라도 안에 있는 값이 모두 같다고 하신걸로 이해했습니다.그래서 자바 객체가 값타입으로 들어가는 경우에는 equals를 통해서 같은지를 비교한다는 것도요!! 김영한님의 강의 중 예제로 들어주셨던 Member의 favoriteFoods, addressHistory는 값 타입을 데이터베이스 테이블로 변환한 예시로 이해했습니다.그리고 강의 내용에서 JPA를 이용해서 Table 구조를 생성하는 걸로 이해했습니다. 여기까지가 제가 이해한 내용입니다. 저는 그래서 해당 구조로 데이터베이스를 만들어준다고 인지했고, FAVORITE_FOOD, ADDRESS는 각각 중복값이 들어갈 수없다고 생각했습니다. 문제상황하지만 테이블의 생성 내용을 보면, 기본키 설정 부분이 빠져 있습니다.외래키 매핑만 되어 있고 실제로 기본키 부분이 빠져있습니다.제가 만든, ADDRESS 테이블을 예시로 들면,이는, FAVORITE_FOOD 도 동일합니다. 정말 중복값이 들어갈 수 없는지 테스트해보았습니다.테스트를 위한 코드는 다음과 같습니다.Address address = new Address("newCity", "street", "10000"); Member member1 = new Member(); member1.setName("member1"); member1.setHomeAddress(address); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("피자"); member1.getFavoriteFoods().add("족발"); Address oldAddress = new Address("oldCity3", "street", "10000"); member1.getAddressList().add(new Address("oldCity", "street", "10000")); member1.getAddressList().add(new Address("oldCity2", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); em.persist(member1); 결과값은 다음과 같습니다.값을 보게되면, FAVORITE_FOOD의 경우는 Set 자료구조 사용으로 중복값이 들어갈 수 없는 것이고, ADDRESS의 경우는 중복값이 들어갈 수 있었습니다. 만약 값의 변경이 일어나는 경우에는 어떻게 될까? 하는 고민이 생겨, 중복으로 들어있는 내용의 값을 변경해보았습니다.Address address = new Address("newCity", "street", "10000"); Member member1 = new Member(); member1.setName("member1"); member1.setHomeAddress(address); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("피자"); member1.getFavoriteFoods().add("족발"); Address oldAddress = new Address("oldCity3", "street", "10000"); member1.getAddressList().add(new Address("oldCity", "street", "10000")); member1.getAddressList().add(new Address("oldCity2", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); em.persist(member1); em.flush(); em.clear(); Member findMember = em.find(Member.class, member1.getId()); System.out.println("================== Start 2 =================="); findMember.getAddressList().remove(oldAddress); findMember.getAddressList().add(new Address("newCity1", "street", "10000")); tx.commit(); 결과값은 다음과 같습니다.중복값을 한번에 지워준다면, 그래도 결과적으로는 ADDRESS값을 중복이 없는 값객체로 쓸 수 있겠다고 생각했지만, 모두 지우지 않고 중복값을 하나만 지웠습니다.물론 List의 특성 상 중복 값 한개만 지우는게 당연하지만요. 가설목표하던 테이블 구조로 실제로 만들어지지 않았다고 생각했습니다. -> 기본키가 없다.왜냐하면 생성하고자 하는 테이블 구조와 생성된 테이블 구조가 다르기 때문입니다.음식에서 중복이 생기지 않는 이유는 Set의 특성 때문이지 테이블 때문이 아니라고 생각이 들었습니다. 값 객체의 특성 상 중복을 허용하는 경우는 없다.좋아하는 음식의 경우 같은 음식이 두번 있을 이유는 없지만, 이전의 주소의 경우는 같은 주소에 두번 이사갈 수 있다.그렇다면 음식과 다르게 주소의 경우는 중복이 가능하고, 값을 추적할 수 있어야 하므로 Entity로 사용하는게 맞지 않을까요?이 부분은 김영한님깨서 설명해주신 부분과 일치하지만, 결론까지 도달한게 맞는지 궁금합니다. 두서 없이 길게 적은 것 같은데, 제가 생각한 가설이 맞는지가 궁금합니다. 그리고 나아가 가설까지 도달하는 방식에 문제가 있거나 고칠점이 있다고 피드백도 부탁드립니다. 읽어주셔서 감사합니다.
-
해결됨실전! 스프링 데이터 JPA
같은 테이블의 외래키와 복합키
안녕하세요 영한님. 항상 강의 잘 듣고있습니다.회사에서 레거시 코드를 엔티티로 변경하다보니 궁금한게 있어 문의드립니다.첫번째 질문혹시 복합키가 3개의 컬럼으로 되어있을 때, 2개의 컬럼이 같은 테이블과 매핑해야 된다면 어떻게 해줘야하는지 알 수 있을까요? @EmbeddedId, @IdClass 둘 다 필드명으로 매핑을 해줘야 하는데, 한 필드밖에 매핑이 안되서 여쭤봅니다.두번째 질문아래 키들이 전부 Enum으로 되어있다면 조인할 때 @Enumrated(STRING) 이 적용이 안되는 것 같은데 어떻게 하면 좋을지 여쭤봅니다.예를 들어,A의 복합키 [a, b, c] 중 [a, b]가 B와 매핑되는 외래키이고, [c]는 C와 매핑되는 외래키입니다.* 여기서 B의 a, b는 B의 PK입니다.* A와 B는 일대다, A와 C 또한 일대다 관계입니다.class A { @Id @Enumerated(STRING) EnumType a; @Id @Enumerated(STRING) EnumType b; @Id @Enumerated(STRING) EnumType c; } class B { @Id @Enumerated(STRING) EnumType a; @Id @Enumerated(STRING) EnumType b; } class C { @Id @Enumerated(STRING) EnumType c; }@EmbeddedId 사용시@Embeddable public class AId implements Serializable { private BId b; @Enumerated(STRING) private EnumType c; } @Embeddable public class BId implements Serializable { @Enumerated(STRING) private EnumType a; @Enumerated(STRING) private EnumType b; } @Entity public class A { @EmbeddedId private AId id; // 쿼리에서 EnumType의 숫자값이 들어갑니다. @ManyToOne(fetch = LAZY) @JoinColumns(value = { @JoinColumn(name = "a"), @JoinColumn(name = "b") }) private B b; }
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
강의 PPT 자료는 어디서 다운받을수 있나요?
안녕하세요.강의 PPT 자료를 찾아봤는데 없어서 문의드립니다. 현재 다운받을수 없는건가요?
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
프록시와 연관관계 관리 - orphanRemovel 관련 질문
안녕하세요.[프록시와 연관관계 관리 - orphanRemovel] 내용에서 질문드립니다.orphanRemovel = false, cascade = ALL 로 설정한 상태에서 @OneToMany로 설정된 컬렉션 내의 값을 제거하면, cascade 옵션에 의해 update 쿼리가 나갈 때 컬렉션에서 제거된 원소가 같이 삭제되어야 하는게 아닌가요?위 내용이 틀렸다면 cascade의 delete 쿼리는 부모 엔티티 '자체'가 사라졌을 때만 컬렉션 내의 자식 엔티티들에게 전이되는 걸까요??추가로, 고아 객체 제거 기능은 cascade와 마찬가지로, 연관관계의 주인이 아닌 컬럼에서도 사용이 가능한건지도 궁금합니다!내용이 잘 이해되질 않아 질문이 다소 두서없는 점 죄송합니다ㅜ
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@PostMapping으로 등록 시 파라미터 안에 List 질문입니다.
안녕하세요강의 완강 후 따로 프로젝트를 만들어 보던 중 궁금한 게 생겨서 질문 드립니다. PostMapping으로 등록할 때 CreateRequest라는 별도의 클래스를 만들어 주어서 파라미터로 받았는데 이 CreateRequest안에 List를 받아야 할 경우가 있다면 어떻게 해줘야 하는지 잘 모르겠습니다. Product 클래스 입니다.Module 클래스 입니다.하나의 Product에 여러 개의 Module이 들어갈 수 있기 때문에ProductModule 클래스를 만들어줬습니다.이러한 경우에서Product를 등록할 때아래와 같이 넘겨주고 싶으면CreateProductRequest 에서 List를 어떤식으로 받아줘야 하나요? 아래와 같이 해봤는데 잘 안되는 것 같아서요...
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
entity로 의존관계가 들어와야하는데 반대로 의존관계가 나가버린다
회원조회api 영상의 5:40초쯤 하신 말씀입니다.근데 이 말이 무슨말인지 잘 모르겠어요왜 의존관계가 나간다고 표현하시는 거죠?json으로 출력할때만 출력하지 않는것이 왜 의존관계가 나가는일인건가요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
CQS
관련 질문에 대한 답변을 읽어봤는데도 이해가 가지 않아서 질문드립니다.커맨드와 쿼리를 분리해야한다는 CQS를 설명하신 말이었어요. 내부변경이 일어나는것은 커맨드, 명령어라고 부른다커맨드는 결과값을 그대로 반환하면안된다내부변경이 일어나지않는 것은 쿼리라고 부른다.쿼리는 결과값을 반환한다-> 1. 커맨드에서 결과값을 반환하면 안되는 이유가 뭘까요?update 메서드 안에서도 결국은 update하는것(커맨드)과 findOne(쿼리)하는 코드가 모두 들어가있는거잖아요? 근데 이게 왜 cqs를 지킨 사례인거죠?@Transactinalpublic vodi update(Long id, String name){ memberService.update(id,name); Member member = memberService.findOne(id); rreturn ~~~;}
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
memberUpdateDto가 필요한 이유
강의도중에 설명해주시긴 했는데 그래도 이해가 덜 가서 질문드립니다membersaveDto만있으면 memberupdatedto를 만들지 않아도돼요둘다 만들게 되면 코드의 중복이 발생하는것아닌가요?save와 update는 아예다른것이기때문에 중복이 발생해도 상관이 없는걸까요?아예다른것이라기엔 update에도 있고 save에도 있는 필드에 변화가 생겼을때 둘다 수정을 해주어야해요그럼 수정해야할 포인트가 늘어나는건데도 updateDto를 생성해주는게 맞는걸까요?