무지를 아는 것이 곧 앎의 시작

Spring 9

멀티 모듈 프로젝트 세팅하기

멀티 모듈 프로젝트는 왜 세팅할까? A 엔티티가 있고 이걸 다루는 API 서버 어플리케이션이 있다. 근데 마침 같은 A 엔티티를 다루는 배치 어플리케이션의 개발이 필요하다. 별도의 프로젝트로 배치 어플리케이션을 개발하면, 그 배치 어플리케이션 쪽에도 A 엔티티와 관련된 코드를 옮겨줘야 한다. 그리고 이 A엔티티를 다루는 어드민 전용 API 어플리케이션이 또 필요하다. 이것도 별도의 프로젝트로 개발한다면, A 엔티티는 세 군데에 동시에 코드가 존재하게 될 것이다. 마치 아래 그림처럼. 이러한 구조가 되었을 때, 만약 A 엔티티의 요구사항이 변해서 수정이 생기면 어떻게 될까? 각각의 프로젝트에서 각각 A 엔티티에 수정 사항을 반영시켜야 하고, 미처 반영하지 못하고 배포를 나갔을 경우엔 어떠한 문제가 생길지도..

Spring 2023.11.27

분산락 언제 잡고 어떻게 잡는게 좋을까

프로젝트 진행하다 보면 동시성 이슈를 해결해야할 때가 있다. 최근 사이드 프로젝트에 북마크 기능을 구현할 때 어떻게 동시성 이슈를 잡았었고 어떤 고민을 해서 잡는 방법을 채택했는지 기록해볼까 한다. 도메인 간단 이해 일단 도메인 구조를 보면, Place(장소)라는게 있고, 이 장소에 북마크를 찍는개념으로 해서 Bookmark(북마크)가 있고 1(장소):N(북마크)로 되어있다. 그리고 Place 리스트를 조회할 때 bookmark 갯수가 같이 노출돼야하기 때문에 성능 최적화를 위해 bookmarkCount라는 컬럼을 Place가 반정규화해서 들도록 했다. /// imports... /// annotations... public class Place extends AbstractRootEntity { @Id..

CS 2023.10.09

RedisTemplate는 @Transactional 안에서 어떻게 동작할까?

최근 사이드 프로젝트를 하며 재밌는 사실을 알게 되어 포스팅을 남겨본다. RedisTemplate를 사용할 때 스프링에서 추상화하여 제공해주는 트랜잭션 기능을 사용하고 싶으면 다음과 같은 세팅을 하면 된다. @Configuration @RequiredArgsConstructor @EnableTransactionManagement public class RedisConfig { //... @Bean public RedisTemplate redisTemplate( final RedisConnectionFactory redisConnectionFactory ) { final RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnecti..

Spring 2023.06.27

내편 로깅 정책 정리

요청정보 로깅에 대한 변천사 아 인터셉터에서 Request Body 로그 찍고싶다.. 요청 정보는 서비스 로직 시작 전에 찍어야지..? 요청로깅 AOP로 해야겠다 로깅 성능에 대한 고민 로깅 성능에 대한 고민 작업 트레이스 로깅 로그 잘 남기면 디버깅이 수월해짐 위 과정들을 통해 로깅 정책을 픽스한다. 로그 레벨 프로덕션 서버: 루트레벨 info, 어플리케이션 패키지 info 개발 서버: 루트레벨 info, 어플리케이션 패키지 debug 로컬: 루트레벨 info, 어플리케이션 패키지 debug 로그 관리 프로덕션 서버: 롤링 파일 어펜더를 사용해서 1일마다 최대 10mb 단위로 잘라서 압축 관리, 최대 14일치 보관 개발 서버: 파일 어펜더를 사용해서 파일을 남김. 서버 재실행마다 초기화 로컬: 콘솔창에..

Spring 2022.10.24

로그 잘 남기면 디버깅이 수월해짐

개발용 서버에선 프로덕션 서버로 배포되기 전 QA작업이 이뤄지고, 프론트엔드와의 협업시 사용되기 때문에 로컬에서 발견하지 못한 버그를 발견하게 되는 케이스가 꽤 잦았다. 하지만, 부실한 로그를 남기고 있었다면, 개발 서버 자체에서 버그의 발생 경로를 추측하는 데에 어려움이 있었다. 그래서 프로젝트의 로깅 정책에 debug레벨로 개발서버와 로컬 환경에서 모든 작업에 대한 트레이싱 정보를 남기는 정책을 추가했다. 왜 개발용 서버에서만 트레이싱 로그를 남겨야 하는가 로컬 환경에서 버그를 발견했다면, 대부분의 개발자는 IDE의 디버깅 모드로 디버깅을 시도할 것이다. 하지만, 로컬 환경이 아니라 서버에 올라간 프로그램의 경우 IDE의 기능을 이용할 수 없기에 어플리케이션이 남겨놓은 로그에 디버깅을 의존하게 된다...

Spring 2022.10.23

요청로깅 AOP로 해야겠다

2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Body 로그 찍고싶다.. 아 인터셉터에서 Request Body 로그 찍고싶다.. 요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. alexander96.tistory.com 2022.09.26 - [개발 이야기/Spring] - 요청 정보는 서비스 로직 시작 전에 찍어야지..? 요청 정보는 서비스 로직 시작 전에 찍어야지..? 저번 포스팅에 있던 내용과 이어질 듯..ㅎ 바로 이전 포스팅 2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Bo..

Spring 2022.10.23

요청 정보는 서비스 로직 시작 전에 찍어야지..?

저번 포스팅에 있던 내용과 이어질 듯..ㅎ 바로 이전 포스팅 2022.08.17 - [개발 이야기/Spring] - 아 인터셉터에서 Request Body 로그 찍고싶다.. 아 인터셉터에서 Request Body 로그 찍고싶다.. 요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. alexander96.tistory.com 여기서 보면 스프링 인터셉터의 afterCompletion에서 로그를 찍고 있다. 왜 afterCompletion에서 찍게 됐냐면 바로 RequestBody가 스트림 형태로 들어오기 때문. 스트림은 한번 소비하면 다시 못쓰기 때문에 로깅에서 써버..

Spring 2022.09.26

아 인터셉터에서 Request Body 로그 찍고싶다..

요즘 우테코 레벨3과정의 팀 프로젝트를 하고 있다. 팀원끼리 업무 나눠서 분업하고 있는데 로깅을 맡게 되었다. 로깅 전략을 세우다 보니 모든 Http 요청에 대한 정보를 찍을 필요성을 느꼈다. 모든 요청에 대한 공통 처리이니 '아 스프링의 인터셉터에서 로그 찍음 되겠네!' 싶었다. 찍고싶은 요청 정보는 HTTP Method, Request URI, AccessToken 존재 여부, Request Body 정도였다. Interceptor는 preHandle이라는 메서드에서 파라미터로 HttpServletRequest 가 들어오고 여기서 요청 정보를 뽑을 계획이었다. 그래서 짠 코드 @Slf4j @Component @RequiredArgsConstructor public class LoggingInterce..

Spring 2022.08.17

스프링 컨트롤러 Request Mapping

스프링 프레임웍의 컨트롤러에서는 http 요청이 들어오면 특정 메서드를 실행하고 반환하는 방식으로 작동합니다. 이 포스팅에서는 컨트롤러에서 요청을 처리할 메서드에 매핑하는 기준들에 대해 작성해볼까 합니다! Http Method (요청 방식) http 요청 메세지에는 method라는 것이 존재합니다. 대표적으로 GET, POST, PUT, PATCH, DELETE 5가지가 존재하며, 특별한 역할을 하는 기타 메서드들도 존재합니다. 스프링 컨트롤러에선 이 http 메서드로 요청 매핑을 나눌 수 있습니다. @PostMapping("/http-method/users") public ResponseEntity createUser(@RequestBody User user) { Long id = 1L; return ..

Spring 2022.04.30