소개
호주에 살고 있는 소프트웨어 개발자입니다. 30년간 다양한 분야의 시스템과 서비스를 개발해본 경험이 있습니다.
스프링 프레임워크와 관련 기술을 좋아하고 JVM 기반 언어를 주로 사용합니다.
한국스프링사용자모임(KSUG)을 설립하고 활동했고, 토비의 스프링이라는 책을 쓰기도 했습니다.
개발과 관련된 다양한 주제에 관해 이야기하는 것을 좋아합니다.
강의
전체3수강평
- 쵝옵니당
DongHyuck Kim
2024.09.13
1
- 좋은 강의 감사합니다.
godkkoo
2024.09.10
1
- 기대하는 강의라서 집중하여 듣고 있습니다.
kmshsh1
2024.09.06
1
- 좋은 강의 감사합니다!
최한슬
2024.09.02
1
게시글
질문&답변
2024.09.08
인터페이스는 사용하는 클래스에 가장 가까이 두는 걸로 이해했습니다. 하지만 그 인터페이스를 사용하는 클라이언트가 많다면 어떻게 해야할까요?
인터페이스를 구현과 분리하는 방식을 쓸 때, 기본적으로는 인터페이스의 클라이언트와 인터페이스를 가까이 둡니다. 그런데 인터페이스를 사용하는 클라이언트가 여러개라면? 이 때는 별도의 위치로 분리하는 수 밖에 없죠. 중요한 건 모듈 레벨에서, 혹은 계층 레벨에서 클라이언트와 같은 레벨에 두는 겁니다. 구현과 함께 또는 가까운 쪽이 아니고요. 패키지는 분리될 수 있겠지만요.
- 0
- 2
- 45
질문&답변
2024.09.08
멀티 스레드를 사용하는 테스트에서 트랜잭션 사용에 대해서..
API 레벨에서 DB 데이터의 동시성 문제를 다루고 싶다면 이건 DB 트랜잭션과 락을 사용하는 방식으로 해결해야 합니다. 테스트를 만들 더라도 모든 작업이 완료된 뒤에(즉 여러개의 트랜잭션 처리가 다 정상적으로 실행완료된 뒤에) 최종 값을 검증해야 하기 때문에 @Transactional 테스트는 어떤 식으로든 사용할 수 없습니다. @Transactional 테스트는 단일 트랜잭션을 롤백하는 것인데, API 수준의 동시성이라면 동시에 API를 실행하는 순간 이미 트랜잭션이 API마다 하나씩 따로 생기는 시나리오니 이건 단일 트랜잭션 롤백이라는 방식을 사용하는 테스트 기법의 대상에서 완전히 벗아난 것입니다. ExecutorService를 사용할 때는 트랜잭션 시작 이전, 즉 Controller에 대해서 테스트 하시는 것이 좋습니다. 개별적으로 새로운 트랜잭션이 만들어질 것이고요. 혹은 mockMvc를 이용한 MVC테스트를 이용하셔도 됩니다. 지금 준비하는 강의에서 데이터 처리 동시성 관련 문제를 한번쯤 다룰텐데 그때 구체적인 예를 소개해드리겠습니다. 그 전에라도 검색해보시면 동시성 문제를 다루는 좋은 블로그 글을 찾으실 수도 있을 겁니다.
- 0
- 4
- 59
질문&답변
2024.09.08
멀티 스레드를 사용하는 테스트에서 트랜잭션 사용에 대해서..
그런데 예로 드신 코드는 문제가 있습니다. ExecutorService에서 새로운 쓰레드를 만들고, 이 쓰레드에서 db 액세스를 하면, repository에서 새로운 트랜잭션이 만들어지는데, 이러면 고립도 설정에 따라서 같은 데이터를 두 개의 쓰레드에서 액세스할 때 어떤 결과가 나올지 모릅니다. 트랜잭션이 완료되지 않(을 수도 있)는 상태에서 두 개가 어떤 순서대로 진행될지 모르기 때문이죠. 현실에서는 절대 이런 스타일로 코드를 작성하시면 안 됩니다. 해결할 수 있는 문제도 없고, 멀티 쓰레드에서 어떤 타이밍에 어떤 코드가 실행될지 예측도 불가능합니다. 멀티쓰레드에서 서로 동기화를 잘 하지 않으면 안 되는데, 굳이 이렇게 코드를 작성할 필요도 없는데 이렇게 만드는 건 불필요할 뿐입니다.
- 0
- 4
- 59
질문&답변
2024.09.08
멀티 스레드를 사용하는 테스트에서 트랜잭션 사용에 대해서..
@Transactional 롤백 테스트를 사용하는 데 두 가지 제약사항이 있습니다. 이건 공식 문서에도 구체적으로 업급됩니다. 첫번째는 지금 처럼 멀티 쓰레드를 사용하는 것이고, 두 번째는 @Transactional의 propagation을 REQUIRES_NEW로 지정해서 별개의 트랜잭션을 만드는 것입니다. 이 두가지 케이스에선 테스트에서 @Transactional을 사용하시면 안 됩니다. @Transactional은 테스트에서 트랜잭션을 시작한 뒤에 ThreadLocal에 바인딩하고 해당 쓰레드와 해당 트랜잭션만 롤백시키기 때문입니다. 이런 특별한 케이스에선 트랜잭션을 다 커밋시키고 테스트에서 검증한 뒤에 해당 데이터를 삭제해주는 방법을 쓰셔야 합니다. 특히 @Async라든가 멀티 쓰레드를 만들어서 그 안에서 DB 조작이 일어나는 경우, 모든 쓰레드 작업이 완료된 것을 확인하고 테스트에서 검증을 해야 합니다. 그렇지 않으면 테스트 결과가 항상 동일하게 나오지 않을 수도 있습니다.
- 0
- 4
- 59
질문&답변
2024.09.02
MyAutoConfigImportSelector 에서 생성자로 ClassLoader를 주입받을 수 있는 점
MyAutoConfigImportSelector는 EnableMyAutoConfiguration 애노테이션 정의에서 @Import로 지정되어있습니다. 여기서 @Import에 다음과 갈이 지정되어있어서 MyAutoConfigImportSelector를 스프링 컨테이너를 초기화하는 과정에서 마치 빈 처럼 취급해서 필요한 오브젝트를 주입 받고, 빈 등록 기능을 수행할 수 있도록 해줍니다. (사진) ImportSelector는 좀 특별하게 취급되는 스프링 구성정보를 동적으로 만드는 컨테이너의 고유한 기능이라고 생각하시면 됩니다. @Import와 ImportSelector 인터페이스의 javadoc을 자세히 읽어보시면 도움이 될 겁니다. ImportSelector 인터페이스의 문서를 읽어보면 다음과 같이 BeanClassLoaderAware 인터페이스를 추가해서 클래스로더를 주입 받도록 만들 수 있다고 되어있고요. ImportSelector 구현 클래스가 만들어져서 동작할 때 필요한 오브젝트를 제공해주는 것이지요. 예전엔 setter 메소드를 가진 인터페이스를 추가로 구현해줬지만, 스프링의 생성자 주입 방식을 따르면 생성자 파라미터로 정의하는 것만으로, 스프링 컨테이너가 만든 클래스로더가 적용이 됩니다. (사진)
- 0
- 1
- 31