이야기를 나눠요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
spring-boot 2.7 이상을 사용 하시는 분의 경우
안녕하세요. 강사님께서는 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; } */ }
-
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
junit5에서는 @Test 에노테이션에서 expected를 지원하지 않는 것 같습니다.
Assertions.assertThrows(IllegalStateException.class, () -> { memberService.join(m2); // Exception 터져야 돼. }); 혹시 junit5 쓰시는 분들은 위와 같이 수정하여서 돌려도 괜찮은 것 같습니다.
-
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
강사님 따로 멘토링은 안하시는지요?
인프런에도 멘토링 서비스가 있는데, 멘토링은 따로 안하시나요?
-
자바 ORM 표준 JPA 프로그래밍 - 기본편
하이버네이트 완벽 가이드 책 질문입니다.
영한님 강의, 책들을 보면서 더 깊게 공부해보고 싶다는 열정, 관심이 불타오르게 되었습니다!갑자기 개빈 킹이 쓴 책인 "하이버네이트 완벽 가이드에는 무슨 내용이 있을까?"라는 생각과 함께 도전해보려고 고민하고 있는데 강사님의 의견이 궁금합니다 ㅎㅎ (자바 ORM 표준 JPA 프로그래밍 책의 저자이시고 자료가 없었던 시절에 밑바닥부터 공부하셨던 분이셔서 의견이 궁금합니다.)2010년에 나온 책이라서 현재와 맞지 않는 내용도 있겠지만, 하이버네이트 개발자가 쓴 책이면 JPA, 하이버네이트를 깊게 이해할 수 있지 않을까?라는 호기심이 생겼습니다.더 나아가서 로드 존슨이 쓴 책들 중에서 유일한 번역본인 "expert one-on-one J2EE 설계와 개발"도 파헤치고 싶네요.
-
호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
User 테이블 바로 생성 안 되시는 분들 테이블명 바꿔서 하시면 됩니당.
H2 데이터베이스 2버전부터 User가 예약어가 된 것 같습니다.User로 바로 테이블 생성이 안 되시는 분들은 클래스 이름을 User가 아닌 다른 것으로 하시거나 @Table(name = "Users") 이런 식으로 테이블명을 바꾸시면 잘 됩니다.
-
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
Spring Security 관련된 내용도 다뤄 주셨으면 해요~!
기술 면접이나 면접 과제 중 인증, 인가 또는 사용자 정보 암호화(jwt) 관련된 과제들도 많이 출제가 되더라구요프로젝트 진행하면서 회원가입, 로그인 구현 시 코드를 끌어다 사용해 구현은 했었지만 사실 너무 복잡하고 어려워서 사실 그 부분에 대한 질문이 들어오면 입도 못 뗄 것 같아요...보안 관련 시리즈도 기대 해봅니다!!영한 튜터님 강의 보면서 정말 즐겁게 공부하고 있어요:)
-
실전! Querydsl
QueryDsl SpringBoot 2.7의 gradle 설정을 공유합니다.
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 -> cleanGradle -> 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 으로 빼버리는 거 만들어주지 않을까 하는 기대가 있긴 합니다.
-
실전! 스프링 데이터 JPA
연관관계가 있는 Entity 저장
안녕하세요. 강의를 듣고 공부하는 중, 연관관계가 있는 Entity를 저장할 때 궁금한 부분이 있어 질문드립니다. 아래의 예제의 User에는 컬럼에 연관관계가 있는 UserType 엔티티가 있고,화면에서는 typeCode값(UserType의 키값)과 userName값을 Dto로 전달받아서 저장을 하고있습니다. User를 save할 때에 UserType을 조회 후 생성자로 객체를 만들고 save를 했었는데, 이렇게 하다보니 select insert 2개의 쿼리가 실행되더라구요.(userTypeRepository.findById 후 save) 그래서 방법을 찾다보니 findById 대신에 getById로 UserType을 조회후 save하면,UserType select가 Lazy로 동작하여 insert 쿼리만 실행이 되는걸 확인했습니다. (CASE1.) 또 다른방법으로 User 엔티티에 UserType의 키값인 typeCode를 추가하고,dto에서 받은 typeCode로 User객체를 만들어 저장하는 방법도 있더라구요. (CASE2.) JPA를 사용하면서 save시 getById로 호출후 save하는 방식이 맞는건지,실무에서는 어떠한 방식으로 사용되는지 궁금하여 질문드립니다. -------------------------- CASE 1. @Entity @Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class User { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToOne @JoinColumn(name = "TYPE_CODE") private UserType userType; @Column(name = "USER_NAME") private String userName; public User(UserType userType, String userName) { this.userType = userType; this.userName = userName; } } @Entity@Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class UserType { @Id @Column(name = "TYPE_CODE") private String typeCode; @Column(name = "TYPE_NAME") private String typeName;} @Getter@Setterpublic class UserFormDto { private String typeCode; private String userName; public User toEntity(UserType userType) { return new User(userType, userName); } } @Service...@Transactionalpublic void createUser(UserFormDto userFormdto) { UserType userType = userTypeRepository.getById(userFormdto.getTypeCode()); User user = userFormdto.toEntity(userType); userRepository.save(user);} --------------------- CASE 2. @Entity @Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class User { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToOne @JoinColumn(name = "TYPE_CODE") private UserType userType; @Column(name = "TYPE_CODE") private String typeCode; @Column(name = "USER_NAME") private String userName; public User(String typeCode, String userName) { this.typeCode = typeCode; this.userName = userName; } } @Entity @Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class UserType { @Id @Column(name = "TYPE_CODE") private String typeCode; @Column(name = "TYPE_NAME") private String typeName;} @Getter@Setterpublic class UserFormDto { private String typeCode; private String userName; public User toEntity() { return new User(typeCode, userName); } } @Service...@Transactionalpublic void createUser(UserFormDto userFormdto) { User user = userFormdto.toEntity(); userRepository.save(user);}
-
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
나름의 페이징 처리를 만들어봤습니다
안녕하세요 초보개발자 명아주입니다. 배치를 사용하지 않고, 직접 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 - 웹 애플리케이션 개발
MVC강의랑 JPA기본편이랑 병행하는건 어떨까요?
안녕하세요 현재 영한님 스프링 강의를 듣고 있습니다. 우선 좋은강의만들어주셔서 감사합니다. 제가 지금 야생형으로 해서 JPA 활용1편을 거의 다들었고 JPA기본편을 들을 차례인데요, 개발바닥 이벤트로 영한님의 모든 강의를 구매해놓은 상태입니다. 그래서 문득 JPA강의를들으면서 MVC강의도 같이 들으면 좀더 이해가 잘 될까? 아니면 기존 야생형코스를 다듣고 MVC를 추가로 듣는게 나을까? 고민이 되더라구요 JPA활용1편을 무작정 들어보면서 흥미가 더 올랐고 모르는부분은 제가 찾아가면서 해보니 가면갈수록 내공이쌓여서?? 이해가 잘 되고 있습니다.ㅎㅎ 1월중순부터 지인들이랑 프로젝트를 하나 해보기로한 상황이기도하고.. 궁금해서 여쭤봅니다!
-
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
마이바티스랑 이별 준비중....
강의 정말 잘 봤습니다. 쉽게 잘 설명해 주셔서 감사합니다. JPA 강의도 김영환님꺼 예전에 들었는데 다시금 들어보고 추천 로드맵을 밞아보려 합니다. 저도 육아대디라 시간이 잘 안나지만 틈틈히 열심히 듣겠습니다. 좋은 강의 정말 감사합니다.
-
스프링 핵심 원리 - 기본편
다음강의 조금 궁금합니당!!
지금 혹시 JPA를 CRUD정도는 알고 있는 정도인데 미니프로젝트를 하다가 보니까 http와 mvc에서 많이 지식이 필요 할거 같아서 JPA말고 http와 mvc를 먼저 수강할라고 하는데 혹시 수강하는 데 문제가 있을지 궁금합니다 갓영한님:)
-
실전! Querydsl
질문있습니다. Jpa와 Mongo QueryDSL 같이 설정하는 법
현재 프로젝트를 진행하면서 한 프로젝트에 JPA(RDB:mysql), Mongo(Mongo)를 같이 쓰고 있는 중입니다. 다름이 아니라 Mongo도 QueryDSL이 있는 것을 파악하고 pom.xml에 build될 때 @Document가 있는 클래스도 Q클래스가 생성될 수 있도록 하려고 합니다. <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>${querydsl.version}</version></dependency><dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-mongodb</artifactId> <version>${querydsl.version}</version></dependency><dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>${querydsl.version}</version> <scope>provided</scope> <exclusions> <exclusion> <artifactId>javassist</artifactId> <groupId>org.javassist</groupId> </exclusion> </exclusions></dependency> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processors> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor> </processors> </configuration> </execution> </executions></plugin> 이렇게 하니 maven clean & compile을 수행하니, error: Attempt to recreate a file for type 들이 쭉 뜨고, error: cannot find symbol Q클래스들을 찾을 수 없다고 쭉 뜹니다. 그리고서 Q클래스가 제대로 생성되지 않은채로 빌드가 끝납니다. 혹시 Jpa QueryDSL, Mongo QueryDSL을 함께 쓰시는 법을 아시나요?