회사에서 신규 서비스 오픈을 앞에 두고 반영 이후 운영 CBT 를 진행하다가, 오류로그가 계속 올라오는 것을 확인하였습니다. 에러 로그를 확인해보니 하나의 로직에서 DB에 Insert(저장) 후에 해당 값을 Select(조회) 하는 과정에서 발생하였습니다. 발생한 이유를 확인해보니 테스트 환경에서는 발견이 안되었는데, 운영 환경은 모두 이중화가 되면서 발생하였다. 로직은 @Transactional 어노테이션으로 트랜잭션을 걸어두었으나 트랜잭션이 끝나기 전에 Insert(저장)은 1번 Session 으로, Select(조회)는 2번 Session 으로 동작 후 Insert하면서 NPE가 발생하고 있었습니다. 위와 같은 에러가 발생했다는 것은 @Transactional 어노테이션이 제대로 동작을 안했다는 것..
Spring 에서 개발을 하면서 예외가 발생되면 @ControllerAdvice 가 선언된 클래스가 동작하여 알맞은 예외타입(RuntimeException, NullPointerException 등)에 메소드가 호출된다. 대부분 프로젝트마다 로깅하는 방법이 정해져있기 때문에, 거의 사용되지는 않겠지만 빠르게 개발하면서 나중에 변경해야지 하고 e.printStackTrace() 로 작성하는 경우가 있다.(작성자 본인이 그렇다...) 전체 에러 메세지는 보기는 싫고, 실제 예외가 발생된 부분(소스 위치)만 로깅하고 싶었는데 구글링해보니 똑같이 생각하신 분이 계셔서 참고하게 되었다.) 이번 글에서는 e.printStackTrace를 말고 getStackTrace 로 간단한 코드를 통해서 확인해보려 한다. 1...
종종 Spring + MyBatis 개발을 하던 도중에 ResultMap 또는 ResultType 에 InnerClass 로 선언하고자 하는 경우가 있다. 1. 파일 구성 - 간단하게 예제를 통해서 진행해보겠습니다. - ResultType 에서 사용하고자 하는 파일은 아래와 같습니다.(Response 를 사용) 실제 개발에서는 DB의 값을 그대로 전달하는 것은 좋은 방법이 아니지만, 간단한 테스트를 위해서 바로 사용하였습니다. public class TodoDto { @Builder @AllArgsConstructor @NoArgsConstructor public static class Request { private String item; private boolean completed; } @Data ..
이전 글에서 NoSQL 을 로컬환경에 설치하는 것을 알아보았고, 해당 글에서는 SpringBoot 에서 CouchBase 를 연동해서 간단하게 테스트를 진행해보고자 합니다. 1. 환경 세팅 1-1. build.gradle - CouchBase dependency 를 추가해줍니다. implementation 'org.springframework.boot:spring-boot-starter-data-couchbase' 1-2. CouchBase 실행(Mac) - 이전 글에서 Docker 를 통해 설치한 CouchBase 를 실행합니다. docker run -d --name db -p 8091-8094:8091-8094 -p 11210:11210 couchbase:community-7.1.1 - 만약 위 명령..
SpringBoot 로 개발을 하다 보면 클라이언트와 통신 중 데이터에 대해서 Validation(검증)이 필요한 경우가 있습니다. 검증 클래스를 별도로 생성하여 검증을 진행할 수 있지만 간단하게 어노테이션을 통해서 JSR 표준을 이용하여 검증도 가능합니다. 이번 글에서는 이 JSR 표준을 이용한 @Valid 어노테이션에 대해서 정리해보고자 합니다. 0. Dependency 추가 Gradle(build.gradle) implementation 'org.springframework.boot:spring-boot-starter-validation' Maven(pom.xml) // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-..
회사에서 업무를 할당받게 되면서 Spring Batch 를 사용하고 있는 배치서버를 맡게 되었습니다.(Spring Batch 에 대해서는 추후 포스팅하기위해, 공부하고 정리하고 있습니다...) 그전에 간단하게 스프링에서 @Scheduled 어노테이션을 사용하여 간단하게 스케줄링 하는 것을 정리해보고자 합니다. 1. Spring Schedule(스케줄) 설정하기 - 간단하게 스프링부트(SpringBoot)에서 스케줄 설정은 아래와 같이 할 수 있습니다. @SpringBootApplication @EnableScheduling public class TestApplication { public static void main(String[] args) { SpringApplication.run(TestAppl..
회사에서 코드를 분석하다가 외부 API 통신 시 사용하고 있는 WebClient 를 발견할 수 있었다. Spring 5 부터 제공하는 기능이였고, 이전에는 RestTemplate 를 사용하고 있었어서 WebClient 에 대해 알아보고 정리해보고자 한다. 1. WebClient 란? - Spring 5 부터 제공하는 RestTemplate 를 대체하는 웹 클라이언트(HTTP Client). - 웹으로 API를 호출하기 위해 사용되는 Http Client 모듈 중 하나. - 기존의 동기(Sync) API 를 제공할 뿐만 아니라, 논블로킹(Non-Blocking) 및 비동기(Async) 방식을 지원해서 효율적인 통신이 가능. - 요청을 나타내고 전송하게 해주는 빌더(Builder) 방식의 인터페이스를 사용...
이전 글에서 JPA에 대한 기본 정리를 진행해보았습니다. 이번 글에서는 JPA 에서 가장 중요할 수 있는 영속성 컨텍스트(Persistence Context)에 대해서 정리해보고자 합니다. 1. 영속성 컨텍스트란? - 엔티티(Entity)를 영구 저장하는 환경. - 어플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 저장소 같은 역할. - 엔티티 매니저(EntityManager)를 통해 영속성 컨텍스트에 접근. - EntityManager 를 통해 Entity 를 저장, 조회하면 EntityManager 는 영속성 컨텍스트에 해당 Entity 를 보관하고 관리. 2. 영속성 컨텍스트 생명주기 - 영속성 컨텍스트의 생명주기는 아래 이미지와 같이 4가지 상태가 있다. 비영속(new) : 영속성 컨텍스..
개발을 배우면서 처음 Java에서 DB 와 관련된 작업을 할 때는 JDBC API를 배웠습니다. JDBC API는 항상 모든 로직 안에서 Connection 객체를 받아오고, SQL 문을 작성하고, 끝나면 close 시켜야 했습니다. 그리고 이러한 중복되고 불필요한 코드를 작성하는 것을 보완해주는 MyBatis, Spring JdbcTemplate 를 배워 사용하였습니다. 최근에는 ORM 기술을 통해 SQL 작성없이 객체를 DB에 직접 저장/관리를 할 수 있게 도와주는 JPA 를 사용하여 DB 작업을 대부분 사용하고 있습니다. 이번 글에서는 이 JPA에 대해서 정리를 해보고자 합니다. 0. ORM(Ojbect-Relational Mapping) 이란? - JPA에 대해서 알기전에 기본이 되는 ORM에 대..
회사에서 소스를 분석하는 도중에 의존성 주입을 필드에 @Autowired 어노테이션을 사용하지 않고, 생성자를 생성하여 주입하고 있었다. 그리고 종종 생성자에는 아예 @Autowired 어노테이션도 사용되지 않고 @RequiredArgsConstructor을 사용하고 있었다. 항상 필드 주입으로 사용하고 있었어서, 궁금해서 시니어 분께 여쭤보니 @Autowired는 deprecated 돼가는 분위기이고, 또한 생성자 주입을 권고하고 있기도 하다는 답변을 받았다. 추가로, 인텔리제이에서도 Autowired 어노테이션을 사용하면 아래와 같이 경고메시지를 보여주고 있었다.(매번 자세히 확인도 안 하고 넘어갔는데...) 대충 번역해보자면 "필드 주입은 권장하지 않습니다. 항상 빈에서 생성자 기반으로 종속성을 주..