25%
66,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
batchsize 질문 있습니다.
1. batchsize는 지연 로딩에 대한 것들을 in query통해서 한번에 가져오는 거라고 이해하면 될까요?? 2. batchsize통해 DB에서 애플리케이션에 불러온다고 하셨는데 그럼 영속성 컨텍스트에도 batchsize통해 한번에 불러온 데이터들이 들어 있는건가요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
컬렉션 조회 및 Dto..질문 있습니다!
안녕하세요 강사님 다름이 아니라 실무에서 querydsl을 많이 사용하고 있는데, 저 같은 경우 거의 Dto로 직접 조회할 수 있도록 만들었는데, 강사님은 우선 엔티티를 조회하고 거기서 fetch join등을 활용해서 최적화를 하는 걸 추천한다고 말씀해주셨더라고요 ㅎㅎ 물론 상황마다 다르고 정답은 없겠지만, 그럼 querydsl을 활용하실때도 dto로 직접 조회하기 보다는 entity로 가져오고 그 다음에 dto로 모두 매핑하는 작업을 해주시는 건가요?? V2 처럼이요!
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
양방향 연관관계일 때 한쪽을 끝는거에 대해 질문드립니다.
@JsonIgnore 어노테이션을 사용하면 지금 상태로는 꼭 하이버네이트5모듈을 사용해야 하는거죠? 일단 지금은 그렇게 알고있으면 될까요? 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
예제 수준을 넘어선다면 어떻게 해야할까요?
안녕하세요 팀장님! mvc 강의 열렬히 기다리면서 복습하고 있습니다. 예제에서는 회원 엔티티의 pk를 자동 생성되는 id를 사용하시는데요, 일반적인 포털 사이트 로그인과 같이 id와 pw를 회원이 직접 입력해서 사용하는 경우에는 artificial key 를 pk로 두고, unique 제약 조건으로 로그인 id를 만드는게 좋을까요? 아니면 로그인 id자체를 pk로 만드는 것이 좋을까요? pk는 비지니스 로직과 상관이 없는 유일한 값이어야 하고, generated value가 이 제약조건에 정확히 부합하지만, 회원 id자체가 비지니스 로직과는 별로 연관이 없어 보이기도 하고 unique제약조건또한 만족하니 어떻게 엔티티를 만들어야 할지 고민입니다.
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
강의가 너무 재밌어요
스프링 무료강의부터 시작해서 지금까지 계속 보고있는데 너무재밌어요 스프링, DB에 대해서 아무것도 모르는 상태에서 가볍게 듣다가 중간에 강의 듣는데 필요한 지식들이 있으면 기초적인것만 따로 공부하고 오고 하는 형식으로 듣고있는데 어쩌다보니 여기까지 와버렸네요 ㅎㅎ 사실 저같은 아무것도 모르는 상태에서 듣기에는 점점 갈수록 난이도가 있어서 몇번이고 포기할까 고민도 많이했는데, 그럴때마다 그냥 모르는 부분까지의 강의를 다시 정주행 하기도 하고, 따로 영한님 도서도 구매해서 그걸로 복습하기도 하고 했거든요. 갑자기 이런 글 쓰는 이유는 API 최적화 강의 보면서 이해가 술술 되는 수준까지 온게 너무 신기할 따름이라서 그게 너무 기뻐서 써봤어요.😭 항상 강의 잘 보고있습니다.그리고 저같은 경우는 영한님 JPA 책 덕택을 많이 봤기 때문에 언젠가는 또 다른 다양한 서적들이 나올거라고 믿고있습니다!!! 항상 감사합니다 ㅜㅜ
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
모든 주문리스트 조회하는 타임리프 올려봅니다.
<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head th:replace="fragments/header :: header"></head><body><div class="container"> <div th:replace="fragments/bodyHeader :: bodyHeader"></div> <div> <div> <form th:object="${orderSearch}" class="form-inline"> <div class="form-group mb-2"> <input type="text" th:field="*{memberName}" class="form- control" placeholder="회원명"/> </div> <div class="form-group mx-sm-1 mb-2"> <select th:field="*{orderStatus}" class="form-control"> <option value="">주문상태</option> <option th:each="status : ${T(jpabook.jpashop.domain.OrderStatus).values()}" th:value="${status}" th:text="${status}">option </option> </select> </div> <button type="submit" class="btn btn-primary mb-2">검색</button> </form> </div> <table class="table table-striped"> <thead> <tr> <th>#</th> <th>회원명</th> <th>대표상품 이름</th> <th>대표상품 주문가격</th> <th>대표상품 주문수량</th> <th>상태</th> <th>일시</th> <th></th> </tr> </thead> <tbody> <span th:each="item : ${orders}"> <tr th:each="orderItem : ${item.orderItems}"> <td th:text="${orderItem.item.id}"></td> <td th:text="${item.member.name}"></td> <td th:text="${orderItem.item.name}"></td> <td th:text="${orderItem.orderPrice}"></td> <td th:text="${orderItem.count}"></td> <td th:text="${item.status}"></td> <td th:text="${item.orderDate}"></td> <td> <a th:if="${item.status.name() == 'ORDER'}" href="#" th:href="'javascript:cancel('+${orderItem.order.id}+')'" class="btn btn-danger">CANCEL</a> </td> </tr> </span> </tbody> </table> </div> <div th:replace="fragments/footer :: footer"></div></div> <!-- /container --></body><script> function cancel(id) { var form = document.createElement("form"); form.setAttribute("method", "post"); form.setAttribute("action", "/orders/" + id + "/cancel"); document.body.appendChild(form); form.submit(); }</script></html> 구글 뒤져가면서 왜 이중 each를 쓰는데 인텔리제이가 빨간줄 긋지...싶었는데 tr을 두번으로 each하면 안되나봅니다. ㅠㅠ 바깥의 each를 span태그로 바꿔주니까 잘되는거같네요! 혹시나 막히시는 분들은 참고하셔요! 이거 만드는데 1시간넘게걸렸네요 .. ㅠㅠㅠㅠㅠㅠ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
API 설계시 게시글과 댓글
안녕하세요 강사님. http, 스프링, jpa 모두 강사님 수업을 듣고 인생 첫 스프링 프로젝트로 게시판 API를 구현 해 보려고 하는 대학생입니다. 그래서 현재 아래와 같이 요청경로와 요청법, 응답 본문, 에러응답 등을 문서화 하고 있습니다. 경로를 올바르게 설계했는지는 잘 모르겠지만, 게시글 정보 반환시 게시글과 댓글관계에 대해 궁금해서 질문 드립니다. GET /boards/{board-id}/posts/{post-id} 으로 요청시 게시글의 작성자id, 제목, 내용등이 반환되는데, 댓글들의 목록도 포함시킬지 고민입니다. 보통 게시글이 댓글을 가지고 있으니깐 처음에는 댓글 요청경로를 빼고 게시글 요청에 당연히 포함시켜야 하지 않나? 생각을 했습니다.그런데 댓글에 페이징 기능까지 넣으려고 생각하니깐 게시글과 댓글을 분리해서 게시글정보와 댓글 정보를 각각 받아오도록 하는게 좋을 것 같다는 생각이 들었는데, 혹시 현업에서도 댓글과 게시글은 분리해서 각각 따로 가져오게 설계를 하는지 궁금합니다. 추가적으로, 이건 강사님의 HTTP수업과 관련된 질문이긴한데 게시글,유저 등록같은 POST /boards/{id}/posts 의 201 응답 Location 헤더에 생성된 자원의 주소(예를들어 http://localhost:8080/boards/1/posts/1)가 어차피 포함되어 오는데, 응답 본문에 생성된 자원(게시글)을 다시 보내주는게 RESTful API에 더 가까운가요? 생각해보면 생성된 자원의 위치를 어차피 알려주는데 의미없는 오버헤드인 것 같더라구요.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
패치조인과 페이징 에러 질문입니다.
우선 Post와 User는 다:1 단방향 연관관계로 설정했습니다. 1. 패치조인 없이 페이징 2. 패치조인 + 페이징 N+1문제를 해결하기위해 패치조인을 했습니다.그런데 에러가 났습니다. 로그중에 Count query validation failed for method public abstract ...... 이라는 에러가 있어서jpa가 자동으로 날려주는 CountQuery에 문제가 있나 싶어서 CountQuery를 별도로 작성했습니다. 3. 패치조인 + 페이징 + countQuery 별도로 작성 위 처럼 작성하니 에러없이 정상적으로 동작을 합니다.그런데 왜 에러가 나는지 이유를 정확히 모르겠습니다.. 2번쿼리에서 countQuery가 어떻게 나가길래 에러가 나는건지 궁금합니다..!혹은 다른데에 문제가 있는건가요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
컨트롤러 영속성컨텍스트
선생님 안녕하세요. 강의를 듣다가 궁금한 점이 생겨 질문드립니다. orderRepository는 트랜잭션이 없고, 트랜잭션이 없으면 조회 후에 영속성 컨텍스트가 사라진다고 알고있었습니다. @GetMapping("/api/test/simple-orders")public void orderTest(){ Order order = orderRepository.findOne(4L); System.out.println(order.getMember());// 지연로딩. 프록시객체 이므로 실제 db에서 조회 => 조회 쿼리 나감 System.out.println("------------------------------"); System.out.println(order.getMember()); //영속성컨텍스트 1차캐시에서 조회} select member0_.member_id as member_i1_4_0_, member0_.city as city2_4_0_, member0_.street as street3_4_0_, member0_.zipcode as zipcode4_4_0_, member0_.name as name5_4_0_ from member member0_ where member0_.member_id=? jpabook.jpashop.domain.Member@6c10324f ------------------------------ jpabook.jpashop.domain.Member@6c10324f 근데 위에 코드에서 첫번째 getMember()는 db에서 조회되었고 두번째 결과는 1차캐시에서 조회되었는데, 이렇게 되려면 orderRepository.findOne()이후에도 영속성컨텍스트가 사라지지 않고 유지되고 있어야되는것 아닌지 궁금합니다. 추가로 orderRepository.findOne()에 @Transactional을 붙였을때도 같은 결과가 나오는데 함수 호출이 끝난 시점에는 트랜젝션이 끝나 영속성 컨텍스트도 사라진다고 알고 있어서 혼란스럽습니다. 제가 놓치고 있는게 뭔지 궁금합니다. 감사합니다!!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
one-to-may 의 관계에서 side effet 로 oom 의 발생가능성
안녕하세요 김영한 개발자님 수업을 듣던중 one-to-may 의 관계에서 side effet 로 oom 의 발생가능성에 대해 고민을 하게되어 질문드립니다. 테이블이 category - product - display_info 순으로 one-to-may 관계를 맺고있을 때, 만약category 가 10개, product 테이블의 데이터의 갯수가 10만개, display_info 의 테이블의 데이터가 100 만개일때,각각의 category 가 가지고있는 product 의 display_info 의 갯수를 확인하고 싶은 need 가 있으면,아래와 같이 entity 의 메서드를 통해 받아올수 있다는것을 이해를 했습니다. List<Category> categories = categoryRepository.findAll();List<CategoryResult> categoryResults = categories .stream() .map(category -> { //데이터 커지면 통계쿼리 처리가 좋을수도 있음. List<Product> products = category.getProducts(); int count = products .stream() .map(product -> product.getDisplayInfos().size()) .reduce(0, Integer::sum); return new CategoryResult(category.getId(), category.getName(), count); }) .collect(Collectors.toList());return categoryResults; 그런데 걱정이 되는것은 실제 데이터가 많으면 많아질수록 batch size 를 설정한다 하여도 가져올수 있는 양은 한정적이고결국 categorise 의 products 에 쌓인 데이터들로 인해 oom 이 발생할것 같은데 어떻게 처리를 하면 되나요??( 보통의 webpage 를 생각해보면 이렇게 많은 데이터를 가져올 일이없고 paging 을 이용할것 같긴 합니다. )제가 생각하기에는 아래의 2가지 정도 해결책이 있어보입니다.(1) one-to-many 의 관계를 사용하지 않고 명시적으로 fk 를 이용해서 repository 에서 find 를 호출 하는 방법.을 사용해 봤는데 이방법은 batch size 셋팅을 한다하여도 당연하겠지만 in query 로 sql 이 호출되지 않았습니다.당연히 속도도 현저히 늘려서 엄청난 시간이 걸렸습니다. ( 3분 -> 50분 )( ps. 아래의 코드에서도 inquery 셋팅하는 방법이 있을까요? ) List<Category> categories = categoryRepository.findAll();List<CategoryResult> categoryResults = categories.stream() .map(category -> { long categoryId = category.getId(); List<Product> products = productRepository.findAllByCategoryId(categoryId); int count = products .stream() .map(product -> { Long productId = product.getId(); List<DisplayInfo> displayInfos = displayInfoRepository.findAllByProductId(productId); return displayInfos.size(); }) .reduce(0, Integer::sum); return new CategoryResult(category.getId(), category.getName(), count); }) .collect(Collectors.toList()); (2) count query 를 설정하는 방법위의 needs 의 경우 통계쿼리처리를 하면 되겠지만, 만약 통계 쿼리로 처리하지못하는 로직이 있으면 어떻게 처리를 할수있을까요? 마지막 질문으로 위와 같이 oom 의 위험에도 불구하고 one-to-many 관계를 써야하나요??서비스에서의 가장큰 위험은 예상되지않은 에러라고 생각이 되는데 이경우 어떤 테이블이 어떻게 데이터가 많아질지 모르는 상황에서 위의 상황이 발생할수 있다고 생각이 됩니다.그럼에도 불구하고 성능적인 측면에서 one-to-many 를 쓰지않으면 성능이 너무나도 좋지않아서 고민입니다.긴글 읽어주셔서 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Result반환 관련해서 질문드립니다.
안녕하세요 강사님 질문들을 보다가 Result반환 타입을 명시해 주는게 좋다고 하셔서 Result를 Result<MemberDto> , Result<List<MemberDto>> 이 것 둘다 postman에서 결과는 똑같던데 왜그런지 알 수 있을까요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
REST API에 대한 질문이 있습니다
안녕하세요? 아직까지는 예제에서 데이터를 직접 리턴해주는 방식으로 하고있는데요, 여기서 로이 필딩이 말하는 Restful의 조건을 만족하려면 Self-Descriptive Messages와 HATEOAS를 만족해야 한다고 하는데 이 조건을들 만족하려면 결국 HttpEntity를 사용하여야 하는걸까요? RestTemplate로 작성된 코드를 보고 영한님의 HTTP 강의도 듣고나니 머릿속에서 퍼즐이 맞춰지는 느낌은 드는데 이게 맞는거다 라는 확신은 없어서 제가 제대로 이해하면서 진행하고 있는건지 궁금하여 질문드립니다. 그리고 강의 만족도가 매우 높습니다 ^^ 항상 감사하게 수강하고있습니다. 이대로 QueryDSL까지 열심히 달려서 실무에서 빨리 적용해보고 싶네요 ㅎㅎㅎ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
선생님! 세뇌당할 것 같습니다.
JPA는 인디렉션을 통해 사용하라고 이해하였습니다.. 꼭 DTO를 사용하겠습니다.. 절대 엔티티를 직접 사용하는 일은 없을것입니다.. ㅜㅜ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
뜬금없지만 시간타입에 대해 질문이 있습니다
안녕하세요? JPA에서 시간에 대해 매핑할때 제타위키에서는 Timestamp를 쓰라고 되어있는데 저는 자바8부터는 LocalDateTime을 사용하는걸 권장한다고 배웠거든요. 실제로 직접 매핑해보니 둘다 되긴되던데 영한님은 어떤 타입을 주로 추천하시는지 궁금합니다 !
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
fetchJoin 문의드립니다.
영한 스승님 안녕하세요!본 강의에서 작성하신 querydsl 코드에서요. 궁금한 점이 있습니다! fetchJoin 메서드 호출 없이 join 메서드만 호출할 경우' 주문 엔티티'가 가지고 있는 '멤버 엔티티'를 가져오기 위해 추가적인 쿼리가 호출되지 않을까요? 불필요하게 select 쿼리 내 join 절이 붙어서 나가는 것이 아닌가 궁금합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
repository 에서 findAll 의 return type에 관한 질문이 있습니다!
안녕하십니까 영한님. 우선 항상 좋은 강의에 감사드리며 새해복 많이 받으시길 바랍니다! 다름이 아니라 제가 영한님 수업때 강조받기를 파라미터를 통해서 엔티티를 받지말고 항상 스펙에 알맞는 DTO를 만들어서 받으라고 이해했습니다. 1. 그렇다면 스펙이 아주 조금 다르더라도 (멤버 변수 하나 차이 정도?) 매번 DTO(커맨드 객체라고 표현해도 맞을까요?)를 별도로 만들어서 데이터를 바인딩 시켜줘야 할까요? 2. 그리고 이건 Spring Data JPA 관련 부분이긴 하지만 JpaRepository<> 에서 기본으로 제공하는 findAll() 의 경우 return type이 List<T> 로 되어 해당 엔티티 타입의 리스트로 반환이 됩니다. 엔티티를 노출 시키지 말라고 강조를 받은 저로써 이 부분은 어떻게 되는건지 의문이 생겨서요. Spring Data JPA 의 경우 뭔가 다른건지 아니면 이 리스트를 다시 DTO를 통해 걸러야하는건지 의문이 생겨 질문 남기도록 하겠습니다!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
orderId 가 1000개가 넘어가는 경우에 대해 궁금합니다.
영한님 안녕하세요!orderId 가 1000개가 넘어가는 경우에 대해 궁금합니다.Mysql 기준 where in절에 올 수 있는 최대 개수가 1000개로 알고 있어서요. 이 경우 애플리케이션 코드에서 1000개를 파티션하고 나눠서 호출하는게 맞을까요?
- 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
jacksonfilter, 그리고 @valid 질문드립니다.
삭제된 글입니다
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
querydsl 이 안됩니다.ㅜㅜ
안녕하세요? 강사님!! 항상 강의 잘듣고 있습니다. 다름이 아니라, 제가 build.gradle 에서 querydsl 을 설정 하고 코끼리 모양 버튼 눌렀는데 계속 에러가 떠서 이렇게 질문 드립니다. 항상 좋은 강의 와 답변 감사드립니다 ^^ //querydsl 추가buildscript { dependencies { classpath("gradle.plugin.com.ewerk.gradle.plugins:querydslplugin:1.0.10") }}plugins { id 'org.springframework.boot' version '2.4.1' id 'io.spring.dependency-management' version '1.0.10.RELEASE' id 'java'}group = 'jpabook'version = '0.0.1-SNAPSHOT'sourceCompatibility = '11'//apply plugin: 'io.spring.dependency-management'apply plugin: "com.ewerk.gradle.plugins.querydsl"configurations { compileOnly { extendsFrom annotationProcessor }}repositories { mavenCentral()}dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-devtools' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation("org.junit.vintage:junit-vintage-engine") { exclude group: "org.hamcrest", module: "hamcrest-core" } //querydsl 추가 implementation 'com.querydsl:querydsl-jpa' //querydsl 추가 implementation 'com.querydsl:querydsl-apt'}test { useJUnitPlatform()}//querydsl 추가//def querydslDir = 'src/main/generated'def querydslDir = "$buildDir/generated/querydsl"querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir}sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } }}compileQuerydsl{ options.annotationProcessorPath = configurations.querydsl}configurations { querydsl.extendsFrom compileClasspath}//여기 밑에가 에러 내용입니다.....A problem occurred configuring root project 'jpashop'. > Could not resolve all artifacts for configuration ':classpath'. > Could not find gradle.plugin.com.ewerk.gradle.plugins:querydslplugin:1.0.10. Searched in the following locations: - https://plugins.gradle.org/m2/gradle/plugin/com/ewerk/gradle/plugins/querydslplugin/1.0.10/querydslplugin-1.0.10.pom If the artifact you are trying to retrieve can be found in the repository but without metadata in 'Maven POM' format, you need to adjust the 'metadataSources { ... }' of the repository declaration. Required by: project : Possible solution: - Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
지연로딩과 영속성전이
안녕하세요 영한님. 강의를 듣다가 궁금증이 생겨 질문 남깁니다. 가정하는 상황은 다음과 같습니다. 부모(Team) <----> 자식(Member) 양방향 연관관계를 갖고, 부모에서 @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.All) 입니다. Team은 이미 생성되있고, 새로운 멤버를 추가하는 경우, Team team = em.find(Team.Class, teamid); Member member = new Member(); member.set(team); team.getMemberList().add(member); //질문1. 이때 team에 변경감지가 일어나 em.flush(team) 이 실행되는지 궁금합니다. 질문2. 새로운 member만 add되고 변경감지->영속성전이 가 되는건지, 혹은 기존 member들도 select해오는건지 잘 모르겠습니다!! * 통합적으로.. Cart와 CartItem 같은 엔티티의 경우, 저의 입장은 Cart가 CartItem에 대한 책임과 역할을 갖는 객체로 수정,삭제 등을 관리하고 싶은데, 이때 Cart가 연관관계의 주인이 아니므로 영속성 전이와 고아객체 옵션을 사용하고자 하는 것입니다. 이게 옳은 방향인지 잘 모르곘습니다. ㅠㅠ 감사합니다.