Though iBATIS is one of a very popular ORM framework, it has some irritatating problems that every developers have suffered for a long time. Whenever sqlMap file is modified, one should undergo the tedious process of restarting the application so that the modifications actually take effect. So I made a little extension to Spring framework's SqlMapClientFactory class in order to monitor file modification and re-initialize sqlMapClient accordingly. Basic implementation ideas are : 1. don't change original classes of Spring Framework nor iBATIS library. 2. should run with iBATIS 2.3.0 for jdk 1.4 and iBATIS 2.3.2 or later for jdk 1.5 or higher. (with the nice feature of Spring 2.5.5+ SqlMapClientFactoryBean's wildcard matching while preserving compatibility with old libraries.) 3. assuming default singleton scoped beans, SqlMapClientFactoryBean creates new SqlMapClient instance only when Spring initializes the applicationContext. The object (sqlMapclient) injected to other beans cannot be replaced while the application is up. It should be replaced with a proxy. The proxy, sitting in as the product of the factory, deligates all the received messages to the real sqlMapClient object, which can be replaced whenever the mapping files are modified. 4. make list of files to monitor from SqlMapClientFactoryBean's properties and sqlMapConfig files.
Limitations The list of files to monitor is determined on startup. It doesn't detect added files while running, and emits warning messages for removed files. For example, with a sqlMap file registered to a sqlMapConfig file, it is not monitored but those changes work when refreshed.
Requirements iBATIS sqlmap 2.3.0, Java 1.4, Spring 2.5+ or iBATIS sqlmap 2.3.2+, Java 1.5+, Spring 2.5.5+
Installation 1. replace SqlMapClientFactoryBean with newly created RefreshableSqlMapClientFactoryBean in applicationContext configuration file 2. specify modification detection check interval in milliseconds. 3. add backport-util-concurrent-3.1.jar to classpath.
정말 오래간만의 포스팅입니다. 오랜 동안의 공백기간 이후 이 사이트도 또 잠깐이나마 정상화할 수 있지 않을까 하는 기대를 해보면서 올려봅니다.
오랜 기간 숙원사업(?) 이었던 스프링과 iBATIS sqlMap을 이용해서 애플리케이션 개발/운영할 때 변경사항이 발생할 때마다 서버를 올렸다 내렸다하는 번거로움을 해소하기 위한 방법을 알려드리겠습니다.
일단 JCF 3.5 릴리즈에는 들어갈 것 같고요, 이미 여기저기서 아는 분들은 각자 만들어서 사용하고 계실만한 간단한 방법이긴 합니다만 그래도 정식 배포본에 들어가게 되었으니 언급은 하고 넘어가야겠지요?
- 착안 1. iBATIS 자체를 뜯어고치지는 않는다. 대신 스프링의 SqlMapFactoryBean을 교체 (IoC 컨테이너라 편리) 2. 실행 중 sqlMapClient를 교체하기 - 프록시 처리 및 수행 성능을 고려한 concurrency 처리 3. sqlMap 또는 sqlMapConfig의 xml이 변경되면 자동으로 리로드하도록 파일 감시. 4. Java 1.4, iBATIS 2.3.0, Spring 2.x 조합과 Java 1.5+, iBATIS 2.3.2+, Spring 2.5.5+ 조합간의 차이 처리
나머지는 Javadoc으로 대신합니다. (가만 보니 수동 리로딩에 대한 언급은 빠져있군요.)
RefreshableSqlMapClientFactoryBean iBATIS sqlmap 클라이언트의 sqlMap 및 sqlMapConfig 파일의 변경을 감지, 실시간 적용하는 팩토리 빈.
개요 iBATIS + Spring 개발시 쿼리 매핑 파일이 변경되면 웹애플리케이션 서버를 재기동해야 적용이 됐었다. 이러한 불편을 없애기 위해 매핑 파일 변경을 실시간으로 감시, 적용하는 모듈을 제공한다. 감시 대상 이 모듈은 iBATIS sqlmap 클라이언트의 sqlMap 및 sqlMapConfig 파일의 변경을 감지, 실시간 적용해준다.
제약사항 감시 대상 파일들은 스타트업 당시에 결정된다. 그러므로 추가된 파일들에 대해서는 감지가 되지 않고, 삭제된 파일들에 대해서는 경고 메시지가 나온다. 예를 들어, sqlMapConfig에 sqlMap 파일이 추가되거나 하면 해당 맵이 적용되기는 하지만, 실시간 변경 감지 대상으로 추가되지는 않는다.
요구사항 iBATIS sqlmap 2.3.0, Java 1.4, Spring 2.5 이상 또는 iBATIS sqlmap 2.3.2 이상, Java 1.5 이상, Spring 2.5.5 이상
적용 순서 1. Spring의 applicationContext 설정 파일 중 sqlMapClient를 얻기 위한 SqlMapClientFactory 빈을 신규 클래스로 교체한다. 2. 변경 감지 시간 간격 (1000분의 1초 단위)를 지정한다.
3. 라이브러리 추가 backport-util-concurrent-3.1.jar 테스트 기존의 applicationContext에 등록되어 있던 sqlMapClient에 해당하는 mappingFile들을 편집하거나, sqlMapConfig 파일 또는 그 파일에 등록된 mappingFile(sqlMap 파일)들을 편집하면 주어진 변경감지 시간 후 변경사항이 적용된다.
최근 다수의 회사들이 생산성, 재사용성, 유지보수성, 품질보증 등 자사의 애플리케이션을 견고하게 하고 아웃소싱을 통해 개발되는 애플리케이션을 수치화, 정량화된 데이터를 통해 통제하고자 전사 표준 프레임워크를 구축하거나 도입하고 있습니다.
이와 같이 전사 표준 프레임워크를 구축하고 도입하는데 있어서 고려해야 할 사항들에 대하여 잘 정리하고 있습니다. 저희가 새롭게 시작하고자 하는 일에 많은 도움이 되는 내용들이 있어서 나름대로 느끼는바가 많습니다.
그럼 시작...
어느 정도 규모가 있는 소프트웨어 관련 회사라면 생산성, 유지보수성을 높이고 개발자의 학습비용을 줄이기 위해 전사 표준
프레임웍을 도입하고 있습니다. 그리고 잘 아시듯이, 그런 프레임웍들은 대부분 자바의 오픈소스 프레임웍들의 기반으로 해서 추가,
확장 개발되어 있습니다. 그동안 제가 몇 개의 전사표준 프레임웍을 접하면서 최종 어플리케이션 개발자로써 가지게 된 생각을 정리해
봅니다.
아래 내용은 어느 특정 회사의 프레임웍에만 초점을 두고 있는 내용은 아닙니다. 구체적인 코드의 예까지 들고 싶은 내용도
있지만, 여러 프레임웍에 해당하는 내용일지라도 공개적인 웹사이트에 그렇게 자세한 내용을 올릴 수 있는 전사표준 프레임웍은
오픈소스정책을 펴고 있는 애니프레임 밖에 없습니다. 그래서 지나치게 특정 프레임웍의 대한 비판으로만 해석될까봐 코드 예시는
이 글에는 포함시키지 않았습니다.
첫째, 기존 오픈소스가 제공하는 있는 기능을 중복구현하거나 감싸서 개발할 때는 그 의도를 어플리케이션 개발자에게 알려야
합니다. 오픈소스에서 유사한 이런 것이 있는데, 이런 이유 때문에 따로 작성했다던지, 래핑을 시켰다는 것을 명시해 두면
어플리케이션 개발자들이 그 모듈을 활용하는 할 때 도움이 될 것입니다.
more..
예를 들어, apache commons의 유틸리티들을 래핑한 클래스를 작성했다면, '이 클래스는 자주 반복적으로
나타나는 몇 개의 호출패턴을 묶어서 새로운 클래스로 래핑을 했고, 만약 이 클래스에서 수용할 수 없는 기능이 필요할 때는 직접
apache commons의 API를 호출하면 된다'라는 정도의 안내 문구와 내부에서 참조하는 API문서의 링크정도가 제공될 수
있습니다. 그렇게 한다면 개발자는 해당 클래스를 설계자의 의도대로 사용하면서도 추가로 필요한 기능에 대해서도 유연성 있게
대처할 수 있습니다. 그리고 래핑도 아닌 중복된 구현이라면 '널리 쓰이는 xx클래스의 xxx메서드보다 성능비교에서 더 뛰어난
결과가 보여서 이 클래스를 추가했다. 해당 오픈소스 커뮤니티에도 이 사실을 문의를 했고, 만약 다음 버전의 패치에서 우리가
제안한 구현방식이 적용된다면 차후에 이 클래스는 depreciate 될 수도 있다.'라는 식으로 안내를 할 수 있을 것입니다.
개발자들이 이해할 수 있는 명확한 이유를 문서화 해서 '몰라서 그 모듈을 안 쓴 것은 아니다.'것이 전달되어야지 전사 프레임웍을
만드는 팀이 더욱 신뢰를 얻을 수 있습니다. 유명 모듈과 기능이 중복이 되면서도 그 의도를 알 수 없는 코드를 발견하게 되면,
그 코드를 작성한 사람이 작업량을 많아 보이게 해서 성과를 과장해서 인정받을려고 이런 코드를 더 짠 것이 아닐까 하는 의심까지도
생기게 됩니다.
프레임웍에서 추가로 클래스가 하나 늘어날 때의 댓가는 코드 작성 비용 외에도 문서화, 교육, 지원 비용이 있음을 다 들
알고 계실 것입니다. 유명한 공개 모듈을 활용하면 대략적인 안내와 API문서 링크, 참고할 웹페이지와 책목록만 안내 문서에
넣어주면 끝날 일이 중복 구현시에는 새로 API문서 작성, 문의 답변, 디버깅 지원, 추가 확장 등의 짐이 따라 붙게 되어
있습니다. 전사프레임웍은 API는 회사의 자산이자 부채라는 말을 실감할 수 있는 예입니다. 1 그리고, 동등한 기능이라면 특정 회사 내에서만 쓰는 모듈보다는 회사 밖에서도 많이 쓰이는 모듈이 개발자들의 학습의욕을 더 불러 일으킬 수 있을 것입니다.
둘째, 사내에서 만든 기존 모듈도 지속적으로 개선하고, 때로는 과감히 버릴 수도 있어야 한다고 생각합니다. 기존 모듈의
가치를 지나치게 높게 평가하지 않고, 인터페이스와 구현을 끊임없이 재검토 되어야 합니다. 팀 내에서 높은 직급의 사람이 만들었던
코드라도 마찬가지어야 할 것입니다.
more..
인터페이스를 바꾸지 않고 개선하는 작업은 하위버전 호완성의 문제 없이 지속적으로 할 수 있을 것입니다. 그것을
넘어서서, 기존 모듈과 유사한 기능의 널리 알려진 오픈소스 모듈이 있을 때 기존 인터페이스를 포기할 수도 있어야 한다고
생각합니다. 물론 이미 잘 돌아가는 유지보수 중인 시스템에서도 프레임웍 모듈을 바꾸라는 말은 아닙니다. 다만, 프레임웍을
버전업할 때 기존 개발자들의 학습비용을 이유로 회사 밖에서는 널리 쓰이고 있는 모듈과 그 사용방식의 도입이 잘 되지 않는
현상을 염려해서 하는 말입니다. 기존 개발자가 새로운 모듈을 학습하는 비용도 고려해야 겠지만, 새로 투입될 개발자들의 학습비용을
생각한다면 되도록 참조자료가 많고 개발 경력자가 많은 모듈이 유리할 것입니다. 이직과 업무 변경이 자주 있는 S/W 업계의
특징을 생각해본다면, 더욱 그러합니다.
예를 들면 스프링의 새로운 버전에서 지원되는 기능이 기존의 전사표준 프레임웍에도 존재한다면, 과감히 기존 모듈은 시간을
두고 depreciate 시키는 전략을 쓸 수도 있습니다. 이럴 때는 점진적인 업그레이드 전략을 가지고 신,구버전의 방식을
동시에 지원해 나가는 단계도 필요할 것입니다. 물론 기존 운영 중인 시스템의 프레임웍 버전 교체를 하는 상황이 많아서 100%
하위호환성을 가지고 가야하는 경우도 있습니다. 그러나 그렇기 않은 경우라면, 유명 모듈이 존재하는 범용적인 기능 부분에서는
기존의 인터페이스와 설정방식을 살리기 위해 적절한 시점에 모듈을 못 버리는 것이 오히려 더 많은 학습비용을 미래에 남길 것이라고
생각합니다.
셋째, 프레임웍의 개발단계에서도 결정사항과 주요 설계의 의도들에 대한 것들은 문서로 남겨지고 공유되어서,
어플리케이션 개발자들의 피드백을 받아야 한다고 생각합니다. 보통 모듈 공개 이후에 개발자들이 웹단의 프레임웍 선택
기준이라던지, 모듈의 설계에 대해서 많이 문의를 합니다. 그 때도 답변 담당자가 검토과정을 알지 못하면 상세한 대답을 하기가
어려울 것입니다. 'XX 프레임웍은 검토했던 담당자가 지금 여기에 없어서 저도 자세히는 모르겠네요. '라거나 '지금은 그 때 그
모듈을 작성했던 개발자가 없어서 확실히는 모르겠으나, 제 추측으로는...'라는 내용이 포함된 답변을 본적도 있습니다. 프레임웍
개발팀 내부의 업무 인계나 개발자들의 반복적인 문의를 잘 처리하기 위해서라도 그런 내용의 정리, 공유는 필요합니다. 그리고 그런
문의들은 결정사항이 확정된 후에 그것을 돌이킬 수 없을 때가 아닌, 검토 과정 중에서 받아서 실무 개발자들의 경험을 충분히
활용하고 더 많은 사람들의 지식을 모을 수 있어야 합니다.
more..
"Spring MVC 등 다양한 프레임웍을 검토했으나, 웹단의 ajax지원 태그라이브러리에 장점이 있는 프레임웍이 저희 조직이 행하고 있는
유형의 어플리케이션 개발에 가장 생산성 향상을 가져다 줄 것으로 판단하여 Struts2를 기반으로 하여 만들어졌습니다." 정도의
내용이 프레임웍 안내 문서에 포함되어 있다면, 개발자들의 의구심과 고민을 더 줄여줄 수 있지 않을까요? 그리고 '저희 팀에서
이미 Struts2의 태그라이브러리를 활용한 샘플들이 많으므로 배포 때 같이 포함되면 다른 팀에도 도움이 될 것
같습니다','현재 코드 중 이런 부분은 훨씬 짧게 줄일 수 있습니다' 라는 것 같은 피드백을 미리 얻을 수도 있다면 훨씬 더
개발과정이 수월해 질 것 입니다.
넷째, 배포되는 모듈과 샘플들은 최종 확정 전에 엄격한 설계 검토와 코드리뷰가 이루어 져야 합니다.
more..
큰 틀의 설계는 한번 확정되면 그 유산을 계속 짊어지고 가야하니 더욱 더 신중해야 합니다. Spring-batch
프로젝트의 예를 봐도 작년에 나왔던 마일스톤 버전의 인터페이스와 현재의 버전은 확연히 그 모습이 다릅니다. 최고의 개발자들이
모인 스프링개발 조직에서도 숙고와 재검토를 반복한다고 보여집니다.
그리고 구현에서도 바람직하지 않은 코드가 배포되었을 때도 문제 해결 지원, 재작성, 수정 비용 뿐만이 아니라, 프레임웍
개발팀의 신뢰하락이라는 치명상을 입힐 수도 있습니다. 큰 문제가 안 되는 사소한 코드라도, 일반적인 Java의 코딩원칙과 명백히
어긋나는 코드를 발견하게 되면, 다른 잘 된 부분의 코드들까지도 다 평가절하되어 버릴 수 있습니다. 언젠가 Effective
Java에 나오는 내용조차도 지키지 않은 코드들을 프레임웍 내부코드에서 만난 적도 있었는데, 프레임웍 개발팀 중에 한명이라도
이런 기초적인 것도 모르는 사람이 있으니 어딘가에 또 문제가 될 수 있는 코드가 있지 않을까 하는 걱정이 생기더군요. 프레임웍
개발팀은 회사전체에서 실력있는 분들이 모인 곳이라고 알고 있으니, 서로 검토만 한다면 일반 개발자들보다 훨씬 높은 품질의
코드를 만들 수 있을 것입니다. 그리고 PMD, findBug, JDepend 같은 코드검사툴도 적극활용하는 것이 좋겠고,
이미 프레임웍 개발팀정도면 대부분 그렇게 하고 있는 것으로 알고 있습니다.
다섯째, 프레임웍을 현장에서 적용할 때 선택할 수 있는 사안들이 유연하게 제공되고, 각각의 장단점과 선택의 기준등이
제시되었으면 좋겠습니다. 전사표준 프레임은 개발자들을 가두어 두는 벽이 되어서는 안 되고, 든든하게 딛고 뛸 수 있는 바닥이
되어야 할 것입니다. 그래서 그런 프레임웍에 모듈의 조합이나 설정 파라미터 등에 있어서 다양한 선택이 존재하는 것은 당연한
일입니다. 그러나 각 프로젝트마다 많은 선택의 조합들을 다 검토할 수 있는 여력이 안 되고, 구체적인 선택기준이 없다면 오히려
그런 선택의 폭들은 짐이 됩니다. 프로젝트에서 목소리 큰 사람의 의견대로 흘러가서 동의하지 못하는 구성원들이 생긴다면 갈등의
소지까지도 될 수 있겠습니다.
more..
어떤 프레임웍에서 DB access Layer를 Hibenate나 iBatis를 다 쓸 수 있게 안내하고 있다면,
'기술 리더를 할 사람 중에 ORM을 이용한 개발경험이 없고, 기존 Legacy시스템의 SQL 쿼리를 바로 활용할 수 있는
상황이면 iBatis가 유리하다'라는 식의 안내가 자세히 들어간 적용가이드, 실무적용 사례 등이 제공될 수 있을 것입니다.
선택을 하기 위한 점수채점표, 체크리스트 등이 제공될 수 있다면 더욱 유용할 것입니다.
여섯번째, 오픈 소스 프레임웍을 매개로 조직의 경계를 넘어선 공동작업을 시도해 보아야 한다고 생각합니다. 회사와 업계를
막론하고 Java 오픈소스 기반의 프레임웍들은 많이 쓰이고 있습니다. 그래서 많은 조직들에서 같은 고민들을 조직마다 따로 동시에
하고 있을 것으로 추측됩니다. 이런 상황에서 적용사례, 활용팁, 문제해결 사례, 프레임웍 간 비교검토 결과 등의 자료 공유와
코드 공유, 공동의 교육과정 개설 같은 일이 이루어 질 수 있다면 상호이익이 될 것입니다. .
more..
위키노믹스라
는 책의 6장을 보면, 관련 업계 전체가 협업한 사례로 인간 유전자 지도 연구 프로젝트가 나와 있습니다. 이것은 수많은
제약회사에서 독점적으로 진행하던 유전자 프로젝트를 포기하고 개방적인 협업에 동참하도록 한 중요한 분기점이 되었다고 합니다.
어짜피 제약회사의 수익은 신약개발을 통해 이루어지는 것이기 때문에 그에 기초에 되는 유전자 지도를 공동으로 연구하면 들어갈
비용을 줄일 수 있다고 생각한 것이죠. 유전자 염기서열이 완제품이 아닌 재료로 쓰일 자원인것과 마찬가지로, 전사 프레임웍은
최종적으로 수익을 창출하는 서비스 개발이나 사업수행을 위한 것입니다. 내부의 성과물을 밖으로 꺼내놓고 외부 의견을 수용할 수
있는 조직이라면 외부인재 활용하면서 비용을 절감하고 혁신속도 향상시킬 수 있는 보답을 얻을 것입니다.
예를 들면 웹단의 프레임웍을 비교를 하는 보고서를 써야 한다면 다른 업체에서 내놓은 보고서를 참고할 수 있다면 더 깊이 있는 검토를 할 수 있을 것입니다.2 중복해서 쓰지 말아야할 것은 코드뿐만이 아니고, 자료작성, 문제해결 탐색에 쓰는 시간도 마찬가지 입니다.
지금까지 나온 내용을 정리해보면 다음과 같습니다. 오픈소스 모듈을 래핑하거나 중복된 기능을 구현할 때는 의도를
개발자에게 알리고, 기존 모듈에 대해서도 개선을 해나가면서 때로는 과감히 범용적인 모듈로 교체할 수 있어야 합니다. 그리고
개발과정 중에서도 주요 결정사항과 설계안을 공유해서 피드백을 받고, 최종배포 전에는 설계안과 코드를 엄격하게 검증해야 합니다.
그리고 배포 후에는 유연한 선택 사항들과 구체적인 선택 기준을 제공하는 적용가이드를 제공하고, 회사 조직의 경계를 넘어선 협업도
모색해 보는 것이 좋습니다.
이런 것들을 이루는데 기술적으로는 스프링 프레임웍이 든든한 토대가 되어줄 것은 확실합니다. 잘 아시는 것처럼 유연한 구조로 인한 확장성, Spring portfoilo에
서 제공하는 폭넓은 기능의 모듈들, 빠른 발전 속도와 안정된 하위호환성, 그리고 세계적으로 많은 사용자로 인한 튼튼한 사용자 층
등이 그 이유입니다. 그리고 스프링프레임웍의 공식포럼들을 이용해서 외국개발자들과도 정보를 주고 받음과 동시에 우리 KSUG(http://forum.ksug.org )의 포럼을 통해서도 조직의 벽을 넘어서서 성과물 공유를 할 수 있을 것입니다.
이에 대해 maven archetype:create goal이 DEPRECATED 되었다는 소식을 듣고 mvn archetype:generate 로 전환을 시키기 시작했습니다. 그러나 여기서도 역시 마찬가지 오류가 발생을 합니다.
local repository를 지우고 central repository로 붙어서 해보니 되는 것 같습니다.
그래서 혹시나 하고 internal repository를 엎어보았습니다.
그러나 역시 안됩니다.
프록시 대상 repository들 중에서 엉뚱한 artifact를 올리고 있는 게 있나 해서 하나씩 날려보다가, velocity 쪽이 pom 파일이 안올라가서 따로 올려놓은 게 보입니다. 왜 그랬었는지 생각이 안나서 그냥 지워보았습니다만 역시 안됩니다.
archetype plugin이 아무래도 velocity와 연관이 있을 것 같아서 좀 더 자세히 알아보고자 구글링을 했더니 velocity:velocity:pom:1.5가 central repository 상에서 pom에 기술된 위치와 다른 엉뚱한 디렉토리에 설치되어 있어서 artifactory에서 거부를 하고 있는 것이었습니다.
좌우당간 해당 velocity-1.5.pom을 받아서 grooupId를 수정한 후, 강제 설치했습니다.
이제 잘 굴러갑니다.
-- 3줄 요약 -- 1. archetype:generate가 안되는 현상 발생 2. maven central repository 관리의 문제로 velocity 1.5 pom 파일의 정합성 오류가 있다. 3. internal repository에 수정본 업로드하여 1의 문제 해결