spring boot 버전을 올리면서 3.4.x 버전을 사용하게 됐고, 동작을 확인하던 도중 기존 코드에서 에러가 발생했다.Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)해당 로우가 다른 트랜잭션에서 업데이트되거나 삭제되었다는 메시지인데, 버전을 올리지 않으면 해당 에러는 발생하지 않았다. 해당 문제가 발생할 수 있는 상황은 이렇다.// 엔티티 정의@Entity@Table(name = "person")@AllArgsConstructor@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Person { @Id @Generated..
spring 은 전통적으로 http client 로 RestTemplate 을 제공해왔다. 그러다가 webflux 의 등장과 함께 비동기로 동작하는 http client 인 WebClient 라는 모던 http client 를 제공하기 시작했는데, 초기엔 mvc 에서도 이 WebClient 를 이용하는걸 권장했다. 하지만 WebClient 를 이용하기 위해선 webflux 전체에 의존해야하고, reactive 라이브러리인 proejct reactor API 를 사용해야하는 불편함이 있었다. 불편함이라고 썼지만 개인적으론 최악의 경험이었다. 그러다가 spring boot 3.2 에 신규 동기 http client 가 들어왔으니 그게 RestClient 이다. 오늘은 RestClient 를 잘 사용하기 위한..
이번엔 예외처리에 대한 이야기를 해보려한다. 실무에서도 흔히 보이는 방식과 그 방식에서 아쉬웠던 부분도 함께 정리해보고자 한다. # 1개의 Exception 클래스와 error enum실무에서 가장 많이 본 예외처리 방식이다. 대다수가 이런 방식을 사용하고 있을거라고 생각한다.// 예외 클래스 정의@Getterpublic class ApiException extends RuntimeException { private ErrorCode errorCode;}// 에러 코드를 담는 상수 정의, 사용자노출 메시지와 http status 코드를 관리@AllArgsConstructor@Getterpublic enum ErrorCode { ENTITY_NOT_FOUND("엔티티를 찾지 못했습니다.", 40..
이번엔 특별히 무언가 주제가 있다기보다 실무에서도 쉽게 접하는 상황에서 어떻게 인터페이스를 설계하는게 올바른지 예제를 통해 알아가보려 한다. 지난 포스팅의 후속작정도 될 것 같다. # 요구사항소셜 로그인 로직을 구현해야한다. 소셜 로그인은 네이버, 카카오, 구글을 지원할 예정이다. 소셜 로그인을 할때 각 플랫폼들이 필요로 하는 정보는 아래에 적어놨다. 실제 플랫폼들의 소셜 로그인을 구현하는건 아니어서 아래 필요정보들은 실제 플랫폼 소셜 로그인과는 상관없이 가상의 필요정보다. 네이버: client-key, 사용자 id, 사용자 동의여부카카오: client-key, 사용자 id구글: client-key, 사용자 토큰 # 인터페이스 정의소셜 로그인과 각 플랫폼들의 관계는 딱봐도 개발자로 하여금 뭔가 추상화를..
기존 spring boot 3.0.13 버전에서 3.1.12 로 버전업을 시도했다. 하위호환을 잘 보장해준 덕에 큰 이슈없이 빌드에 성공했는데 엔티티 조회시 ArrayIndexOutOfBoundsException 이 발생하는걸 확인했다. 해당 엔티티는 크게 복잡하지 않은 보통의 엔티티였는데 왜 문제가 발생한건지 정리하려한다. 문제가 발생하는 환경을 간단한 엔티티로 표현하면 이렇다.@Entity@Table(name = "car")public class Car { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "car_id") private Long id; @Column(name = "car_type") ..
spring batch 를 이용할때 어떤 reader 를 이용할지 항상 고민되는 편이다. DB 접근을 JPA 로 하고 있다면 대표적으로 JpaCursorItemReader, JpaPagingItemReader 중에 고민하게 된다. 보통 이 둘을 고민하는 상황이 오면 성능적으론 JpaCursorItemReader 가 더 좋다는걸 알게 된다. 하지만 대량의 데이터를 조회한 후 커서를 이동시키는 이 방식은 타임아웃을 유발할 수 있기에 데이터가 많을땐 조심해야해서, 이런 문제에 대해 안전한 JpaPagingItemReader 를 선택하는 경우가 많다. 하지만 페이징 기반의 리더를 쓰게되면 몇가지 곤란한 부분이 있는데 대표적으로 특정 상태를 이용해 조회한 후 상태를 변경하는 방식의 배치 잡을 만들때다. 1페이지를..
spring batch 4.3 부터 JpaCursorItemReader 가 추가됐다. 이게 추가되기 이전에는 배치에서 JPA 를 쓸땐 JpaPagingItemReader 를 사용하거나 cursor 방식이 필요하다면 HibernateCursorItemReader 를 써야했다. JpaCursorItemReader 가 추가된지 비교적 얼마 안됐기때문에 아직 HibernateCursorItemReader 를 이용해 돌아가고있는 배치가 많을 것으로 예상한다. 하지만 HibernateCursorItemReader 는 spring batch 5.0 부터 Deprecate 되었고, 5.2 부터는 아예 삭제될 예정이므로 최신 spring batch 에서 배치 로직을 작성하거나 기존 spring batch 프로젝트의 버전..
spring 을 공부하면 가장 먼저 배우는 키워드 중 하나가 DI 이다. DI 란 무엇인가? 의존성을 직접 해결하지 않고 외부로부터 주입받는 것이다. 더군다나 주입받는 대상을 구현 클래스가 아닌 인터페이스로 지정하면 확장에 열려있는 설계가 되며, DI 는 스트레티지 패턴에 기초하고 있다는걸 공부하게 된다. 그럼 spring 을 사용하고 있는 우리는 공부한걸 잘 이해하고, spring 으로 애플리케이션을 개발할때 다형성을 잘 이용하고 있을까?@Componentpublic class DataGetter { public String get() { // SQL 을 이용해 데이터 조회 }}@Componentpublic class DataAggregator { @Autowired ..
spring batch 를 이용하여 배치를 만들때 job 설정은 아래와 같이 JobbuilderFactory 를 주입받아 이를 이용한다.@Configurationpublic class SimpleBatchConfiguration { @Autowired private JobBuilderFactory jobBuilderFactory; @Bean public Job simpleJob(Step step) { return this.jobBuilderFactory.get("simpleJob") .start(step) .build(); }} 하지만 현재 최신버전(3.2.5)의 spring boot 를 이용한다면 해당 클래스가..
현재 진행중인 프로젝트에서 spring boot 2.7.18 을 사용하고 있다. 현시점(2024.04.28) 기준 2.x 버전에서 가장 최신이다. 엔티티 로딩과정에서 직관적이지 못한 이슈를 만나서 정리하고, 어떤때 발생하고 어떻게 해결할 수 있는지 정리해보려한다. spring boot2.7.18hibernate-core5.6.15.Final # 이슈상황- 엔티티 Main 과 엔티티 Sub 는 1:1 관계로 @OneToOne 관계를 맺고있다(fetchType 은 디폴트 설정인 EAGER 를 사용한다). 외래키는 Main 에서 관리한다고 가정한다.- Main 과 Sub 는 논리적 연관관계만 가질뿐 데이터베이스 설정상으로 외래키 관계를 강제하지는 않는 상태다.- Main 과 Sub 는 두 엔티티가 모두 정상적..
- Total
- Today
- Yesterday
- toby
- frontend개발환경
- http
- OOP
- servlet
- db
- javascript
- Design Pattern
- frontcode
- java8
- DesignPattern
- Git
- TEST
- mariadb
- spring cloud
- MySQL
- JPA
- Jackson
- java
- backend개발환경
- JavaScript Core
- Spring
- go-core
- clean code
- code
- 정규표현식
- generics
- Kotlin
- programming
- EffectiveJava
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |