![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/egXiq3/btsFfvFgyIA/AKwuvNCi1SNAPb5CBFEVnK/img.png)
리소스를 효율적으로 사용하겠다는 섣부른 판단에 객체를 스프링 빈으로 등록해 싱글톤으로 사용할 경우 필자와 같은 참사가 이루어질 수 있으니 이 글을 읽는다면 도움이 되기를 바란다. 물론 잘 알고 쓰면 싱글톤이 안티패턴이라는 불리는 것이 와닿지 않을 것이다. 기술스펙 (Springboot2.7, Freemarker2.3) 문제는 다음과 같았다. DB에 Freemarker로 작성된 A라는 내용이 들어가야하는 상황인데 아주 간혈적으로, 데이터 상 거의 1/50000의 확률로 B라는 내용이 들어갔다. 비즈니스를 바탕으로 소스를 분석하고 문제가 될 만한 코드를 찾기는 쉽지 않았다. 1/50000로 생각하다보니 무엇보다 상황을 재현하는 것이 불가능한 것처럼 느껴졌다. 비슷한 예제코드를 보자. import freema..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/borwJa/btsDAihfw6Y/EmEtu2vsxULIaOPXVoqkL0/img.png)
이슈는 간단했지만 해결책은 결국 돌고 돌았던 내용을 정리해보려고 한다. (최종 코드는 맨 하단을 참고) 일반적인 url path에 대한 400이나 404 등의 에러 핸들링은 성공적으로 진행되었고 문제가 없었다. ErrorController, @ExceptionHandler을 적절히 사용하여 커스텀하게 에러를 핸들링하고 있던 도중 url에 특수문자가 들어간 경우 톰 캣의 버전이 노출된다는 요청이 있었고 보안상 막을 필요가 있었다. 첫번째로 의문이 들었다. 왜 내가 만든 ErrorController를 타지 않는 것이지? 디버깅을 해볼 필요도 없었다. 요청에 대한 트레이싱 정보가 아예 애플리케이션에 전달 조차 되지 않았다. 내가 생각한 것보다 더 앞단에서 막는 것 같다는 생각이 들었고 이것저것 찾아보기 시작했..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/b6U7dk/btspgnEYIxU/l1AlNH1UgriSye8KvdJuK0/img.png)
{ "timestamp": "2019-02-15T22:24:41.275+0000", "status": 404, "error": "Not Found", "message": "No message available", "path": "/123", "nice": "springboot" } 에러 처리는 애플리케이션 개발에 있어 여러 오류를 빠르게 파악하고 수정하는데 있어 유용하게 사용되어 의무가 아닌 필수가 되었다. 기본적으로 스프링부트 애플리케이션을 만들고 실행하면 404 Not Found에 대해서 다음과 같은 화면을 볼 수 있다. 같은 요청 localhost:8080/123에 대해서 포스트맨을 사용하여 JSON 응답값을 확인해보면 다음과 같다. { "timestamp": "2023-08-14T22:21:24...
이전에 step2에서 포인트컷 표현식과 트랜잭션 속성을 이용해 트랜잭션을 일괄적으로 적용하는 방식은 복잡한 트랜잭션 속성이 요구되지 않는 한 대부분의 상황에 적용가능하지만 클래스나 메소드에 다라 제각각 속성이 다른, 세밀하게 튜닝된 트랜잭션 속성을 적용해야 하는 경우 일괄적으로 속성을 부여하는 것 대신에 직접 타깃에 트랜잭션 속성정보를 가진 애노테이션을 이용하는 방법이 있다. @Transactional을 정의한 코드는 직관적이라 이전에 설명한 속성을 모두 포함하고 있다. pacakage org.springframwork.transaction.annotation; ... @Target({ElementType.METHOD, ElementType.TYPE}) @Retension(RetentionPolicy.R..
이전에 step1에서 코드로 만든 어드바이스를 제외한 자동 프록시 생성기(DefaultAdvisorAutoproxyCreator), 포인트 컷(AspectJExpressionPointcut), 어드바이저(DefaultPointcutAdvisor)는 모두 스프링이 직접 제공하는 클래스를 빈으로 등록하고 프로퍼티를 설정해줬다. 이 세가지 클래스를 이용해 선언하는 빈은 AOP를 적용하면 반복적으로 등장하게 된다. 스프링에서는 AOP를 위해 기계적으로 적용하는 빈들을 간편한 방법으로 등록할 수 있다. AOP와 관련된 태그를 정의해둔 aop 스키마를 제공한다. 더보기 네임스페이스(Namespace)는 XML 문서에서 요소, 속성 등을 구분하기 위한 식별자(identifier)이다. XML 문서에서는 각 요소나 속..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/bzDcnz/btsdsQXQuM9/spVmAGBw9LJ6HNnyqtHpk0/img.png)
이전 step4에서 고민한 자동 프록시 생성을 빈 후처리기를 이용한다. BeanPostProcessor 인터페이스를 구현해서 만든 빈 후처리기를 이용하면 스프링 빈 오브젝트로 만들어지고 난 후에 빈 오브젝트를 다시 가공할 수 있게 해준다. 빈 후처리기 중의 하나인 DefaultAdvisorAutoProxyCreator를 사용하여 문제를 해결한다. 빈 후처리기를 스프링에 적용하는 방법은 빈 후처리기 자체를 빈으로 등록하면 빈 오브젝트가 생설될 때마다 빈 후처리기에 보내서 후처리 작업을 요청한다. 이를 잘 이용한다면 타깃 빈 오브젝트의 일부를 프록시로 포장하고 프록시를 빈으로 대신 등록하는 작업이 가능하다. 이것이 자동 프록시 생성 빈 후처리기다. 1, 2. DefaultAdvisorAutoProxyCrea..