Gradle, Java, Springboot 버전 업그레이드
Gradle Version upgrade
6.6.1 → 6.8.3 → 7.2 → 8.6
SpringBoot version upgrade
2.3.4 → 2.7.7 → 3.0
Java version upgrade
8 → 17
java {
sourceCompatibility = '17'
}
주요 변경 사항
Javax.servlet.http → Jakarta.servlet.http
- javax → jakarta 패키지 변경
- jakarta.servlet.http 내부 클래스들
- HttpServletRequest, HttpSession, HttpServletResponse
- jakarta.persistence 의 어노테이션들
- @Table, @Entity, Column, @Id, @GeneratedValue 등 … Entity 작성에 쓰이는 다수의 어노테이션들
- jakarta.transaction
- Transactional
- jakarta.ServletException
- jakarta.annotation.PostConstruct
- jakarta.servlet.http 내부 클래스들
- RememberMe 기능 구현 중 관련 Intercepter가 클래스 `HandlerInterceptorAdapter` 를 상속하는 방식 → 인터페이스인 `HandlerInterceptor` 를 구현하는 방식으로 변경
Spring Security
`WebSecurityConfigurerAdapter` 가 Springboot 2.7.x 부터는 deprecated되고, 3.x부터는 사라지기 때문에 2.7.7버전인 상태에서 해당 코드들을 리팩토링해준다.
- 공통 사항
- `antMatchers()` → `requestMachers()` 로 변경
- `HttpSecurity`의 아래 메서드들은 모두 deprecated(추후에 수정 필요)
- `httpBasic()`, `formLogin()`, `sessionManagement()`, `logout()`, `rememberMe()`
- HttpSecurity 관련
`void configure(HttpSecurity httpSecurity)` 메서드 → `SecurityFilterChain filterChain` 메서드로 변경
@override
public void configure(HttpSecurity http) throws Exception {
...
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
...
}
1. WebSecurity 관련
`void configure(WebSecurity webSecurity)` → `WebSecurityCustomizer webSecurityCustomizer()`
💡 Cf. WebSecurity와 HttpSecurity의 차이 WebSecurity가 HttpSecurity보다 우선적으로 고려되어, WebSecurity에 ignore() 작성시 HttpSecurity에서 해당 url들에게는 인가 설정이 적용되지 않는다.
[수정에 참고한 블로그 포스트]
https://soojae.tistory.com/53
[추가적으로 참고할 블로그 포스트]
https://www.baeldung.com/spring-security-httpsecurity-vs-websecurity
https://soojae.tistory.com/53
2. AuthenticationManager 사용
- `void configure(AuthenticationManagerBuilder auth)` → `AuthenticationManager authenticationManager(AuthenticationConfiguration config)`
- `AuthenticationManagerBuilder` 를 인자로 받던 것을 `AuthenticationConfiguration` 을 받도록 변경하고, 메서드 타입과 메서드명을 `void configure` 에서 `AuthenticationManager authenticationManager` 로 변경한다.
- 기존의 `AuthenticationManager`가 `AuthenticationManagerBuilder`를 이용하도록 변경한다.
변경 전
@Override
private void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
private BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
private CustomAuthenticationProvider authenticationProvider() {
return new CustomAuthenticationProvider();
}
변경 후
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
// auth.authenticationProvider(authenticationProvider());
return configuration.getAuthenticationManager();
}
@Bean
private CustomAuthenticationProvider authenticationProvider() {
return new CustomAuthenticationProvider();
}
@Setter 제거 및 생성자 객체 생성 방식에서 빌더 패턴으로 변경(`@Builder`)
Cf. MariaDB → MySQL로 변경하면서 궁금해진 점
- mysql-connector/j와 mysql-connector-java의 차이 https://thenicesj.tistory.com/545
- Java 버전을 8 → 17로 올렸는데 `Could not target platform: 'Java SE 17' using tool chain: 'JDK 8 (1.8)'.` 에러 발생(Build, Execution, Deployment > Gradle > Gradle JVM 버전 변경으로 해결 가능)
- Gradle 버전 변경
- Cf. Gradle 버전 종류(참고)
- # mac, linux gradlew wrapper --gradle-version 7.2 # window ./gradlew wrapper --gradle-version 7.2
Issue: Collection의 size로 sorting하여 Jpa 객체 조회하기
상세) CommentImp의 수로 내림차순하여 BoardImp를 조회하는 기능 구현(Pagenation은 덤)
방안
CommentImp 수로 내림차순된 BoardImp을 조회한 후 BoardImp의 id들로 CommentImp count 조회
1. board_id, count(comment.id)만 조회해올 dto 작성
@Getter
@Setter
public class CommentCount {
private Long boardId;
private Long count;
public CommentCount(Long boardId, Long count) {
this.boardId = boardId;
this.count = count;
}
}
2. BoardImp 조회시 order by b.comments.size 를 적용해본다. (오류 발생)
@Query(value = "select b from BoardImp b" +
" join b.writer m" +
" left join b.comments c" +
" group by b.id" +
" order by count(c.id) desc")
Page<BoardImp> findAllOrderByCommentsCountDesc(Pageable pageable);
3. CommentImp 조회시 BoardImp 아이디 리스트를 이용해 조회
@Query("select new com.portfolio.demo.project.dto.comment.count.CommentCount(c.board.id, count(c.id))" +
" from CommentImp c" +
" join c.board" +
" group by c.board.id")
List<CommentCount> findCommentCountsByBoardIds(List<Long> ids);
4. 리스트 타입으로 조회된 데이터를 Map으로 변경하고, BoardImp 리스트를 반복하여 아이디에 맞는 CommentCount값 가져오기
Pageable pageable = PageRequest.of(page, size);
Page<BoardImp> pages = boardImpRepository.findAllOrderByCommentsCountDesc(pageable);
List<BoardImp> list = pages.getContent();
List<Long> ids = list.stream().map(imp -> imp.getId()).collect(Collectors.toList());
List<CommentCount> commentCounts = commentImpCountRepository.findCommentCountsByBoardIds(ids);
Map<Long, Long> commentCountMap = commentCounts.stream().collect(Collectors.toMap(CommentCount::getBoardId, CommentCount::getCount));
List<BoardImpParam> vos = list.stream().map(BoardImpParam::create).toList();
for (BoardImpParam board : vos) {
Long count = commentCountMap.get(board.getId());
if (count != null) {
board.setCommentSize(count.intValue());
} else {
board.setCommentSize(0);
}
}
향후 개선하고 싶은 방향
1. CI/CD 파이프라인 자동화 방식 변경 - 현재의 GitAction, Docker를 이용한 방법에서 Jenkins 또는 GitLab 사용 방식으로 변경
2. 데이터 삭제시 실제 삭제보다는 flag값을 두어 데이터는 남기되 사용자에게 보여지지 않게끔 변경
참고글
https://covenant.tistory.com/277
https://covenant.tistory.com/279 (Springboot 버전 업그레이드)
https://post.dooray.io/we-dooray/tech-insight-ko/back-end/4173/ (Springboot 버전 업그레이드2)
https://covenant.tistory.com/277 (Spring Security 버전 업그레이드 및 리팩토링)
https://curiousjinan.tistory.com/entry/spring-boot-3-1-security-6-security-config-class-detail-2 (Spring Boot 3 & Security 6)
https://multifrontgarden.tistory.com/303 (spring boot 3 migration#02 WebSecurityConfigurerAdapter)
https://oingdaddy.tistory.com/399 (HandlerInterceptorAdapter deprecated → HandlerInterceptor)
https://kdhyo98.tistory.com/31 (모든 Exception에 대한 트랜잭션을 취소하고 싶다면? with @Transactinal)
https://interconnection.tistory.com/123 (Transactional 패키지의 차이 - org.springframework.transaction.annotation.Transactional 와 javax.transaction.Transactional)
https://velog.io/@rmswjdtn/JAVA-문법-Record-Class (record란?)
https://velog.io/@jehpark/Spring-Data-JPA-쿼리-like-containing의-차이점 (JPA like절 사용)
https://github.com/HomoEfficio/dev-tips/blob/master/Mockito when-thenReturn 사용 시 WrongTypeOfReturnValue 오류.md (Object is not mock 오류)
https://0soo.tistory.com/40 (JPA Test 관련 사항들 정리)
https://velog.io/@seungho1216/JPA검색-시-hibernate-에러와-해결 (JPA excape 에러)
https://velog.io/@im2sh/Spring-boot-Spring-boot-3-Swagger-3.0-설정
'Backend > Spring' 카테고리의 다른 글
Spring) .yaml(.yml) 파일 프로퍼티 불러오기 (0) | 2024.05.28 |
---|---|
Spring) Spring환경에서의 단위 테스트(JUnit5, Mockito) (0) | 2024.03.26 |
Spring) 도커로 이전 버전 H2 컨테이너 생성해 프로젝트와 연동하기 & EntityManager 사용해 CRUD하기 (1) | 2022.11.20 |
Spring + React 프로젝트 환경 구축 (0) | 2022.05.06 |
Spring) 실제 프로젝트가 실행되는 실제 경로 구하기 (0) | 2022.01.16 |