학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 강의 9:12 쯤 부분을 실습하다가 JUnit4와 5를 설치와 삭제를 반복하다가 실수로 test 디렉토리를 지워버렸습니다. 그러니까 그 다음 단계에서 어노테이션이 다 빨간색으로 인식이 안되는데 test 디렉토리 지웠을 때 어떻게 복구하면 되는지 궁금합니다. 답변 부탁드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 실행 버튼이 생기지 않는데, 어떻게 해야할까여 ? ㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. null값이 들어올때의 오류를 방지하기 위해 optional로 감싸준다고 하셨는데 왜 List<Member> findAll();에서는 Optional로 감싸주지 않는건가요?
JPA에서 컬렉션 조회와 페이징을 함께 사용하려면 ToOne (OneToMany, OneToOne) 관계를 모두 페치 조인하고, 지연 로딩 성능 최적화를 위해 hibernate.default_batch_fetch_size 옵션을 적용해야 한다. 라고 배웠었는데 이 내용이 Spring Data JPA에서도 컬렉션을 조회하면서 페이징 관련된 Pageable, Page 등을 사용하기 위해서는 default_batch_fetch_size 를 적용해줘야 하는 거죠??
좋은 강의 잘 보고 있습니다. 감사합니다. 섹션 5. "실전프로젝트 - 인가 프로세스 DB 연동 웹 계층 구현"의 "6) 웹 기반 인가처리 실시간 반영하기" 강의를 보다 의문이 생겨 질문을 남기게 되었습니다. UrlSecurityMetadataSource 클래스에 다음과 같은 reload() 함수가 있습니다. 여기서 "securityResourceService.getResourceList()"의 반환값과 "requestMap"의 타입이 똑같으니 requestMap = securityResourceService.getResourceList(); 으로 바로 객체를 할당하면 될 것 같았는데, Iterator를 사용하여 put 하시는 것이 성능상의 문제나 다른 이슈가 있어서 이렇게 작성을 하신건지 의문이 들었습니다. 새로운 List를 바로 할당하지 않고, 기존 List 객체를 유지하신 이유가 궁금합니다! 감사합니다. // UrlSecurityMetadataSource 클래스 public void reload() { LinkedHashMap<RequestMatcher, List<ConfigAttribute>> reloadedMap = securityResourceService.getResourceList(); Iterator<Map.Entry<RequestMatcher, List<ConfigAttribute>>> iterator = reloadedMap.entrySet().iterator(); requestMap.clear(); while (iterator.hasNext()) { Map.Entry<RequestMatcher, List<ConfigAttribute>> entry = iterator.next(); requestMap.put(entry.getKey(), entry.getValue()); } }
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] plugins { id 'org.springframework.boot' version '2.6.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' ext["hibernate.version"] = " 5.6.5.Final " configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'javax.validation:validation-api' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' //JdbcTemplate 추가 //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //MyBatis 추가 implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0' //JPA, 스프링 데이터 JPA 추가 implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:$ { dependencyManagement.importedProperties['querydsl.version'] } :jpa" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" //H2 데이터베이스 추가 runtimeOnly 'com.h2database:h2' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() } //querydsl 추가 //def querydslDir = '$buildDir/generated' def querydslDir = "src/main/generated" //clean { // delete file(generated) //} 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 } 강사님이 올려주신 내용 + 구글링 + 직접 수정했습니다. 간혹, 빌드는 되는데 generated 파일에 QClass 안보이시는 분들은 queryDsl 저장되는 경로에 $buildDir 대신 'src/main/'으로 해보세요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예 예 예 [질문 내용] 여기에 질문 내용을 남겨주세요. 3가지 오류가 있다는데 하란대로 했는데 왜 안되는지 모르겠어요. 시작부터 난관이라 너무 스트레스받네요.. C:\Program Files\spirngboot\pulsar-spring\.gradle\7.6.1\fileChanges\last-build.bin (지정된 경로를 찾을 수 없습니다) Failed to create parent directory 'C:\Program Files\spirngboot\pulsar-spring\.gradle' when creating directory 'C:\Program Files\spirngboot\pulsar-spring\.gradle\vcs-1' Could not update C:\Program Files\spirngboot\pulsar-spring\.gradle\7.6.1\fileChanges\last-build.bin 이렇게 세가지가 나옵니다. 어떻게 해야할까요.
재기동을 했음에도 불구하고 쿠키값이 그대로 남아있는 현상이 있어서 원하는 요청이 정상적으로 이루어지지 않았던 문제가 있었습니다. 이상해서 원인을 파악하다보니 현재 전 mysql DB 를 연결하여 사용중이었고, 호돌맨님은 H2 DB 를 사용중이시더라구요. 그래서 재기동을 할때마다 쿠키값이 삭제되고 다시 생성이 되지 않았던 건데 혹시 이런 상황에서 조언이 될 만한 링크나 키워드를 알려주실 수 있으실까요?? 제가 직접 삽질하면서 찾아보고 해결해보려구요 ㅠㅠ (현재는 매번 재기동 할때마다 쿠키값을 직접 삭제해주면서 강의를 따라가고 있습니다)
단건 조회는 결과가 없을 경우 예외 발생 대신 null을 반환한다고 하였는데 이 null을 어떤 방식으로 처리하는게 좋은 방법인가 싶어 질문 드립니다. 질문 드리고 싶은 방법은 아래와 같이 2가지입니다. 둘 중 어느 방식을 사용하는게 더 좋을까요? if문을 통해 null일 시에 런타임 예외 터트리기 Member member = memberRepository.findById(10L) if (member == null) { throw new CustomException("찾고자 하는 멤버가 없습니다."); } 반환 타입을 Optional로 감싸 반환하기. Optional<Member> member = memberRepository.findById(10L).orElseThrow(() -> new CustomException("찾고자 하는 멤버가 없습니다."));
※※※※※ 해결완료 ※※※※※ mvc.perform()의 get이나 post 같은 매서드 타입을 스태틱임포트 해야하는데 이 때 선택지가 3개 있습니다. 이 중 MockMvcRequestBuilders의 post()를 임포트 하니까 해결이 됐습니다. RequestBuilder로 캐스팅을 해주지 않아도 되구요 그리고, 이래저래 해보면서 MockMvc 말고도 MockMvcBuilder 객체를 이용해서 build().perform()으로 시작해 똑같이 코드를 작성하면 테스트가 정상적으로 실행됩니다! ※※※※※ 해결완료 ※※※※※ SecurityConfig 테스트 강의에도 질문을 드렸는데.. 답이 없길래 그냥 넘어갔는데 여기서도 쓰여 다시 질문드립니다. MockMvc를 이용해서 테스트를 진행할 때, @Test @DisplayName("회원가입 테스트") void join_test() throws Exception { // given JoinRequestDto joinRequestDto = JoinRequestDto.builder() .username("minsu") .password("1234") .email("minsu@gmail.com") .fullname("김민수") .build(); String requestBody = objectMapper.writeValueAsString(joinRequestDto); System.out.println("requestBody = " + requestBody); // when ResultActions resultActions = mvc.perform((RequestBuilder) post("/api/join").content(requestBody).contentType(MediaType.APPLICATION_JSON)); // then } 위 부분에서 문제가 생기는 부분은 아래 코드인데요 // when ResultActions resultActions = mvc.perform((RequestBuilder) post("/api/join").content(requestBody).contentType(MediaType.APPLICATION_JSON)); 먼저 content를 설정할 수 있는 api?가 없고요. 해당 구문을 RequestBuilder로 캐스팅해야 빨간줄이 사라집니다. 그러니까 perform()이 파라미터로 RequestBuilder를 받게 돼있습니다. gradle은 아래와 같습니다. plugins { id 'java' id 'org.springframework.boot' version '2.7.12' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'io.com' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.auth0:java-jwt:4.2.1' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } 그리고 테스트쪽 라이브러리는 아래와 같습니다. Gradle: org.junit.jupiter:junit-jupiter:5.8.2 Gradle: org.junit.jupiter:junit-jupiter-api:5.8.2 Gradle: org.junit.jupiter:junit-jupiter-engine:5.8.2 Gradle: org.junit.jupiter:junit-jupiter-params:5.8.2 Gradle: org.junit.platform:junit-platform-commons:1.8.2 Gradle: org.junit.platform:junit-platform-engine:1.8.2 Gradle: org.mockito:mockito-core:4.5.1 Gradle: org.mockito:mockito-junit-jupiter:4.5.1
아래와 같이 최대 허용 가능 세션 수를 설정하고, 테스트 해보려고 했는데 /invalid 나 /expired 페이지로 이동하지 않고 /login 페이지로 이동하는데 뭐가 문제인지 모르겠습니다. http .sessionManagement() .invalidSessionUrl("/invalid") .maximumSessions(1) .maxSessionsPreventsLogin(true) // false도 테스트 해봄 .expiredUrl("/expired");
주문 서비스 개발 부분 강의를 듣다가 궁금한 점이 있어 질문드립니다. 주문 취소(OrderService.cancelOrder) 부분에서order.cancel() 만 작성하면 JPA 특징으로 인해, 데이터 업데이트 관련 쿼리 로직 없이 자동으로 업데이트 된다고 하셨는데요. 주문 생성(OrderService.order)의 EntityManager 가 사용된 orderRepository.save (order); 와 혼동이 와서 질문 남깁니다. 주문 취소 order.cancel() 메서드를 타면서 엔티티의 값(status, count 등) 변경 내역이 자동으로 업데이트 되는 것이라고 하면, 주문 생성도 Order.createOrder(member, delivery, orderItem); 를 타면서 엔티티의 값들을 설정하기 때문에 orderRepository.save (order); 를 사용하지 않아도 되는게 아닌가 라는 생각이 듭니다. 제가 JPA 를 잘 몰라서 혼란이 오는 것 같은데.. 쿼리는 직접 작성하지 않아도 업데이트/저장/삭제 등 DB 조작이 일어나려면 EntityManager 를 통해야 된다고 생각하고 있었습니다. 주문 취소는 EntityManager 없이 업데이트 되고, 주문 생성은 EntityManager의 persist() 를 사용해서 저장하는 것 이 2가지 차이점에 대해서 설명 부탁드립니다! 감사합니다 :)
@RequiredArgsConstructor @RestControllerpublic class MemberController { private final MemberRepository memberRepository; @GetMapping("/members/{id}") public String findMember(@PathVariable("id") Long id) { Member member = memberRepository.findById(id).get(); return member.getUsername(); } public void init() { memberRepository.save(new Member("userA")); } 2023-06-17T14:29:55.066+09:00 DEBUG 6856 --- [nio-8080-exec-1] org.hibernate.SQL : select m1_0.member_id, m1_0.age, m1_0.created_by, m1_0.created_date, m1_0.last_modified_by, m1_0.last_modified_date, m1_0.team_id, m1_0.username from member m1_0 where m1_0.member_id=? 2023-06-17T14:29:55.068+09:00 INFO 6856 --- [nio-8080-exec-1] p6spy : #1686979795068 | took 0ms | statement | connection 4| url jdbc:h2:tcp://localhost/~/datajpa select m1_0.member_id,m1_0.age,m1_0.created_by,m1_0.created_date,m1_0.last_modified_by,m1_0.last_modified_date,m1_0.team_id,m1_0.username from member m1_0 where m1_0.member_id=? select m1_0.member_id,m1_0.age,m1_0.created_by,m1_0.created_date,m1_0.last_modified_by,m1_0.last_modified_date,m1_0.team_id,m1_0.username from member m1_0 where m1_0.member_id=1; 2023-06-17T14:29:55.071+09:00 INFO 6856 --- [nio-8080-exec-1] p6spy : #1686979795071 | took 0ms | commit | connection 4| url jdbc:h2:tcp://localhost/~/datajpa ; 2023-06-17T14:29:55.074+09:00 ERROR 6856 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.util.NoSuchElementException: No value present] with root cause java.util.NoSuchElementException: No value present at java.base/java.util.Optional.get(Optional.java:143) ~[na:na] at study.datajpa.constoller.MemberController.findMember(MemberController.java:18) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.9.jar:6.0.9] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.9.jar:6.0.9] http://localhost:8080/members/1 에 userA가 나와야 하는데 Whitelabel Error Page가 뜨고 위와 같은 오류가 나옵니다.
9:20초 쯤에 이전에 발급된 토큰이 있다고 말씀해주셨는데 이전이라는게 언제를 말씀하시는건가요 ? 서버를 재가동시키고 아무것도 안하고 지금 요청만 보냈을뿐인데 어떻게 갑자기 CSRF관련 토큰이 있는건가요?? 저는 강의 똑같이 따라했는데 csrfToken값이 null이나옵니다.
질문1 커넥션을 많이 사용하지 않는 경우 OSIV를 키고, 실시간 요청이 많은 경우는 OSIV를 끈다고 했는데 OSIV를 끄는 경우가 스트리밍 서비스나, 채팅 기능에 해당할가요 ?? 질문2 질문1의 내용이 맞다면 만약 프로젝트에 게시판, 작성자와 1:1 채팅 기능이 있다면, 게시판은 OSIV를 키고, 채팅 기능을 담고 있는 로직들에만 별도로 OSIV를 끄는 옵션이 따로 있나요?? 아니면 제가 멀티 모듈을 사용한적이 없어 자세히는 모르지만 멀티 모듈을 사용해서 각 기능들을 모듈화해서 따로 옵션을 설정하는건가요??
안녕하세요 강의 정말 잘 듣고있습니다. 해당 챕터의 마지막 강의인 "API 개발 고급 정리" 영상에서 엔티티 조회 방식과 DTO 직접 조회 방식 중 어떤 것을 더 권장하는지에 대해 설명해주시는 부분에 대해 질문이 생겼습니다. 저는 아무래도 DTO 조회 방식은 쿼리문도 까다롭고 DTO를 추가로 만들어야 하기 때문에 우선 손이 잘 안가는 느낌이있었던 반면에, 엔티티 조회는 쿼리가 더 단순하고 배치사이즈 옵션으로 쉽게 페이징도 적용할 수 있어서 좀 더 다가오긴했습니다. 두 방식에 대한 차이와 장단점을 듣고나서는 네트워크 성능과 컴퓨터 성능이 워낙 좋아져서 엔티티 조회 방식으로 접근해도 거의 충분하다라고 이해를 했는데요. 강의를 만드신 시기가 몇년 전인만큼 현재는 시간이 흘러 네트워크 성능과 컴퓨터 성능이 더 발전했는데 지금은 엔티티 조회하는 방식만으로 컬렉션 조회하는데 성능 문제가 없을까요?