새로운 것을 배워야 좋은 프로그래머인가요? 프로그래밍

어떤 분이 힘들다고 푸념하면서 새로운 것을 배워야만 좋은 프로그래머인거냐고 질문을 올렸길래 답을 달았다.

일단은 아래와 같이 답을 달았다.
항상 새로운 것을 배우는 것은 훌륭한 프로그래머가 아닙니다.(그렇다고 나쁘다는 뜻도 아닙니다. 단지 새로운 것을 배운다는 것 자체가 훌륭한 프로그래머의 정의는 아니다 라는 의미입니다.)

현재 개발을 하면서 어떤 문제가 반복적인 노가다성 작업인지, 인간의 실수를 유발하는 작업인지를 잘 살피고 그 문제를 해결하기 위해 공부하고 해결책을 제시하는 것은 훌륭한 프로그래머입니다.

다른 사람들의 반복 적이고 인간이 하기에는 오류가 많은 것을 자동화해주는 "프로그래머"라는 직업에 종사하면서 자기 자신이 겪고 있는 문제조차 공부하기 싫어 외면한다는 것은 좋은 프로그래머가 아닙니다.


내가 생각하는 좋은 프로그래머는 (특히 서비스 개발쪽에 종사하는 - 주로 웹,모바일 서비스등) 새로운 것을 추구하는 사람이 아니라 주어진 문제에서 발생하는 최적해를 찾아내는 사람이다. 최신 기술이 중요한게 아니라 최적 기술이 더 중요하며 그 와중에도 반복적이고 오류를 발생시키는 문제가 있을 때에는 과감히 새로운 기술을 도입도 할 수 있어야하고, 비록 낡은 기술이라도 현재 상태의 최적해라면 그리고 팀에 의해 정해진 규칙이고 그 규칙이 별다른 문제가 없다면 묵묵히 따를 수도 있어야 한다.

최신 기술만 추구하는 사람들은 보통 서비스는 제대로 만들지도 못하면서 자기 회사 서비스를 자기 개인 코드 연습장처럼 사용하여 서비스 전체를 아예 오픈도 못해보거나 실제 론칭 후에 발생하는 문제들을 해결하지 못해(너무 신기술이라 폭넓게 검증된 적이 없어서) 손을 놔버리는 모습을 보일 때도 있고,
공부하려들지 않는 개발자들은 어떻게 어떻게 꾸역꾸역 서비스를 유지하지만 근본적인 문제를 해결하지 못하고 외면하면서 문제의 크기를 계속 키워서 시스템 전체를 손댈 수 없는 지경의 위험에 빠뜨리는 것을 본다.

이 둘 강의 균형을 어떻게 유지할 것인가?

공유하기 버튼

 
 

Spring ChainedTransactionManager 어떻게 사용해야 하나? 프로그래밍

Spring Data Commons 1.6에는 ChainedTransactionManager라는 것이 추가 돼 있다

하나의 애플리케이션에서 여러 데이터베이스에 접근할 때 @Transactional 애노테이션을 통해 트랜잭션을 잡아줄 때 여러 데이터소스(DataSource)의 트랜잭션 매니저(Transaction Manager)를 따로따로 지정해서 작업해야 한다.
사실 그렇게까지 어려운 일은 아니지만 확실히 복잡도가 높아지긴 한다. 그래서 편리하게 사용하라고 나온 것이 ChainedTransactionManager이다.
이는 여러 트랜잭션 매니저를 인자로 받아 @Transactional에 기본 트랜잭션 매니저로 등록시켜두면, 트랜잭션이 시작될 때 지정된 모든 트랜잭션 매니저의 트랜잭션을 동시에 시작시키고 메소드 종료시에 동시에 커밋(commit) 혹을 롤백(rollback)을 수행한다.

javadoc 문서에 보면 The configured instances will start transactions in the order given and commit/rollback in reverse order, which means the PlatformTransactionManager most likely to break the transaction should be the last in the list configured. A PlatformTransactionManager throwing an exception during commit will automatically cause the remaining transaction managers to roll back instead of committing.라고 나온다.
즉,
  • 지정된 순서대로 트랜잭션이 실행되고,
  • 지정된 역순으로 트랜잭션이 종료된다.
  • 다시말해, 에러를 내기 쉬운 트랜잭션을 마지막에 지정해서 트랜잭션 종료 작업이 최초로 호출되도록 해야한다

왜냐면, 에러를 낼 가능성이 높은 트랜잭션이 최초로 롤백이 돼야 그 뒤의 다른 트랜잭션도 따라서 롤백 되기 때문이다. ChainedTransactionManager는 단지 트랜잭션 시작과 종료를 동시에 해줄 뿐이지 Two Phase Commit을 지원하는게 아니라서 이미 다른 트랜잭션이 커밋된 상황에서 하나의 트랜잭션이 롤백 됐다고 해서 이미 커밋된 것들이 다시 롤백되지는 않는다. 따라서 가장 위험한 요소를 최초로 커밋/롤백 시도하도록 해야 한다.

그런데 문제가 여기서 끝나지 않는다.

Spring의 PlatformTransactionManager는 기본적으로 트랜잭션이 시작될 때 Connection을 확보한다. 여기서 실제로 해당 Connection의 사용여부는 중요하지 않다. 그냥 무조건 Connection을 확보한다.

ChainedTransactionManager가 firstTransactionManager와 secondTransactionManager를 묶은 상태일때, ServiceA가 firstTransactionManager의 데이터소스만 사용하는 작업을 하더라도 secondTransactionManager의 데이터소스의 커넥션까지 함께 물고 들어가게 된다.

이 상황이 되면 실제로 secondTransactionManager는 아무 하는 일도 없이 커넥션 고갈 상태에 빠질 수 있다. 게다가 secondTransactionManager에 참여하는 데이터소스의 최대 커넥션 갯수가 firstTransactionManager의 커넥션 갯수보다 더 적은 상황이라면 사태는 더욱 심각해진다.

따라서 최종적으로 봤을 때 ChainedTransactionManager에 참여하는 모든 DataSource의 최대 커넥션 갯수는 동일하게 맞춰주는 것이 좋다.

또한, Spring은 LazyConnectionDataSourceProxy라는 것을 제공해주고 있다.
이를 사용하면 트랜잭션 매니저에 의해 커넥션이 호출되더라도 실제로 커넥션이 사용되기 전까지 원본 데이터소스에 커넥션 요청을 미룸으로써 불필요한 커넥션 생성 요청을 방지해준다. 따라서 CTM 으로 묶여있는 데이터소스들이 사용도 안되는 커넥션 요청으로 커넥션 고갈을 겪는 문제를 완화시켜준다.

LazyConnectionDataSourceProxy는 ORM 사용시 캐시 히트율이 높아서 ReadOnly 트랜잭션은 시작했으나 정작 DB에 한번도 액세스하지 않는 상황이 될 때도 매우 유용하다.

위 사항은 직접 테스트를 해보았다.

ChainedTransactionManagerTest에서 테스트 코드와 결과를 볼 수 있다.

공유하기 버튼

 
 

1 2 3 4 5 6 7 8 9 10 다음