선생님 덕분에 좋은 회사에 취업해서 업무를 배우고있습니다~ 회사 입사 이후에도 퇴근 후 선생님의 좋은 강의를 계속 듣고 싶어서 문의드려요. 수강평에 3월쯤 오픈 예정이라고 답글 달려있는걸 보았는데 3월달에 다음강좌 오픈 확정인가요? 제가 선생님의 수업을 모두 들었지만 본의 아니게 Frontend로 가게되어 다음강의에 있는 React 부분이 너무 궁금해서 문의 남깁니다~~ 항상 감사합니다!
안녕하세요 항상 강의 잘 보고 있습니다. 다름이 아니라 영한님의 jpa강의를 토대로 제가 하는 토이프로젝트에 적용하는 과정에서 궁금한 점 몇가지가 생겨서 질문드립니다. application.yaml파일에서 ddl-auto: create-drop으로 했을때 콘솔창에서는 해당 테이블이 없다면서 자꾸 오류가 났었습니다(콘솔에서는 오류가 나오나 DB상으로는 적절하게 테이블이 생성되었음). 그러나 먼저 ddl-auto: create로 해당 테이블들은 생성해놓고 그 다음 update를 하니 오류없이 동작했습니다. 강의를 들을때는 그러지 않았던것 같았는데 원래 이런건가요? 영한님께서 강의 도중 다대다 관계는 1대다, 다대1 관계로 풀어서 진행하라고 하셨던 기억이 납니다. 그렇게 하는 이유에 대해서는 이해를 하였습니다. 저는 기존의 관계형 데이터 베이스에서는 기존의 다대다 관계를 이루고 있던 테이블들의 pk를 가져와서 새로운 테이블에 FK로 넣었고 이러한 두개의 FK를 묶어서 하나의 PK로 만들었습니다. 그러나 강의에서는 기존의 테이블들을 이어주는 테이블에 FK로 넣어주기는 하였으나 아예 새로운 PK를 만들어서 강의를 진행하시던 기억이 납니다. 여기서 제가 궁금한 점은 기존에 제가 했던 방식대로 하려면 @Embedable으로 복합키를 만들어서 진행을 해야할까요? 아니면 기존 하던 방식 말고 새로운 PK를 만들어서 진행하는 방식이 훨씬 깔끔할까요? 제가 진행하는 토이프로젝트의 환경은 aws ec2를 사용하고 있으면 DB는 mariadb를 사용하고 있습니다. 자바 버전은 17입니다.
안녕하세요. 강사님께서는 2.6 버전을 사용 권장 하셨지만 왠지 모를 궁금함에 2.7에서 사용하는 spring security 5.7 이상에서 바뀐 부분으로 한번 적용을 해보고 싶었습니다. 인프런에 올라온 많은 분들의 질문을 정리 하여 만들어 보았습니다. package com.example.userservice.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import com.example.userservice.service.UserService; import lombok.RequiredArgsConstructor; @Configuration @EnableWebSecurity @RequiredArgsConstructor public class WebSecurity { private final UserService userService; private final BCryptPasswordEncoder bCryptPasswordEncoder; private final Environment env; AuthenticationManager authenticationManager; // spring.boot 2.7 부터는 WebSecurityConfigurerAdapter가 아닌 // SecurityFilterChain 을 사용 합니다. @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); authenticationManagerBuilder.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder); authenticationManager = authenticationManagerBuilder.build(); //AuthenticationFilter authenticationFilter = new AuthenticationFilter(); //authenticationFilter.setAuthenticationManager(authenticationManager); AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager , userService , env); http.csrf().disable(); http.authorizeRequests() //.antMatchers("/error/**").permitAll() // public abstract java.lang.String javax.servlet.ServletRequest.getRemoteAddr() is not supported 보기 싫을때 활성화 .antMatchers("/**") .hasIpAddress("127.0.0.1") .and() .authenticationManager(authenticationManager) .addFilter(authenticationFilter) ; http.headers().frameOptions().disable(); return http.build(); } //ex) 기존의 경우 AuthenticationManagerBuilder 를 오버라이드 하여 사용 하였지만 filterChain 안에서 호출 하여 설정 합니다. /* protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder); } */ //ex)filter를 authenticationAmanger에 주입 하던 getAuthenticationFilter역시 filterChain 내부에서 사용 합니다. /* private AuthenticationFilter getAuthenticationFilter() throws Exception { AuthenticationFilter authenticationFilter = new AuthenticationFilter(); authenticationFilter.setAuthenticationManager(authenticationManager); return authenticationFilter; } */ }
영한님 강의, 책들을 보면서 더 깊게 공부해보고 싶다는 열정, 관심이 불타오르게 되었습니다! 갑자기 개빈 킹이 쓴 책인 "하이버네이트 완벽 가이드에는 무슨 내용이 있을까?"라는 생각과 함께 도전해보려고 고민하고 있는데 강사님의 의견이 궁금합니다 ㅎㅎ (자바 ORM 표준 JPA 프로그래밍 책의 저자이시고 자료가 없었던 시절에 밑바닥부터 공부하셨던 분이셔서 의견이 궁금합니다.) 2010년에 나온 책이라서 현재와 맞지 않는 내용도 있겠지만, 하이버네이트 개발자가 쓴 책이면 JPA, 하이버네이트를 깊게 이해할 수 있지 않을까?라는 호기심이 생겼습니다. 더 나아가서 로드 존슨이 쓴 책들 중에서 유일한 번역본인 "expert one-on-one J2EE 설계와 개발"도 파헤치고 싶네요.
기술 면접이나 면접 과제 중 인증, 인가 또는 사용자 정보 암호화(jwt) 관련된 과제들도 많이 출제가 되더라구요 프로젝트 진행하면서 회원가입, 로그인 구현 시 코드를 끌어다 사용해 구현은 했었지만 사실 너무 복잡하고 어려워서 사실 그 부분에 대한 질문이 들어오면 입도 못 뗄 것 같아요... 보안 관련 시리즈도 기대 해봅니다!! 영한 튜터님 강의 보면서 정말 즐겁게 공부하고 있어요:)
plugins { id 'org.springframework.boot' version '2.7.4' id 'io.spring.dependency-management' version '1.0.14.RELEASE' id 'java' } group = 'study' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' // queryDSL 설정 implementation "com.querydsl:querydsl-jpa" implementation "com.querydsl:querydsl-core" implementation "com.querydsl:querydsl-collections" annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정 annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드 annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드 } tasks.named('test') { useJUnitPlatform() } // Querydsl 설정부 def generated = 'src/main/generated' // querydsl QClass 파일 생성 위치를 지정 tasks.withType(JavaCompile) { options.getGeneratedSourceOutputDirectory().set(file(generated)) } // java source set 에 querydsl QClass 위치 추가 sourceSets { main.java.srcDirs += [ generated ] } // gradle clean 시에 QClass 디렉토리 삭제 clean { delete file(generated) } 해당 소스는 타사 강의 보다가 본 설정에서 가져왔습니다. 기존 영한님 강의와 다른 점이 3가지 있으니 주의하시기 바랍니다. Querydsl Q파일 생성 위치가 다릅니다. 기존 영한님 강의대로 $build 로 시작하는 설정을 사용하면 테스트 실행 시 Q파일의 위치를 찾지 못해서 테스트가 실패합니다. Gradle -> Tasks -> build -> clean Gradle -> Tasks -> build -> build 혹은 classes 기존 영한님 교안에는 빌드 시 Gradle -> Tasks -> other -> compileQuerydsl 로 Q파일을 생성하지만, 이 방법의 경우 other에 해당 메뉴가 없습니다. 그래서 빌드 시에는 그냥 build 메뉴의 build 혹은 classes 로 빌드하시면 Q파일이 생깁니다. 영한님 강의에서는 gradle build 폴더가 대부분 git 버전관리에 포함되지 않으므로 따로 설정할 필요가 없지만, 이 경우 Q파일이 소스폴더에 들어가므로 .gitignore 에 아래와 같이 별도로 경로를 설정해 주어야 합니다. ### Querydsl /src/main/generated 혹시 저같이 청개구리마냥 강의에 나온 버전 사용 안 하고 최신 버전 사용하시는 분들께 도움이 되었으면 좋겠습니다. 저도 타사 강의에서 가져온 것이고 기초 테스트만 통과한 것이라서 혹시 강의에 맞지 않는 경우 영한님이나 다른 분들이 추가 정보를 주시면 좋을 것 같습니다. 여담인데 QueryDSL은 쿼리 짜긴 확실히 편한데 설정이 버전마다 중구난방이라 불편합니다. 똑똑한 개발자분들이 이런 설정도 그냥 @Configuration 으로 빼버리는 거 만들어주지 않을까 하는 기대가 있긴 합니다.
안녕하세요 초보개발자 명아주입니다. 배치를 사용하지 않고, 직접 IN 쿼리를 만들어주게 한번 해봤습니다. 이렇게 하면 실제 쿼리가 2번 나가게 됩니다. 조금더 복잡하긴 하지만, jpa 를 잘 모르는 사람이 보기엔 이해하기 더 좋지 않을까 싶습니다. 단점은 2번째 쿼리가 좀 크게 나가는 점과 distinct 문제, 배치 사이즈의 한계같은 부분이 없다는 것이라고 생각합니다. public List<Order> findAllWithPaging(int offset, int limit) { List<Long> ids = em.createQuery("select o.id from Order o", Long.class) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); return em.createQuery(""" select distinct o from Order o join fetch o.member join fetch o.delivery join fetch o.orderItems oi join fetch oi.item where o.id in :ids """, Order.class) .setParameter("ids", ids) .getResultList(); }
안녕하세요 현재 영한님 스프링 강의를 듣고 있습니다. 우선 좋은강의만들어주셔서 감사합니다. 제가 지금 야생형으로 해서 JPA 활용1편을 거의 다들었고 JPA기본편을 들을 차례인데요, 개발바닥 이벤트로 영한님의 모든 강의를 구매해놓은 상태입니다. 그래서 문득 JPA강의를들으면서 MVC강의도 같이 들으면 좀더 이해가 잘 될까? 아니면 기존 야생형코스를 다듣고 MVC를 추가로 듣는게 나을까? 고민이 되더라구요 JPA활용1편을 무작정 들어보면서 흥미가 더 올랐고 모르는부분은 제가 찾아가면서 해보니 가면갈수록 내공이쌓여서?? 이해가 잘 되고 있습니다.ㅎㅎ 1월중순부터 지인들이랑 프로젝트를 하나 해보기로한 상황이기도하고.. 궁금해서 여쭤봅니다!