Server/Spring 51

Spring I/O 2024 - 스프링으로 DDD 구현하기! (해석 및 리뷰)

Spring I/O 2024에서 DDD(Domain Driven Design) 관련된 강연을 했다.Implementing Domain Driven Design with Spring by Maciej Walkowiak @ Spring I/O 2024해당 강연은 DDD의 기본부터 Spring을 활용한 구현 방법을 설명한다. 아래는 해당 강연 내용을 해석한 내용이다.DDD마틴파울러는 DDD를 아래와 같이 설명한다.DDD(Domain-Driven-Design) is an approach to software development that centers the development on programming a domain model that has a rich understanding of the process..

Server/Spring 2024.09.27

코프링 - runBlocking 모두 제거해야 하나?

runBlocking {} 제거해야 할까코틀린과 코루틴을 처음 접하는 경우가 많을 것이다.코틀린이 익숙하지 않은 프로젝트를 보면 대부분 Controller 메서드의 시작이 runBlocking()이 되어있고, 사실상 코루틴은 runBlocking(), runCatching() 밖에 존재하지 않는 경우가 있다.내가 투입된 프로젝트의 코드도 동일한 상황이었고 그랬고, '코루틴을 사용할 때의 이점을 하나도 못누리고 있는 것은 아닐까..?' 하는 의심을 가지게 되었다.runBlocking은 왜 문제이며, 어떻게 개선할 수 있는 지 알아보자.runBlocking아래는 runBlocking에 대한 docs의 일부이다.Runs a new coroutine and blocks the current thread inte..

Server/Spring 2024.06.16

Spring에서의 Proxy, AOP 동작원리 이해하기!

지난번 Spring AOP를 적용하면서 생겼던 문제에 대해 소개했다. https://jaehoney.tistory.com/375 이번 포스팅에서는 실무보다는 기본 개념에 대해 집중적으로 알아보자. 해당 포스팅은 김영한님의 스프링 핵심 원리 - 고급편의 프록시 관련 내용을 정리한 것이며, 프록시와 AOP의 동작의 기본 개념이라고 보면 된다. 프록시 패턴 프록시 패턴에서는 프록시가 너무 많이 생기는 문제가 있다. 아래는 GOF 프록시 패턴의 예시이다. 예로 들면 Repository 1개마다 전부 프록시 클래스를 생성해야 한다. 프록시를 적용할 클래스가 100개라면 100개의 프록시를 적용하는 코드를 만들어야 한다. 즉, 단일 책임 원칙에 어긋나고 기능 변경 시 다수의 클래스에 변경이 전파된다. 이 문제를 해..

Server/Spring 2023.11.16

Spring의 Servlet에 X-Forwarded-For 헤더가 왜 안들어올까?!

아래는 실무 중에 만난 이슈와 해결 과정에 대해 다룬다.정확한 원인과 해결 방법보다는 풀어나간 과정에 집중되어 있다.원인과 해결 방안이 궁금한 분은 가장 아래로 내리시면 될 것 같습니다!헤더에 X-Forwarded-For이 안들어오는 문제 발견아래는 공통 라이브러리의 코드의 일부 코드를 요약한 것이다.public class HeaderUtil { static public HeaderInfo initHeaderInfo(HttpServletRequest request){ return HeaderInfo.builder() .token(request.getHeader(HeaderInfo.JWT_HEADER)) .clientIp(request..

Server/Spring 2023.10.26

Accept 헤더가 포함된 REST API에서 에러를 내려주는 방법!

이번 포스팅은 회사에서 메일 원문 다운로드 API를 개발하면서 생긴 이슈에 대해 공유한다. 이해하기 쉽도록 메일 원문 대신 첨부 파일로 재해석해서 작성했다. 요즘은 파일 스토리지로 외부 인프라를 많이 사용해서 직접 설계해야 되는 상황이 드물긴 하다. 파일 접근 게시판의 첨부파일 기능을 생각해보자. 메타 데이터에는 빨간 네모와 같이 파일명과 확장자, 파일 사이즈, 다운로드 경로 등이 저장될 것이다. 다운로드를 클릭하면 실제 파일 스토리지에 접근해서 파일을 Binary 형태로 가져올 것이다. 게시판을 노출하기 위해서 메타 데이터를 가져올 때 파일 정보까지 모두 가져오면 오버헤드가 발생할 것이다. 그래서 2개의 End-point로 분리했다. Accept REST API에서는 url에 자원에 대한 경로를 지정한..

Server/Spring 2023.10.20

Spring - Bean은 어디에 저장되나?

스프링 공식 문서를 읽다가 Spring Bean은 어떤 자료구조에 저장되어 있고 어떤 과정으로 찾아서 의존을 주입하는 지가 궁금해졌다. 해당 부분을 찾아가면서 알게된 결과에 대해 다룬다. 아래에서 말하는 Bean은 싱글톤 빈임을 가정한다. 들어가기 전에 Spring의 경우 템플릿 메서드 패턴과 전략 패턴을 충분히 활용해서 수 많은 인터페이스에 책임을 위임하고 있고 구현체도 아주 많다. 그러다보니 자세히 다루면 양이 너무 방대해지는 문제가 있어서 어디까지 다룰 것인가에 대한 고민이 있었다. 너무 Deep한 문제는 다루지 않고 내용을 다루기에 이해가 필요한 부분까지만 다룰 것이니 겁먹지 마시고 봐주시면 좋겠다! getBean() 아래를 보면 ApplicationContext의 refresh()가 수행되면 i..

Server/Spring 2023.10.09

AOP, Proxy 이해하기! (BeanNotOfRequiredTypeException이 왜 발생할까?)

문제 상황 실무에서 QueryDsl을 사용한 Repository의 테스트 코드에서 에러가 터졌다. 문제를 이해하고 해결한 과정이 인상깊어서 소개하고자 한다. 아래 프로젝트는 소개를 위해 만든 프로젝트의 패키지 구조이다. 우리가 익히 아는 JPA + QueryDsl을 사용할 때 사용하는 패키지 구조이다. QueryDsl을 사용하는 Repository는 아래와 같다. @Repository @RequiredArgsConstructor @Transactional(readOnly = true) public class MemberRepositoryImpl implements MemberRepositoryCustom { private final JPAQueryFactory queryFactory; @Override ..

Server/Spring 2023.09.10

ApplicationContext란 무엇인가?!

ApplicationContext는 무엇일까..? 일반적으로 스프링 컨테이너라고 불리며 빈을 관리한다 정도로 알고 있다. 더 자세히 알아보자. ApplicationContext Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this. An ApplicationContext provides: Bean factory methods for accessing application components. Inherited from ListableBeanFactory. ..

Server/Spring 2023.08.14

SpringBoot - 무중단 배포 정말 안전할까?! (+ Graceful Shutdown)

k8s, 리버스 프록시 방식 등을 통해 무중단 배포를 하게 된다. 기존 인스턴스를 종료했을 때 이미 수행중인 작업이 있는 지 어떻게 보장할 수 있을까..? Graceful Shutdown Shutdown Graceful은 '우아한 종료'라는 뜻으로 하던 작업을 모두 안전하게 처리한 후 프로세스를 종료하는 것을 말한다. Linux의 kill - 15 명령어로 Graceful Shutdown을 할 수 있다고 말하는데, 실제 Spring 애플리케이션을 보면 하던 작업들이 강제로 종료된다. SpringApplication에서 요청을 어떻게 처리하는 지 Linux에서는 알 수 없기 때문이다! SpringBoot SpringBoot 2.3 부터는 손쉽게 Graceful Shutdown을 할 수 있는 설정을 제공한다..

Server/Spring 2023.08.13

@RequestBody에서 Enum과 String 어떤 것을 사용할까?!

Controller에서 Type과 같이 특정 값에 대해서만 입력을 받아야 하는 경우가 있다. 이때 Enum을 사용하면 아래의 문제가 생길 수 있다. 각 Layer의 강결합 아래는 기존의 코드이다. @RestController @RequiredArgsConstructor public class AlarmController { private final AlarmUseCase alarmUseCase; @PostMapping @ResponseStatus(HttpStatus.NO_CONTENT) public void postAlarm(@RequestBody PostAlarmRequest request) { String content = request.getContent(); PostType type = reque..

Server/Spring 2023.08.13