Whiteship's Note


오랜만에 다시 본 애니프레임

모하니?/Thinking : 2008.11.11 15:50


얼마만에 살펴보는 건지 모르겠지만, 많이 발전한 것 같은 느낌입니다. OSAF를 공개하고나서 프레임워크 공개가 얼마나 쉽지 않은 일인가.. 얼마나 챙길 것이 많은지를 몸소 채험하고 있는 와중에 애니프레임을 보니까 뭔가 느낌이 새롭습니다. 깔끔한 홈페이지부터 잘 정리되어 있는 문서화가 정말 부러웠습니다. 크게 Core랑 Web이랑 Tool과 예제가 있고, 그 중에서 Core, Web을 봤더니 다시 메이븐으로 세세 하게 다시 나눠 두었습니다. 보면서 몇 가지 놀라웠던 걸 정리하겠습니다.

1. 프레임워크 외적인 요소.

깔끔한 홈피와 다량의 문서화가 부러웠습니다. 사용자와 그들의 피드백을 받고 있다는 것두요. 이것도 어쩌면 일종의 피드백을 드리는 것이오니.. 제가 지금 뭘 하고 있는거죠? ㅋㅋㅋ OSAF 홈피 가꿔도 모자랄 판에 지금 애니프레임 리뷰를 해주고 있다니 ㅠ.ㅠ 그래도 괜찮습니다. 많이 배웠거든요.

2. 하이버네이트 학습 테스트

가장 놀랜건 hibernate 모듈이었습니다. HQL을 XML에서 읽어오는 서비스였습니다. 해당 기능을 제공하는 서비스 인터페이스와 구현체 하나씩을 제공하는 모듈입니다. HQL 변경하기도 쉽고 담당자가 일괄적으로 관리하기 편하겠죠.


왼쪽에 패키지 명들을 쭉 보면.. 감탄만 나옵니다. 거기에 테스트 클래스를 작성한 걸 보면 코드 뿐만이 아니라 테스트 하고자 하는 시나리오를 적어 둔 걸 볼 수 있습니다. 남을 고려한 코드가 바로 저런게 아닌가 싶더군요. 저도 개인적으로 하이버네이트 학습을 하면서 만든 학습 테스트들이 쫙 있는데 요즘은 시간이 지나서 찾아 보려고 해도 해당 테스트가 뭘 테스트 했는지 천천히 코드를 읽어보기 전까진 알기 힘든데.. 정말 좋은 방법인 것 같습니다. 한 수 배웠습니다. 하이버네이트 RI 프로젝트를 진행할 땐 저런식으로 해야겠습니다.

3. 코드 원 저자 표시 분명해짐


제가 예전에 봤을 때는 유겐이나 로드 존슨의 이름도 없이 그들이 작성한 코드를 여러 곳에서 발견할 수 있었습니다. 그걸 보고 감정이 상해서 글을 좀 겪하게 썼었는데요. 이번에는 그런 코드가 없는 것 같습니다. 이런 원저자 표기는 시각적으로, 이성적으로, 감정적으로도 여러 긍정적인 효과를 준다고 생각합니다. OSAF아직 원 저자를 표시해 줄만한 코드가 없다보니 전부 Author Toby, Whiteship 입니다.

4. private static Log(X)


이것도 역시 지난 번에 지적했었던 문제 같은데 고쳐졌습니다. 수정하신 분인 임수연님 이신듯 한데요. 이 분이 애니프레임워크에서 hibernate를 포함하여 상당히 많은 부분에 기여(?라고 하긴 좀 그런가요.ㅎㅎ) 하신 것 같네요. OSAF도 이 부분은 일찌 감치 사부님의 지시하에 private static을 사용했었죠. 그래서 저는 한동안은 원래 private static으로 하는 거구나.. 로 알고 있었습니다.ㅋㅋ
이 부분은 http://wiki.apache.org/jakarta-commons/Logging/StaticLog 이 글 혹은 http://whiteship.me/1637 이 글을 참조해서 수정이 필요합니다.

5. 애스팩트도 사용하는 구나...


사용 예제 뿐만 아니라 프레임워크에서 제공하는 Aspect도 있습니다. 성능 모니터링에 사용할 애스팩트 같은데 좋쵸 그런거 제공해주면.. OSAF도 지난 스프링 세미나에서 발표했던 애스팩트 중에 쓸만한 것들은 포함에서 M2 때 공개해야겠습니다.

6. 작명 규칙이 뭔가 맘에 안드네

그렇다고 좋은 것만 눈에 띄진 않았습니다. 인터페이스를 표기할 때 I(영문 대문자 아이)를 붙이기로 한 것 같은데 저에게는 저런 표기가 좀 낯설어서 그런지 코드 보기가 불펴했습니다. IPropertyService = 아이프로퍼티서비스. 그럼 구현체는 그냥 PropertyService인가... 아니요. PropertyServiceImpl 입니다. 그럼 그냥 인터페이스는 PropertyService라고 하고 구현체는 뒤에 Impl을 붙이는 걸로 구분하는게 낫지 않았을까 싶은데.. 뭐 개발팀에서 정할 일이니 모르겠습니다. 기왕 스프링 기반 프로젝트면 스프링 작명 스타일을 따르는게 좋치 않을까 하는 개인적인 소망입니다. OSAF는 스프링 작명을 따르고 있습니다.

7. 예제 코드의 수많은 설정 파일

자바 1.5 미만 프로젝트를 지원하기 위해서겠지만, 설정 파일이 정말 많네요. 이건 뭐.. 어찌해야 될런지.ㅋㅋ;;; 새삼 OSAF는 설정 파일이 정말 없는거구나 하는 생각이 들더군요.


예제 코드의 applicationContext만 저정도... OSAF는 물개선샌님께서 설정 파일이 없어서 어디서 설정한 건지 알 수가 없었다는... 후훗. 애노테이션이 다 그렇쵸 뭐.ㅋㅋ 장단점이 있는 것 같습니다. 애노테이션으로 하면 설정을 한 군대에서 볼 수 없으니 답답하고, 세부 내용이 기본값 등으로 숨겨져있을 수 있어서 뭔가 명시적이지가 않은데, 설정 파일 수는 줄어 들고 소스코드랑 그와 관련된 설정이 한 군대에 있으니까 소스 코드 보면서 설정 보기도 편한데 반면.. XML은 블라블라브라ㅡㅏ브ㅏ..

8. 웹 예제.. 좀 짱인듯

웹 예제를 보니까 스프링 시큐리티, 재스퍼 리포트, Flex, Ajax, 캬오.. 너무 많은 내용이 하나의 예제에 들어가있는것이 아닌가 싶었습니다. 돌려보진 않았습니다. parent 폼을 못찾아서 지금 모든 프로젝트가 다 빨간 불이거든요.ㅋㅋ OSAF와 비교해 보면 태그 파일이 전혀 없습니다. 커스텀 태그는 몇 개 보이던데 OSAF가 제공하는 화면 컴포넌트 같은 것은 없습니다. JSP는 여전히 노가다로군요. 이 부분에 대한 프레임워크 지원은 미약했습니다. 화면 컴포넌트는 OSAF가 짱입니다.

9. 약간 아쉬운 거 '틀'

DAO 구현에 어떤 틀이 있는가? 조금 애매합니다. 그냥 일반적인 스프링을 사용한 DAO 구현처럼 보이기도 하는데, 쿼리를 보내는 부분은 애니프레임이 제공하는 쿼리 서비스를 사용해서 합니다. OSAF와는 정반대의 모습니다. GenericDAO라는 확실한 틀을 제공하고 쿼리는 자율에 맡기고 있습니다.

Service 구현에도 어떤 틀은 없네요. CRUD같은 반복적인 코드도 DAO와 마찬가지로 직접 일일히 구현해야 합니다. 예제를 보니까 DAO와는 달리 서비스 쪽은 인터페이스를 사용해서 만들고 있습니다. 흠~ 인터페이스를 쓰려면 DAO도 쓰고 안 쓰려면 Service도 쓰지 말지 왜 그렇게 했을지 좀 의아했습니다. 어쨋든 어떤 틀 같은 건 없었습니다. OSAF는 GenericService를 제공하죠. 두 종류의 GenericService를 제공하는데 하나는 Context가 있는 것(다른 것에 종속하는 것)이고, 하난 없는 것(독립적인 것)입니다.

컨트롤러 구현에는 어떤 틀이 있습니다. 위에서 본 코드 중에 하나인 AnyframeFormController 같은 것을 상속하여 컨트롤러를 만들고 있습니다. OSAF도 두 종류의 GenericController를 제공하여 컨트롤러 구현을 매우 간편하게 할 수 있도록 멋진 기능을 제공하고 있죠. 애니프레임이 제공하는 컨트롤러를 쓰더라도 상당 부분의 코드느는 스프링을 그냥 썼을 때와 비슷해 보입니다.

결론적으로.. 애니프레임의 프레임이라는 것이.. 조금 불투명해 보인다는 것입니다. OSAF 처럼 확실한 틀이 안 보입니다.

10. 발전한 모습에 정말 놀랐습니다.

몇 개월 전에 봤던 그 프레임워크가 맞나 싶을 정도로 많이 발전한 모습이고 코드 곳곳에서 노력하신 흔적을 볼 수 있었습니다. 샘날 정도로....

이것으로 상당히 긴 애니프레임 리뷰를 마치겠습니다. 몇 달 전엔 죄송했습니다. (__)/
top


[KSUG] 스프링 AOP 선택, 활용, 이슈 - 스크린캐스팅

Spring/KSUG : 2008.11.11 08:56




위 링크에서 동영상 링크를 사용하여 mov 파일을 다운 받으시거나, 퀵 타임 플레이어가 설치되어 있다면, 웹에서 바로 보실 수도 있습니다.

발표를 하고 2주 정도 지난 다음 녹화를 한 건데, 스크린캐스팅을 좀 짧게 찍고 싶어서 총 다섯 개로 나눠서 한 편당 10~15 내외로 찍었습니다. KSUG 블로그를 통해서 한 주에 한 편식 올리겠습니다. 쉬는 시간 짬짬히 구경해 주세요. :)

이번에 올린 동영상은 AOP에 대한 내용인데, AOP 자체에 대해서는 깊게 알지 못하기 때문에, 제가 아는 한도 내에서만 살짝 살펴봤습니다. 따라서 내용이 다소 수박겉할기식으로 느껴질 수도 있는데요. 첫 번째 동영상의 목적은 AOP에 대해 자세히 설명 드리는 것이 아니라 AOP라는 개념을 프로젝트에 도입하면 어떤 도움을 받을 수 있는지 좀 더 현실적인(코드를 통해서) 감을 잡게 해드리는 것이 목적이기 때문에 그다지 AOP 개념이나 역사에 대해 자세히 다루진 않았습니다. 가볍게 보실 수 있겠죠.ㅋ

어느새 점심 시간이네요. 식사 맛나게 하세요.

updated 2008/11/11

이번에는 스프링 AOP에 대한 주제로, 코딩으로 Proxy 만드는 방법, 스프링 API 사용 방법, XML 스키마 사용 방법, @AspectJ 사용 방법, AspectJ 연동 방법까지 살펴봅니다.

next 2008/11/18
top


IntelliJ도 좋아보이는데.. 상용인게 안타깝네요

Good Tools : 2008.11.10 23:56


스프링 2.5랑 DM까지도 기본으로 지원해줍니다. 플러그인 설치가 필요없죠. CSV를 비롯한 SVN 등 여러 소스 버전 관리 툴도 기본으로 지원해줍니다. 상용이라는 거 빼곤 단점을 찾아보기가 힘드네요. 일단 단축키를 모르고 세부 기능을 잘 모른다는 것이 제 문제이기는 한데, 그거야 사용하면서 잘 알아나가면 될 것 같고... 흠.. 30일간은 무료로 사용할 수 있으니 한 번 써보세요~

http://www.jetbrains.com/idea/


사용자 삽입 이미지
메이븐 프로젝트도 아닌데, 프로젝트 만들 때 필요한 라이브러리 선택하면 알아서 lib 폴더에 넣고 클래스패스에 추가해줘요. 스프링+하이버 프로젝트 만드는거 완전 껌인데요.ㅋㅋ

메이븐도 물론 기본으로 지원, 멀티 POM 까지 지원해준다고 했으니 여기서 OSAF를 로딩하면 어떻게 될까? 궁금하네~ 생각난 김에 바로 ㄱㄱㅆ

사용자 삽입 이미지

오. M2Eclipse로 로깅한거랑 비슷하게 읽어오는군요. 심심해서 테스트도 돌려봤습니다. 캬~ 괜찮아요. 괜찮아.
top

TAG IntelliJ

리눅스 명령어 백스라운드로 실행하기

Linux : 2008.11.10 22:35


참조: http://blog.keduall.co.kr/lsb76/69

nohup 명령어 &

창을 꺼도 계속 돌아가도록 nohup 추가.
백그라운드로 실행여 콘솔창 볼 수 있게 & 추가.

자세한 건 몰라요.


top

Linux : 2008.11.10 22:35 Trackback. : Comment.

Why OSAF 1. 테스트 코드를 익힐 수 있습니다.

OSAF : 2008.11.10 22:04


OSAF를 공개한지 한 달이 아직 안 됐습니다. 10월 23일에 공개했었죠. 지금까지 약 200에 가까운 다운로드를 기록하고 있지만, 전혀... 아무런... 반응이 없다는 것에는 가히 놀라울 뿐입니다. 그냥 제가 쓴 글의 댓글 몇 개 정도 뿐의 관심이 저에게 한 편으로는 아쉬움으로 또 다른 한 편으로는 오기로 다가옵니다.

완전 최첨단 프레임워크인 OSAF에 왜 이렇게 관심이 없을까. 고민을 많이 했습니다. 어렵나? 메이븐 떄문인가? 그거 없어도 되는데. 문서가 부족하긴 부족하고. 그래도 어떻게 이렇게 조용할 수가 있지. 홈피 디자인이 좀 구리긴 한데.. 그거 때문인가? ㅋ. OSAF 발음이 너무 어려운가? 별에 별 생각을 많이 했습니다. 당연히 기운도 빠집니다. OSAF를 공개한 건 어쩌면 OSAF에게 못씁짓을 한 건 아닌지 말이죠.(Max님의 '어디가서 밥은 먹고 다녀야 할텐데..' 라는 댓글이 생각납니다.)

긍정적으로 생각하기로 했습니다. 언젠가는 빛을 보겠지. 열심히 계속 가꾸다 보면 언젠간 알아주겠지. 하고 말이죠. 그래서 OSAF가 여러분에게 어떤 도움을 줄 수 있을지 생각하고 알려드리기로 했습니다. 그 중 첫 번째가 바로 테스트 코드입니다.

OSAF의 테스트 커버리지는 60%가 조금 넘습니다. (앞으로 차차 올릴 예정입니다.) 60%의 테스트 커버리지는 전부 OSAF 개발팀에서 직접 작성한 테스트 코드입니다. 어딘가에서 배껴온 코드가 절대로 아닙니다. 테스트는 초기에 JUnit과 EasyMock을 사용해서 작성 했었습니다. 물론 스프링 테스트 기능도 사용하고 있죠. 배포 직전에는 EasyMock을 Mockito로 교체하여 비슷한 테스트를 보다 깔끔하고 직관적이며 적은 수의 코드로 대체할 수 있었습니다. DBUnit을 확장하여 OSAF가 제공하는 테스트 케이스를 이용하면 DAO 테스트가 매우 간편해질 것 입니다.

이렇게 좋은데... 한 번 들여다 보고 뭐라고 해주시지 않으시겠어요? 좋다. 잘했다. 고맙다. 이런거 말구요. 이 부분의 테스트는 이해가 안 된다. 테스트가 조금 이상하다. 이 부분의 테스트는 왜 안했냐. 어려워서 그런거냐? 이 부분의 테스트는 이렇게 고치는게 좋치 않겠냐? 이런.. 반응이 제가 가장 좋아하는 반응이자 OSAF에게 거름을 주는 방법입니다.

소스 코드는 굳이 다운 받지 않아도(장기적으론 받아 두시면 좋겠지만..)

http://www.opensprout.org:9060/browse/OSAF/osaf/trunk

위 링크로 가시면 웹에서 직접 볼 수 있습니다. 소스 코드나 OSAF 와 관련하여 문제나 제안하고 싶은 것이 있다면 주저하지 마시고 이슈를 등록해 주세요.

http://www.opensprout.org/jira/secure/Dashboard.jspa


top


SpringSource DM Server 이클립스 플러긴

Good Tools : 2008.11.10 14:47


참조 : http://static.springsource.com/projects/dm-server/1.0.x/programmer-guide/html/ch08.html

스프링소스의 프로젝트를 보면 신생 프로젝트들인데도 문서화가 정말 잘 하고 있는게 신기합니다. 전부 개발자들일 텐데(그 중에서 아는 이름은 Rob Harrop밖에 없지만) 개발 하랴 문서화 하랴 정말 대단합니다.

그건 그렇고 SpringSource DM Server(S2DS)를 이클립스에서 실행하려면 간단한 플러그인 설치가 필요합니다.

이클립스 업데이트 사이트: http://static.springsource.com/projects/sts-dm-server/update/

위 주소를 이용해서 플러그인을 설치하고 Server 뷰에서 New Server를 선택하면 다음과 같이 S2DS를 선택할 수 있습니다. 동영상에 보니까 프로젝트를 드래그 앤 드랍 하면 해당 번들을 설치해주던데.. 아직 해보진 않았습니다.ㅋㅋ



물론 저 서버를 생성하려면 OpenSprout에서 배포한. 혹은 자신이 직접 소스 코드에서 빌드한 S2DS 홈 디렉토리를 설정해 줘야 합니다.


서버 탭 구성이나 내용이 Tomcat 서버와는 좀 달랐습니다.


한 번 돌려봤는데 잘 동작합니다.



top


S2DS(SpringSource DM Server) build by OpenSprout 1.0.0

OSAF : 2008.11.09 23:47


스프링소스의 정책이 바껴서 커뮤니티 버전은 직접 빌드를 해야합니다. S2DS라는 멋진 툴 한 번 돌려 보시려면 얼마나 귀찮으세요. Ant로 빌드해야 되는데, readme.txt도 안 읽어보면 어디가서 빌드해야 되는지도 잘 모르겠고, 잘 찾아가서 ant를 실행한다고 해도 OutOfMemory라도 만나는 날에는 정말이지.. 아휴~.

그래서 저희 OpenSprout에서는 다운로드 후 바로 실행해 볼 수 있는 S2DS를 제공하고 있습니다. 빌드하기 귀찮으신 분들에게 이 보다 더 좋은 서비스는 없을 겁니다. 그냥 한 번 빌드해서 실행보려고 해도 갑작스런 에러때문에 당황스러울 수 있는데요. 그런 에러까지 이미 제가 마루타 삼아 겪어보고 빌드했기 때문에 믿고 사용할 수 있는 배포판입니다.

OpenSprout 빌드 서비스. S2DS뿐 아니라, 앞으로 SpringSource 모든 제품을 빌드해서 제공해 드리겠습니다. 완전 사랑스럽죠? 헤헷

다운받고 -> 압축풀고 -> bin/start.sh 실행 -> localhost:8080 접속.

사용자 삽입 이미지

짝짝짝짝짝짝..

다운로드
top


SpringSource Application Platform(S2AP)은?

Spring DM/etc : 2008.11.09 21:34


S2AP랑 S2DS랑 햇갈려서 찾아 봤더니 S2AP는 S2DS와 S2E를 포함한 것을 말하는군요.

참조: http://www.springsource.com/products/suite/applicationplatform

The SpringSource Application Platform is an end-to-end platform that is designed from the ground up for complete portability and scalability for today’s data center and for next-generation virtualized, grid, and cloud computing deployments. The Platform is a collection of products designed to provide the optimal environment to build, run and manage enterprise Java applications that utilize Spring based technologies, including:

[막 번역]
S2AP는 단대단 플랫폼으로 요즘 데이터 센서에 완전히 호환가능하며 확장성 좋도록 설계했고 또한 다음 세대의 가상화, 그리드 그리고 클라우드 컴퓨팅 배포를 고려하여 설계했다. 이 플랫폼은 스프링 기반 기술을 사용하는 엔터프아리스 자바 애플리케이션을 빌드, 실행 그리고 관리하는데 최적의 환경을 제공하는 제품들로 구성되어 있다. 다음을 포함하고 있다.

    *  SpringSource Enterprise delivers the software, services, and technical support necessary to ensure that your organization develops and runs Spring-powered enterprise applications more productively, securely and with the greatest uptime.
    * SpringSource dm Server is a completely modular, OSGi-based Java server designed to run enterprise Java applications and Spring-powered applications with a new degree of flexibility and reliability.

S2E: 스프링을 사용하는 엔터프라이스 애플리케이션을 보다 효율적이고, 잘 사용할 수 있도록 소프트웨어, 서비스 그리고 기술 지원을 한다.
- Spring Enterprise Edition
- SpringSource Perfomance Suite
  - SpringSource Tool Suite
  - SpringSource Application Management Suite
  - SpringSource Advanced Pack of Oracle
- SpringSource Support

S2DS: 완전 모듈화한, OSGi-기반 자바 서버로, 엔터프라이즈 자바 애플리케이션과 스프링을 사용하는 애플리케이션을 새로운 수준의 유연성과 신뢰도를 가지고 실행할 수 있다.
사용자 삽입 이미지




top

TAG S2AP, S2DS, S2E

개발자들의 수다 후기



1, 2, 3부 전부 "국내 XP 적용"을 주제로 이야기를 듣고 나누다 왔습니다. 뒷풀이는 따라가지 못했지만, "수다"가 발전하는 모습을 본 것이 인상적이었습니다.

1부는 주로 테스트에 관한 얘기를 했었습니다. 테스트 작성 비용 떄문에 오히려 일정이 늘어나서 프로젝트가 실패한 사례를 들을 수 있었습니다. 반면 테스트를 작성함으로써 얻을 수 있는 장점들도 들을 수 있었죠. 테스트 코드 작성 때문에 추가 시간이 필요하긴 하지만 장기적으로 봤을 떄 유지보수 시간을 단축시킨다는 측면까지 고려한다면 결국은 개발 시간이 늘어나는게 아니라 오히려 단축시키는 걸 수도 있겠다고 생각하고 있습니다. 그리고 페어 프로그래밍 적용에 관한 이야기도 들었는데, 이 것과 관련해서는 2부에서 더 많은 논의가 이뤄졌습니다.

2부에서는 주로 페어 프로그래밍에 관한 이야기를 나눴습니다. 맨먼스를 어떻게 고려할 것이며, 작업 할 당은 어떻게 하며, 짝을 어떻게 구성하는지, 개발팀원이 자주(6개월 내지 1년) 변경 되는 경우에도 가능한지와 관련하여 페어 프로그래밍 적용을 해보신 분들의 경험담을 들을 수 있는 아주 드문 기회가 있었습니다. 정말 흥미로웠고 저도 페어프로그래밍을 꼭 해보고 싶어졌고, 지금보단 좀 더 사람이 많은(10명 이내) 프로젝트에 참여 해보고 싶단 생각이 들었습니다. 2부도 1부와 마찬가지로 주로 경험이 있으신 분들의 발언이 많았는데, 김창준님의 등장으로 분위기가 새롭게 바꼈습니다. 좀 더 Agile 스럽게 바꼈다고 해야하나. ㅎㅎ

3부에서는 해당 주제에 모인 사람들이 자신이 듣고 싶거나 전달하고 싶은 주제를 제시하고, 한 사람당 세 표를 행사하여 가장 관심이 많은 주제 두 개를 다뤘습니다. 그 중 하나는 애자일 관련 도구에 관한 이야기였습니다. 그 자리에 계신 분들이 XP에 관심이 있으셔서 그랬던 건지는 몰겠지만, 이슈 트래커, CI 툴도 사용하고 계시고, 기본적으로 SVN이나 CVS 같은 소스 코드 관리 툴 뿐만 아니라, GIT까지 사용하고 있단 얘기를 들었습니다. 그 사용 사례에 대해 더 자세히 듣고 싶었지만 시간 관계상 그럴 순 없었습니다. 또 하나는 제가 궁금했던 거. 데이터베이스 스키마와 데이터도 소스 코드처럼 버전 관리를 할 수 있는 도구가 있는데 그것을 사용하고 있는지, 사용하고 있지 않다면 앞으로 사용할 계획은 있는지를 물어봤었는데. 데이터베이스의 데이터가 워낙 중요하고 스키마 변경도 조심스럽기 때문에 해당 도구를 얼마나 신뢰할 수 있느냐가 관건이라는 의견을 들을 수 있었습니다. 또 그 중에는 그런 비슷한 기능을 하는 툴을 직접 만들어서 사용하고 계신 분도 있었습니다. 3부에서 다룬 두 번째 주제는 국내 Agile 적용 데이터 마이닝이었습니다. XP 실천 사항들의 상관성을 살펴볼 수 있었고 조직의 성숙도와 Agile 적용 만족도의 상관 관계도 들을 수 있었습니다. 이와 관련된 자세한 내용은 조만간 김창준님께서 글로 정리하신다고 하셨습니다. 기대됩니다.

오늘은 어떻게 하면 좀 더 체계적이고 효율적으로 논의를 나눌 수 있는지 경험할 수 있었고, XP에 대한 관심이 한층 증가하는 날이 되었습니다. 조만간 XP 실천 사항들을 점검해 봐야겠습니다. 열 몇 개라던데 뭐뭐가 있는지 말이죠... @.@

'모하니? > 그냥 놀아' 카테고리의 다른 글

저는 이제 Alabama에 왔습니다.  (0) 2008.12.07
LA에서 보낸 하루(?)  (6) 2008.12.01
지금은 공항이에요  (8) 2008.11.30
LA, 마이애미, 아틀란타 날씨  (0) 2008.11.28
회사 이사 중  (2) 2008.11.21
개발자들의 수다 후기  (0) 2008.11.09
꺄오~~ 살꺼야. 키보드. 카시오 PX-320  (8) 2008.10.30
보고 싶은 피아노 공연  (0) 2008.10.22
방송탔네~  (0) 2008.10.01
KSUG 도배 성공  (2) 2008.10.01
HP CP1215 맥에서 사용하기  (0) 2008.09.25
top


대략난감 테스트 자동 생성기 Randoop

Good Tools : 2008.11.07 18:01


http://people.csail.mit.edu/cpacheco/randoop/1.2/doc/userman.php

처음 보고는 이야.. 아주 별에 별 도구가 다 있구나. 생각을 하고 과연.. 잘 만들어 줄까?? 라는 기대반 호기심 반으로 들려봤습니다.

테스트를 작성할 대상이 되는 클래스는 예전에 사부님이 시켜주신 TTD 트레이닝 중 하나 볼링게임. 그 중에서도 Frame이라는 클래스를 마루타 삼기로 햇습니다.

package domain;

import java.util.ArrayList;
import java.util.List;

public class Frame {

    List<Roll> rollList = new ArrayList<Roll>();
    protected Integer remainPinNumber = 10;
    private Integer number;

    public Frame(Integer frameNumber) {
        this.number = frameNumber;
    }

    public Boolean isEnd() {
        if (hasStrike() || rollList.size() == 2)
            return true;
        return false;
    }

    protected boolean hasStrike() {
        for (Roll roll : rollList)
            if (roll.getType() == RollType.STRIKE)
                return true;
        return false;
    }

    public void add(Roll roll) {
        setRollType(roll);
        remainPinNumber -= roll.getKnockDownPinCount();
        rollList.add(roll);
    }

    protected void setRollType(Roll roll) {
        Integer knockDownPinCount = roll.getKnockDownPinCount();
        if (rollList.size() == 0 && knockDownPinCount == 10)
            roll.setType(RollType.STRIKE);
        else if (knockDownPinCount == 0)
            roll.setType(RollType.GUTTER);
        else if (knockDownPinCount == remainPinNumber)
            roll.setType(RollType.SPARE);
    }

    public Integer getRollListSize() {
        return rollList.size();
    }

    public Integer getRemainPinNumber() {
        return remainPinNumber;
    }

    public Integer getScore() {
        Integer score = 0;
        for (Roll roll : rollList)
            score += roll.getScore();
        return score;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder("frame(");
        builder.append(number).append(", ");
        for (Roll roll : rollList)
            builder.append(roll.toString());
        builder.append(", ").append(getScore()).append(")");
        return builder.toString();
    }

    public List<Roll> getRollList() {
        return rollList;
    }

}
 
그리 복잡한 클래스는 아니지만 비즈니스 로직이 들어있죠. 저걸 대상으로 테스트 코드를 생성해봤습니다.

10초 동안 돌려서 만들어 봤습니다. 콘솔에 뭔가가 찍히는데 무슨 의미인지는 모르겠고 마지막에 생성된 파일 목록이 나오는데 다섯개나 만들어져있습니다.


저 중에서 RandoopTest.java는 테스트 스위트 파일이고 네 개의 소스 파일이 테스트 코드를 담고 있습니다.

문제는... 대체 뭘 테스트 한 건지도 모르겠는 코드가 14000~2만 라인씩 생성된다는 겁니다. 이클립스가 막 죽으려고 버버버벅 거립니다.

그 중에서 젤 간단해 보이는 걸 몇 개 보여드릴까요?


대략 난감입니다. 테스트를 돌리면 전부 성공하긴 합니다.


그냥 웃음 밖에 안나옵니다. 크하하하하... 저 수 많은 코드와 녹색불은.. 무슨 의미가 있을까요?


top


EJ2E Item 13. 클래스와 멤버 접근성을 최소화 하라

Java : 2008.11.07 10:02


참조: Effective Java 2nd Edition. Item 13: Minimize the accessibility of classes and memebers

잘 설계된 모듈은 내부 데이터 및 구체적인 정보는 외부 모듈로부터 숨긴다. 깨끗하게 구현체와 API를 분리해둔다. 그런 다음 오직 API만을 사용해서만 의사소통 하고 내부 동작은 다른 모듈이 알 필요 없게 한다. => information hiding 또는 encapsulation

Information Hiding이 중요한 이유
- 모듈간의 의존도를 낮춘다. decoupling
- 독립적으로 개발, 테스트, 최적화, 사용, 이해, 수정 할 수 있다.
- 여러 모듈 병렬 개발이 가능해져서 개발 시간을 단축시킨다.
- 유지보수 비용을 낮춘다. 이해하기 쉽기 때문에 빠르게 디버깅 할 수 있다.
- 재사용성이 좋다.
- 규모가 큰 시스템 개발시 위험을 감소시켜준다.

자바가 제공하는 information hiding 기반 시설
- acess control. 클래스 인터페이스, 멤버의 접근성을 기술하는 매커니즘.
- 적당한 지시자를 사용하는 것이 관건

제 1 규칙: 각각의 클래스 또는 멤버의 접근성을 가능한한 최소한의 접근성만 보장하라.

최상위 클래스 또는 인터페이스라면 두 가지 접근 레벨만 사용하면 된다.
- package-private
- public

멤버(필드, 메소드, 내부 클래스, 내부 인터페이스)는 네 가지 접근 레벨이 가능하다
- private
- package-private
- protected
- public

private과 package-private
- 클래스 내부 구현에 관한 것이지 외부로 노출한 API에 영향을 주지 않는다.
protected와 public
- 멤버는 외부로 노출한 API며, 영원히 제공되어야 한다. 구체 구현체와 외부와를 연결해주는 의사소통 수단이 된다.

메소드 접근성과 관련된 제약 사항
- 상위 클래스의 메소드를 재정의 할 때는 상위 클래스의 접근성보다 더 낮은 접근성을 제공하면 안 된다.[JLS. 8.4.8.3]
- 이를 어기면 컴파일 에러
- 인터페이스에 정의하는 메소드는 암묵적으로 public이 된다. [JLS, 9.1.5]

테스트를 할 때, 클래스. 인터페이스, 멤버의 접근성을 조금 높이는 경향이 있다. 즉 private에서 package-private으로 올린다. 거기까진 괜찮다. 그 이상은 올리면 안 된다. 테스트 때문에 외부로 노출하는 API가 되어서는 안 된다.

인스턴스 필드는 절대로 public이면 안 된다.
- mutable 객체의 경우 필드에 저장한 값을 제한하지 못해. 이런 클래스는 thread-safe 하지 않다.
- immutable 객체를 public final로 한다면 필드를 새로운 객체로 변경할 수 없게 된다.
- static 필드의 경우도 마찬가지다. 단 예외가 있다면 상수는 public static final도 제공한다.
- 길이가 0이 아닌 배열은 항상 mutable하다. 따라서 public static final 배열을 가지고 있으면 안 된다.

public static final 배열에 대한 대안.

private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
    Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

private static final Thing[] PRIVATE_VALUES = { ... };
  public static final Thing[] values() {
  return PRIVATE_VALUES.clone();
}


top

Java : 2008.11.07 10:02 Trackback. : Comment.

one A for every B 번역하기



얼핏보면 모든 B에 대한 하나의 A. 즉 모든 B가 하나의 A를 공유하는 것 같이 보이지만, 전혀~~ 전~~~혀 아닙니다. 완전히 틀린 번역이 되버립니다.

"각각의 B에 A 하나씩"

이게 정답입니다.

"the application now maintains one instance of the aspect for every target"

자 그럼 위의 문장은 어떻게 번역 or 이해해야 할까요?

"이제 애플리케이션은 각각의 타겟 객체 마다 애스팩트 객체를 하나씩 사용하게 된다."

이렇게 됩니다. 간혹 원서로 공부를 하시거나 번역을 하실 때 주의 하시기 바랍니다.
top

TAG Every, 번역

OSAF 1.0.0-M2는 스프링 2.5.6 기반 프레임워크~

OSAF : 2008.11.05 11:52


국내 최초 아니 어쩌면 세계 최초 스프링 2.5.6 기반 애플리케이션 프레임워크가 될지도 모릅니다. 크하하하. 최첨단 프레임워크니까 이 정도는 해줘야겠죠?

나오자마자 바로 업그레이드. 이럴 땐 메이븐이 편하긴 합니다. pom.xml에서 프로퍼티 사용해서 버전만 바꿔주면 되거든요.

    <properties>
        <slf4j.version>1.4.3</slf4j.version>
        <spring.version>2.5.6</spring.version>
        <java.version>1.5</java.version>
    </properties>

        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
...

뭐 이런 식입니다. 어떻게 사용하는지 대충 아시겠죠?

인증샷 올립니다



top

OSAF : 2008.11.05 11:52 Trackback. : Comment.

스프링 AOP에서 this와 target 포인트컷 표현식 구분 하시는 분?

Spring/Chapter 7 : 2008.11.05 11:42


Pro Spring 2.5에서 this 표현식에 대한 정의입니다.

the semantics of the this pointcut are such that it would match any method execution on an object whose class matches the specified expression, but how could we match any class in the com package and its subpackages? Therefore, the only allowed syntax is this(class-name),

Pro Spring 2.5에서 target 표현식에 대한 정의 입니다.

Because the target expression defines a pointcut that would match execution of any method on an object whose class matches the specified expression, we cannot use the wildcards.

뭐가 달라 보이나요??? 앞 부분에 어순이 약간 바뀐것 빼고는 도무지 차이를 알 수가 없습니다.

레퍼런스를 보죠.

this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type

target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type

레퍼런스는 그나마 좀 차이가 보입니다. this일 때는 프록시 객체고 target 일 때는 프록시를 적용할 타겟 객체가 주체가 됩니다.

즉, this 표현식은 주어진 타입에 해당하는 스프링 AOP Proxy의 조인포인트에 대응하는 표현식이고.. target 표현식은 주어진 타입에 해당하는 타겟 객체의 조인포인트에 대응하는 표현식이라는 것인데..

어차피 프록시 객체의 타입이 곧 타겟 객체의 타입과 동일하기 때문에 결과는 똑같을 것 같은데 말이죠. 차이를 모르겠습니다. 아흐.. 머리야..

마지막으로 AspectJ 문서를 보겠습니다.

this(Type or Id)
    Picks out each join point where the currently executing object (the object bound to this) is an instance of Type, or of the type of the identifier Id (which must be bound in the enclosing advice or pointcut definition). Will not match any join points from static contexts.

target(Type or Id)
    Picks out each join point where the target object (the object on which a call or field operation is applied to) is an instance of Type, or of the type of the identifier Id (which must be bound in the enclosing advice or pointcut definition). Will not match any calls, gets, or sets of static members.

this는 동적이고 target은 정적으로 타입을 지칭하는 차이밖에 없어보입니다. 흠.. 과연..

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="applicationContext.xml")
public class FooAspectTest {

    @Autowired
    FooBean fooBean;

    @Test
    public void isProxy(){
        assertTrue(fooBean instanceof Advised);
        fooBean.hi();
    }

}


@Aspect
public class FooAspect {

    @Pointcut("this(org.opensprout.spring.aop.thisandtarget.FooBean)")
    public void thisPointcut(){}

    @Before("thisPointcut()")
    public void say(){
        System.out.println("this pointcut executed.");
    }

}

스프링 AOP에서는 this를 target으로 고쳐도 똑같이 동작합니다. 콘솔에 메시지가 한 번 출력되죠. 그러나 AJDT로 실행하면, this의 경우 같은 메시지가 세 번 찍히고, target의 경우 같은 메시지가 네 번찍힙니다. 일단 두 번은 클래스 로딩이나 생성자 호출 조인포인트에서 찍혔다고 생각하고, 하나는 테스트에서 hi 호출 할 때 찍힌거고 가장 의아한건 target 표현식일 때의 마지막 한 번.

디버깅을 돌려본 결과 저 테스트에 두 번 들어가던데;; 왜 그런지 몰겠네요. 아~ 미궁이로 구나..
top


데이터베이스 변경 관리 툴 LiquiBase

Good Tools : 2008.11.04 23:45


http://www.liquibase.org/

소스 코드만 버전 관리하는 것이 아니라 데이버베이스 스키마를 버전 관리해서 지난 변경 사항 이력을 관리할 수 있고, 이를 자동화 하여 통합 빌드로 여러 명의 개발자가 하나의 스키마를 공유할 수도 있습니다. 데이터베이스 리팩터링에도 매우 유용할 것 같습니다.

대강 살펴본 주요 기능은 다음과 같습니다.
- 이클립스 플러긴으로 IDE도 제공합니다.
- Ant, Maven 지원.
- DBMS에 독립적
- 롤백 지원
- 동영상 데모 제공
- 데이터베이스 리팩터링 지원 http://www.liquibase.org/refactorings

무엇보다 홈페이지가 깔끔한게.. 마음에 드네요. 저것도 Wiki로 만든거 같은데... 흠.. OSAF 홈피보다 이쁘자낫;;;


top

TAG LiquiBase

EJ2E Item 12. Comparable 구현을 고려하라

Java : 2008.11.04 18:07


참조: Effecive Java 2nd Edition. Item 12: Consider implementing Comparable

compareTo는 Comparable 인터페이스가 제공한다. Object의 equals와 비슷하지만, 순서 비교가 가능하며, 동일성 여부도 알 수 있고 generic하다.(어떤 의미에서 generic 하다는 거지?) 이 인터페이스를 구현한 클래스는 정렬이 가능한 것으로 인식한다. 따라서 이 클래스 타입의 배열을 다음과 같이 정렬할 수 있다.

Arrays.sort(a);

String은 Comparable 인터페이스 구현했다. 알파벳 순으로 정렬 쉽게 할 수 있다.

public interface Comparable<T> {
  int compareTo(T t);
}

Generic 사용해서 타입 제한 할 수 있다.

제약사항
- 넘어온 객체보다 작을 떄는 음수 반환, 같으면 0 반환, 크면 양수 반환.
- 음수일 땐 -1, 같을 땐 0, 양수일 땐 1을 반환하는 함수 sgn(expression)이 있을 때
  -  sgn(x.compareTo(y)) == -sgn(y.compare-To(x))
  - (x.compareTo(y) > 0 && y.compareTo(z) > 0)이면, x.compareTo(z) > 0
  - x.compareTo(y) == 0 이때, sgn(x.compareTo(z)) == sgn(y.compareTo(z))
 - 권고 사항: equals 비교 했을 때 같은 객체끼리는 compareTo 결과가 0이어야 한다.

구현하기
- equals와 비슷하지만 타입 확인할 필요 없다.
- 캐스팅도 필요없다.
- null 일 떈, NullPointerException 던진다.
- 각각의 필드를 비교한다.

샘플

public int compareTo(PhoneNumber pn) {
  // Compare area codes
  if (areaCode < pn.areaCode)
    return -1;
  if (areaCode > pn.areaCode)
    return  1;
  ...

}


top

Java : 2008.11.04 18:07 Trackback. : Comment.

금강하나리조트 회원권 사기 조심하세요

모하니?/Thinking : 2008.11.04 16:17


무료 숙박권 10장이랑 10년 회원권인가를 준다고 전화가 옵니다. 사기입니다. 목소리도 완벽한 한국인이고 학생이 아닌지, 신용카드가 있는지 물어봅니다. 신용카드가 있으면 사기 대상이 됩니다.

사기 대상이 되면 두 번째 전화가 옵니다. 신용카드 정보를 요구합니다. 유효 년/월, 카드 번호, 뒷면의 핀 번호까지 요구합니다. 이건 정말 한국인입니다. 핀 번호를 요구하는데 정말 알아듣지 못할 이야기로 아주 빠르게 이야기를 합니다. 전 정말 핀번호를 요구하는게 이해가 안되서 계속 물어보고 또 물어봤는데 이 번호가 왜 필요하냐고 말이죠. 계속 이해 못할 소리로 승인이 되는데 지네가 내는거니까 걱정하지 말아라. 카드를 사용중인지 확인하려고 그런다 어쩐다. 정말 별에 별 이해가 안 되는 소리를 무지 빠르게 합니다. 그냥 전화를 끊어버리세요.

지금이 리조트에 놀러갈 떄입니까. Effective Java에서 한 Item이라도 더 배워야지 지금 애인도 없는데 장난 치는 것도 아니고...

사기 당하신 분들의 글(네이버가 이럴 땐 더 좋습니다.)
http://cafe.naver.com/kimbyunmanse.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=7453
http://cafe.naver.com/kimbyunmanse.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=7120
대검찰청 수사 의뢰(구글도 이름값 합니다.)
http://pohang.dpo.go.kr/user.tdf?pg=1&chungcd=01000000&cp=1&catmenu=050201&a=user.board.BoardApp&c=2002&seq=168919&npp=20&board_id=sppo_opinion&

까딱하면 150~160만원이 날아갑니다. 조심하세요 ㅠ.ㅠ

무슨 놈의 리조트 회사가 버젓한 홈페이지 하나 검색이 안되고 사기 관련 글만 검색이 되겠습니까...
살벌한 세상입니다. 역시 뭔가 이상하다 싶었는데 아니나 다를까 사기... 이번엔 정말 한국인 말투였고 완전 고객 상담소 같은 말투여서 진짜로 속을뻔 했습니다. 아니 거의 속은거나 다름없습니다. ㅠ.ㅠ 이참에 카드 하나 그냥 없애야겠습니다.

정말 정말 조심하세요. 이 사람들 한국인이라 눈치도 빠르고 말도 빠릅니다. 둘러대기도 잘 합니다. 절대로 현혹되지 마세요.

top


OSAF를 일반 자바 프로젝트로 읽어 들이는 방법

OSAF : 2008.11.03 23:10


OSAF는 꼭 메이븐 프로젝트가 아니여도 사용할 수 있습니다. 아마 메이븐 때문에 OSAF를 접하시는 분들이 어렵게 느끼시는 것 같은데요. 다음에 배포할 때는 일반 자바 웹 프로젝트 예제도 같이 넣어두겠습니다.

지금은 일단 사용법만 간단하게 보여드리겠습니다.


웹 프로젝트 샘플도 이와 비슷하게 사용하시면 되겠죠?? 음냐.. 내일은 OSAF 아키타입을 보여드리겠습니당.
캬오.. 1일 1스크린캐스팅이 되겠네요. OSAF 말고도 스프링+하이버 게시판 개발 스크린캐스팅도 찍어야 되는데 말이죠. :)

top


아키타입(메이븐 프로젝트 베이스) 만들기

Build/Maven : 2008.11.03 16:43


메이븐에는 아주 괜찮아 보이는 기능이 하나 있습니다. 프로젝트 기본 구조를 생성해주는 아키타입이라는 기능입니다. 매번 프로젝트 시작할 때마다 pom.xml에 필요한 라이브러리 정의한 것조차 매우 귀찮습니다. 웹 프로젝트일 경우에는 자주 사용하는 설정 파일들까지도 매번 다른 프로젝트에서 복사해서 붙여 넣던지 이클립스에 등록한 템플릿 코드를 사용해서 찍어내다시피 합니다. 이런 것들을 전부 처음부터 프로젝트 시작할 때 가지고 있는 상태에서 시작한다면...정말 좋겠죠? ㅎㅎ 하지만 공짜는 없었습니다.

OSAF 웹 애플리케이션 샘플을 아키타입으로 만들어서 OSAF를 사용한 웹 개발을 편리하게 할 수 있는 기능을 제공하려고 마음 먹고 아키타입 개발을 시작했습니다. (원래 오전에 할려고 했는데 블로깅하다보니. 밥먹을 시간이고 밥먹고 좀 놀다보니;;; 어느새 2시..ㄷㄷㄷㄷ)

http://maven.apache.org/plugins/maven-archetype-plugin-1.0-alpha-7/examples/archetype.html

위 링크에 나와있는 맨땅에서 아키타입을 만드는 방법은 완전 완전 완전 완전 완전 노가다입니다. pom.xml 만 살짝 수정하는 아키타입을 만들꺼라면 상관없는데.. 제가 만들고자 하는 아키타입을 기본으로 제공할 파일들이 엄청나게 많습니다. 그럴 때 저런 방법으로 아키타입을 만드는건.. 그냥... 너 좀 고생해봐라.. 라는 것 밖에 안 됩니다.

제가 선택한 방법은

http://maven.apache.org/plugins/maven-archetype-plugin/advanced-usage.html


링크에서부터 느껴지는 포스. 어드밴스드.. 하지만 이 녀석으로 아키타입 만드는 방법도 노가다가 필요합니다. 그다지 행복하진 않았습니다.

만드는 방법을 보죠. 아주 간단합니다.



0. 프로젝트 정리

기존 프로젝트에서 아키타입에 포함시키지 않을 폴더와 파일을 제거합니다. 버전 관리를 하고 있는게 안전하겠죠.

특 히 제거해야 할 폴더는 이클립스 빌드 패스에 output 폴더로 지정되어 있는 폴더 그걸 삭제해 줍니다. 그럼 폴더만 다시 생기고 그 안에 있는 파일과 폴더들은 삭제됩니다. 기본적으로 그 폴더는 Package Explorer에선 안 보이고 Navigator에서 봐야 보일 겁니다.

1. mvn archetype:create-from-project


아키타입으로 만들 프로젝트로 이동해서 위 명령을 입력해 줍니다. 아.. 아닙니다. 주의할 것이 있는 프로젝트 기본 인코딩이 UTF-8이면 그냥 저렇게 실행해도 되지만, 저처럼 euc-kr이면 -DdefaultEncoding=euc-kr 옵션을 추가합니다.

2. 생성된 파일들 확인(노가다)

위 명령을 실행하면 target/generated~~/archytype/ 밑에 아키타입에 추가할 파일들이 쫙 보입니다. 그 파일들을 전부 열어서 원하는 대로 생성될지 확인합니다. 특히 인코딩과 ${packageInPathFormat} 같은걸 제대로 확인합니다.

3. 로컬 저장소에 설치합니다.

target/generated~~/archytype/ 폴더로 이동해서 mvn install을 실행합니다. 그럼 로컬 저장소에 아키타입이 설치됩니다.

4. 로컬 저장소의 아키타입을 이용해서 프로젝트를 생성합니다.

mvn archetype:generate -DarchetypeCatalog=local

이 명령어를 사용하면 아키타입 목록을 메이븐 중앙 저장소가 아니라 로컬 저장소에서 읽어옵니다. 이 목록에 위에서 설치한 아키타입이 보일 겁니다. 그 번호를 선택해줍니다.

그리고 필요한 정보를 줘서 프로젝트를 생성하면 됩니다.

5. 원격 저장소에 배포

최종적으로 프로젝트를 확인하고 원하는대로 생성이되면 원격 저장소에 배포해서 다른 개발자도 이용할 수 있게하면 되겠습니다.

배포하는 방법은 mvn install하던 장소로 이동해서 mvn deploy를 하면 되겠죠. 간단 간단.

ps: 한글 문제는 해결했지만, 패키지가 동적으로 안 바뀌는 문제가 남아있습니다. -_-;; 흠... 이상하네. package명을 주면 만들 때 알아서 바껴야지 왜 패키지는 고정적으로 만들고 import 문에 있는 package만 바뀌는거얌.. 어쩌라구 ㅠ.ㅠ


top


하이버네이트가 문제인가요? 자신이 문제인가요?

모하니?/Thinking : 2008.11.03 12:12


"람보르기니가 있는데 운전 면허증이 없습니다. 그래서 람보르기니를 못타고 다니는데 그게 람보르기니 때문인가요 저 때문인가요."

저는 국내 대형 사이트나 금융권을 비롯해서 흔히 말하는 SI 환경을 경험해 본적이 없습니다. 지금이 11월이니까 이제 개발자로 일한지 거의 1년이 되어갑니다. 그동안의 개발 경험은 금융관련 컨설팅 회사에 아키텍트로 들어갔다가 두 달만에(사실은 한 달만에 냈지만, 한 달은 처리 기간) 사직서를 내고, 지금 있는 회사로 와서 조그마한 유통업에서 사용할 웹 애플리케이션을 사부님한테 배워가면서 스프링, 하이버네이트로 만들었고, 그걸 만드는 과정 중에 얼마전에 공개했으나 별로 빛을 못보고 있는 OSAF를 뽑아냈습니다.

저는 대형 사이트니 초대형 엔터프라이즈니 하는 것에 대한 경험은 없지만 스프링, 하이버네이트를 좋아하고 그만큼 공부도 하고 있고 실무에 적용도 해봤습니다. 한 번은 하이버네이트 버전을 올려놓고 수정할 것들을 제대로 하지 않아서 사부님이 밤을 새면서 버그를 잡은 적도 있습니다.

이런 제가 감히 하이버네이트를 대형 싸이트에서도 쓸 수 있다느니 없다느니 주장하는건 좀 웃긴 일이겠죠. 그래서 전 그런 주장을 하기 보다는 대형 프로젝트나 SI에서 일하시는 분들에게 물어보곤 합니다.

"하이버네이트도 괜찮은것 같은데 왜 iBatis를 쓰고 계신가요?"

답변은 굉장히 다양합니다. 그 중에서 어느정도 공감이가고 그럴 만하다고 생각하는 답변들은 다음과 같습니다.

- 한글로된 참고자료가 없다.
- 개발자가 하이버네이트를 모른다.
- 기술 리더가 iBatis는 익숙한데 하이버는 모른다.
- 레거시 DB를 써야 하는데 정규화가 엉망이다.

이 중에서 마지막 것만 기술적인 문제처럼 보이는데, 사실은 정규화를 제대로 안 했다는 건 DBA가 제 역할을 못한 거라고 볼 수 있으니 결국엔 하이버 문제라기 보단 DB쪽 관계자들의 문제입니다.

한국인이 꼭 한글로된 레퍼런스만 읽어야 한드는 법이 있는 것도 아닌데, 한글로 된 자료가 없다는 핑계를 계속 하는 건 자신의 역량을 제한하고 스스로를 가두는 일밖에 안 된다고 생각합니다. 하이버네이트 관련 자료는 온라인에서 정말 쉽고 많이 찾을 수 있습니다. 그리고 좋은 책도 있죠.(지금 번역도 하고 있습니다.) 그런 것들을 안 본다는 건 그만큼 노력해야 할 필요성을 못 느낀 것 뿐이고, 한글 레퍼런스가 없어서 공부를 못한다는 건 좀 핑계라고 생각합니다. 그래서 이것도 역시 개발자의 문제인거지 하이버네이트의 문제는 아닙니다. 당장 구글에서 hibernate와 iBatis로 검색을 해서 어떤 단어의 검색 결과가 더 많은지 눈으로 직접 확인해보시기 바랍니다.

다음으로 개발자가 좋은 기술이 있지만 몰라서 못쓴다. 이것 역시 하이버네이트의 문제가 아니죠. 개발자의 역량 문제입니다. 하이버네이트를 완전히 마스터 해야 할 필요까진 없겠지만, 적어도 HQL이 날아가면 하이버가 만들어 주는 SQL이 대강 어떠 어떠한 걸꺼라는 예측을 할 수 있는 정도까지만 공부를 하면 될 듯 합니다. 그 뒤에 최적화나 캐슁은 DBA나 소수의 기술 리더가 책임지면 되겠죠. 어쨋거나 이 문제 역시 하이버네이트의 문제는 아닙니다. 개발자가 공부를 안 한게 문제지..

마지막 기술 리더는 프로젝트에서 어떤 프레임워크를 사용 할지 결정할 때 지대한 영향을 주며, 개발자들에게 기술을 전파할 의무가 있다고 생각합니다. 그런 점에서 기술 리더는 현재 프로젝트에 가장 적합한 기술을 객관적으로 평가하고 그 중에서 선택을 해야 하는데 자신이 하이버네이트를 몰라서 자신에게 익숙한 iBatis를 선택한다는 건 물론 타당합니다. 그래야겠죠. 하이버네이트를 쓰라고 해놓고 자신이 못 도와주면 안되니까요. 하지만 만약 그 프로젝트에 하이버네이트가 더 적합한데도 그렇게 선택할 수밖에 없었다면 올바른 선택이긴 하지만 기술 리더에겐 분명히 잘못이 있는거라고 생각합니다. 물론 기술을 잘 모르는 고객이나 개발자들은 잘 모르겠죠. '저 사람이 기술 짱이니까. 저사람 선택이 맞는거겠지'..라고 안일하게 생각하는 개발자 자신의 잘못도 크지만, 이런 인식을 퍼지게 내버려 둔 잘못은 더 큽니다. 오히려 솔직하게 고객이나 개발자에게 지금 프로젝트는 하이버네이트가 더 좋아 보이는데 내가 잘 몰라서 도입을 못하겠다. 이렇게 말하는 기술 리더가 있다면 그 사람이 진정한 기술 짱입니다. 현재는 아니지만 미래의 진정한 짱이 될 수 있겠죠.

윗 글 단락들의 크기로만 봐도 제가 생각하는 문제 원인의 비중을 짐작할 수 있으시겠죠? 맞습니다. 저는 기술 리더가 가장 큰 책임이 있고, 그 다음은 개발자, 그 다음 정규화 제대로 안하는 DBA 순으로 생각하고 있습니다.

저는 위에서 생각한 저 네 가지 답변 말고 하이버네이트 기술 자체를 가지고 올타 그르다를 논하는 답변을 들으면 그 주장에 대한 증거를 찾고 반론에 대한 기술적인 증거를 찾기 전에 일단 이런 의문부터 생깁니다.
외국의 유명한 업체들의 개발자도 하이버네이트를 쓰고 있다. 그 사람들은 바보가 아니다. 그 사람들이 진행하는 프로젝트의 규모가 작은 것도 아니다. 그 사람들도 레거시 DB를 쓰고 있다. 하이버네이트를 iBatis 못지 않게 아주 많이 잘 쓰고 있다. 하이버네이트에 기술적인 결함이 있었다면, 그 사람들이 왜 쓰고 있는거지.. 말도 안돼. 개빈 킹이 가만 있을 만한 성격도 아닌거 같은데.. JBoss에서 노는 것도 아닐텐데 말이지..
반면에 같은 질문을 했을 때 가장 대표적인 기술적인 답변들은 다음과 같습니다.

- 테이블 중심이라 블라 블라..
- 레거시가 블라 블라..
- DB에 특화된 쿼리가 블라 블라..
- SQL을 직접 블리 블라..
- 성능이 블라 블라..

말이 안 되자나요. 저런 문제들이 있는데 유명 해외 업체 개발잘들은 무슨 깡으로 하이버네이트를 쓸까요. 이번 12월에 Spring One America에 가서 직접 물어보고 오겠습니다.

"What kind of framework is used for your persistence layer?"

"How many projects have you experienced with Hibernate?

"Have you ever used Hibernate with legacy DB? Is it really too hard to do that?"

"What about performance?"

"What do you think about Hibernate and iBatis?"

물론 이 질문들은 덤일 뿐이고, 스프링 관련 질문도 많이 하고 와야죠.  가기 전에 S1A에 가서 질문할 것과 말할 것들을 미리 정리해 둬야겠습니다.
top


맥용 녹음기 Sound Studio

Good Tools : 2008.11.02 09:36


오늘 오후 스터디를 녹음 하려고 괜찮은 소프트웨어를 찾느라 시간좀 보냈습니다. ㅎㅎ 스터디 준비도 많이 못했는데 이거라도 잘 준비해 가야죠. 캬캬..

http://www.freeverse.com/apps/app/?id=5012&view=overview

위 링크에 가시면 다운로드 및 동영상으로 사용법을 볼 수 있습니다. 직접 테스트를 한 번 해봤는데 맘에 듭니다. 소리를 잘 잡아주네요. 대신 스터디 하는 도중 맥북에 입력하는 키보드 소리가 너무 크진 않을까 걱정됩니다. 타이핑 할 때 살살해야겠습니다. ㅎㅎ;;

사용자 삽입 이미지

Tip. MP3로 저장하기
- LAME이라는 걸 설치해주셔야 합니다. 여기서 받아서 설치할 수 있습니다.

top


스프링 2.5 @MVC 컨트롤러 테스트관련 궁금한거..

모하니?/Coding : 2008.11.01 14:01


@Controller
@RequestMapping("board/*.do")
@SessionAttributes(value="board")
public class BoardController {

    @Autowired
    private BoardService boardService;

    @Autowired
    private BoardValidator validator;

    @RequestMapping
    public void list(ModelMap model){
        model.addAttribute(boardService.getAll());
    }

    @RequestMapping(method=RequestMethod.GET)
    public void add(ModelMap model){
        model.addAttribute(new Board());
    }

    @RequestMapping(method=RequestMethod.POST)
    public String add(@ModelAttribute("board") Board board, BindingResult result, SessionStatus status){
        validator.validate(board, result);
        if(result.hasErrors())
            return "board/add";
        else{
            this.boardService.saveOrUpdate(board);
            status.setComplete();
            return "redirect:board/list.do";
        }
    }

    @RequestMapping
    public void delete(int id){
        boardService.deleteById(id);
    }

}

위 코드는 간단한 스프링 2.5 @MVC 컨트롤러입니다. CRUD 중에서 U 관련 코드는 생략했습니다.

이 컨트롤러를 작성하면서 확인하고 싶었던 걸 정리하면 다음과 같습니다.
1. board/list.do 라는 요청 결과를 보여줄 뷰는 WEB-INF/board/list.jsp 파일이 맞는지..(ViewResolver 확인)
2. board/list.do 라는 요청을 했을 때 결과 뷰에 넘어가는 모델 객체 중에 List<Board>가 있는지. 그리고 그 모델 객체의 이름이 boardList가 맞는지.(ModelAndView 확인)
3. board/add.do GET 요청이 오면 저 컨트롤러의 add(ModelMap) 메소드가 호출되는지.(RequestMapping 확인)

이 때 2번은 쉽게 테스트가 가능합니다. 인자로 넘겨주는 ModelMap 객체를 하나 만들어서 넘겨주고 해당 메소드를 호출 해보고 ModelMap 객체를 뒤져보면 테스트 하고자 하는 데이터를 찾을 수 있습니다.

그러나.. 1번은 ModelAndVIew 객체를 반환하도록 컨트롤러 코드를 고치지 않는 이상 어떻게 테스트 할 수 있을지 감이 안잡힙니다. 스프링 MVC CoC를 적극 활용하려고 작성한 코드인데 명시적으로 뷰이름을 설정해버리면 그런 의도가 무색해지니까요..

3번도 마찬가지 입니다. 이건 더 감이 안 잡힙니다. 테스트를 할 때 만드는 ApplicationContext가 WebApplicationContext도 아니라서 스프링이 기본으로 등록해주는 빈(request handler, adapter 등)들이 없을 것이기 때문에 스프링 테스트만 가지고는 테스트가 어려울 것 같다는 생각이 듭니다.

어쩌면 컨트롤러 테스트가 아닐 수도 있겠습니다. 스프링 프레임워크가 제공하는 기능에 대한 테스트일 수도 있으니 스프링 코드에서 뷰 리졸버와 요청 맵핑 클래스에 대한 테스트로 만족하고 넘어갈 수도 있겠지만.. 글쎄요. 그래도 왠지 테스트가 하고 싶네요. 혹시 HttpUnit으로 이런걸 할 수 있는건가요. 써보지 않았는데.. 함 살펴봐야겠습니다.
top