Whiteship's Note

'모하니?'에 해당되는 글 935건

  1. 2010.09.04 워드프레스로 옮겼습니다.
  2. 2010.09.01 가산동 LG CNS에서 '스프링 3.0 이해와 선택' 강의 수강하신 분들 안녕하세요/ (2)
  3. 2010.08.31 아파치 Click이 No Framework?? (5)
  4. 2010.08.28 '스프링 3.0 이해와 선택' 강의 후기 (12)
  5. 2010.08.17 토비의 스프링 3 북 오픈 기념샷 (10)
  6. 2010.08.13 이웃나라 (부동산) 이야기 (2)
  7. 2010.08.11 템플릿-콜백 패턴으로 Try-Catch-Finally 블럭을 무찌르자. (6)
  8. 2010.08.11 [BlackBerry] 헬로 Whiteship (4)
  9. 2010.08.11 [IBM DW 스크린캐스팅] 오브젝트와 의존관계 그리고 스프링3 (4)
  10. 2010.08.09 JAOO 2010 YOW는 호주 브리스베인에서 12월 6~7일 컨퍼런스 8~9일 워크샵
  11. 2010.08.07 2010 SpringOne 2GX는 시카고에서 10월 19일부터 22일까지
  12. 2010.08.06 에그2를 샀다
  13. 2010.08.04 [GAE 시리즈] 7. 스프링 @MVC
  14. 2010.08.03 [GAE 시리즈] 6. 배포하기
  15. 2010.08.03 [GAE 시리즈] 5. 정적 자원
  16. 2010.08.03 [GAE 시리즈] 4. JDO
  17. 2010.08.03 세상에 공짜는 없다. (4)
  18. 2010.08.03 [GAE 시리즈] 3. JSP와 로깅
  19. 2010.08.03 [GAE 시리즈] 2. 구글 로그인
  20. 2010.08.03 [GAE 시리즈] 1. 구글 앱 엔진 + 메이븐 + IntelliJ 프로젝트 세팅
  21. 2010.08.02 2010년 계획 (늦은) 중간 점검;;
  22. 2010.07.27 토비의 스프링 3 (4)
  23. 2010.07.20 주말 강의는 2주 연기
  24. 2010.07.19 [스프링 3 이해와 선택] 2차 강의 진행합니다. (4)
  25. 2010.07.12 네가 있어서 정말 감사하다. (4)
  26. 2010.07.07 버즈 버그 미투 장애
  27. 2010.07.07 [이전글에 이어지는 이야기] 숫자에서 객체로...
  28. 2010.07.07 복잡한 로직은 복잡한 DAO로 직결되는가? (6)
  29. 2010.07.02 스프링 DAO 3파전 (6)
  30. 2010.06.25 전자정부 프레임워크 공통 컴포넌트 실행 성공(?) (2)

워드프레스로 옮겼습니다.

모하니?/Blogging : 2010.09.04 00:28


오시던 주소로 오시면 됩니다.

http://whiteship.me 
저작자 표시
신고
top


가산동 LG CNS에서 '스프링 3.0 이해와 선택' 강의 수강하신 분들 안녕하세요/

모하니?/Thinking : 2010.09.01 10:19


https://spreadsheets.google.com/viewform?formkey=dElvckJLdzU0WnhKTDRnMl9fWFZJTVE6MQ

이 링크에서 강의 평가 부탁드려요.
이미 한분은 해주셨답니다.
대충 앞자리에 계시던 분들 중 한 분이 아닐까 생각됩니다.ㅋㅋ 감사합니다. 

1등 평가자에겐 원래 책을 선물로 드리려고 했는데 이미 사셨다니까... 패스...
저작자 표시
신고
top


아파치 Click이 No Framework??

모하니?/Thinking : 2010.08.31 10:35


http://www.likejazz.com/archives/2247

여기서 likejazz님은 아파치 Click을 노 프레임워크라고 소개하고 계신데요.

1. 기사 원문에도 그런 단어가 없을 뿐더러.
2. 기사 번역문도 애매하게 번역한 부분이 없잖아 있지만 직접적으로 노 페임워크라고 업급하지 않았습니다.
3. 충격적으로 아파치 Click 홈페이지에 가보시면 자신이 웹 애플리케이션 프레임워크라고 정의했습니다.

그런데 No Framework 라니요.. 전 소개글 읽다가 "이게 뭐지?" 라고 깜짝 놀라서 하던 일 멈추고 읽게 됐습니다. 그런데.. 지금은.. 그야말로 낚였다는 생각밖에 안 들더군요.

No Framework 가 경량(lightweight) Framework랑 같은 말인건가요? 그건 아닌것 같습니다. 

Apache Click은 프레임워크 대신 HTML 템플릿과 POJO(Plain Old Java Object)만으로 프레임워크의 역할을 대신하는 No-Framework의 일종이다.
likejazz님의 설명입니다. 

그런데..  기사에 올라온 코드만 보셨더라도 Click 프레임워크가 제공하는 클래스(Page)를 상속해서 WelcomPage라는 걸 만드고 있습니다. Page같은 프레임워크 코드를 쓰는데..이게 어떻게 No Framework라고 할 수 있을까요.

Click이 경량 프레임워크라는 데는 동의할 수 있습니다. 스프링처럼 방대한 기능을 제공하지 않는 대신 스프링의 방대항 확장성을 포기하고 Click이 제공하는 간편한 방법. 딱 그 방법으로만 개발을 할 수 있게 해주니까 가벼운 프레임워크라고 볼 수 있습니다. 하지만 그렇다고 해서 그게 프레이워크 없이 POJO로만 개발이 가능하다고 하는 No Framework 랑은 좀 다른게 아닌가 싶습니다. 실제 코드도 안 그렇구요. @_@;


저작자 표시
신고
top


'스프링 3.0 이해와 선택' 강의 후기

모하니?/Thinking : 2010.08.28 23:50


'토비의 스프링 3'을 간추린 내용으로 강의를 세 번 했다. 두번은 한빛ENI에서 4회에 걸쳐서 진행했고 한번은 절반의 내용만 가지고 이동국님 소개로 NHN의 어느 한 팀을 대상으로 진행했다. 6월 말부터 강의를 시작해서 오늘 8월 말까지 거의 쉬지 않고 달려왔다. 하지만 아직도 끝나지 않았다. 앞으로 진행하기로 구두로 계획한 강의가 두개. 최종 합의가 끝난 강의가 하나. 현재 하고 있는 강의가 하나 있다.

강의를 처음 해보는 거라 얼떨떨 하던차에 갑자기 여기 저기서 강의 요청이 들어오는 바람에 더 얼떨떨하고 몸도 약간 피곤하다. 하지만 매우 즐겁고 새로운 아이디어가 많이 떠올라서 좋다.

첫 강의를 준비할 때는 많이 긴장했다. 처음 해보는 강의인데 준비된 자료는 아무것도 없었다. 하지만 난 든든했다. 나에겐 '토비의 스프링 3'이 있었다. 그 책에 있는 내용이 워낙에 좋았다. 강의 할때마다 말하지만 내가 말하고 전달한 내용은 전부 이 책에 들어있다. 난 그거 그것을 최대한 쉽게 이해하고 학습하기 편한 형태로 요약하고 편집해서 준비한 것을 효율적으로 전달하려고 노력하는 것 뿐이다. 그게 나의 '스프링 3.0 이해와 선택'이라는 강의다.

그래서 준비한 것이 우선 소스 코드다. 난 PPT 부터 만들지 않았다. 책 내용 중에 꼭 전달하고 싶은 내용과 꼭 이해해야 할 내용을 소스 코드로 만들었다. 그것도 단계적인 학습 단계에 맞게 또 그걸 편하게 다룰 수 있도록 각 패키지에 번호를 붙여놨고 패키지 순서가 흐트러지지 않게 test00, test01 이런식으로 두가지 숫자를 패키지 명 뒤에 붙여줬다. 그 다음에 준비한 것이 PPT다. 소스 코드만 가지고 이해하기 어려운 내용을 PPT로 보강했다. 이 소스에서 저 소스로 넘어갈 때 무엇 때문에 그렇게 넘어가는 것인지 그 결과는 어떤지에 초점을 맞춰 PPT를 작성했다. 마지막으로 소스코드가 변화하는 과정을 보여주려고 코딩 동영상을 녹화했다. 라이브코딩은 생각보다 시간이 많이들고 리스크가 높다. 라이브코딩의 묘미는 발표자의 실수라지만 이제 그런 시절은 갔다. 라이브코딩의 목적이 재미라면 모르겠지만 그게 아니라면 수강생을 불안에 떨게 하면 안된다고 판단했다.

나름대로 열심히 준비한 발표이다보니 자연스래 별로 긴장하진 않는다. 그래도 새로운 장소에서 강의하게 될 때는 항상 약간은 설레이고 약간은 긴장된다. 그래서 항상 첫강의때 1시간정도 일찍 강의장에 도착해서 노트북을 빔에 연결하고 인터넷을 잡고 이클립스를 띄우고 PPT를 띄워서 마음을 가라앉힌다. 그러고 나면 금새 마음이 편해져서 긴장이라는 말은 금방 잊게 된다. 그 뒤에는 수강생의 반응에 신경을 곤두세운다.

강의가 시작되면 나는 수강생들의 반응을 살피기 시작한다. 얼굴은 반응을 살피기 가장 좋은 표적이다. 나는 설명을 하고 수강생들은 화면을 본다. 나는 수강생들의 얼굴을 본다. 그 얼굴 중에는 '네. 이해가 됩니다.', '그래 알겠어.', '이미 아는거자나', '아. 졸려..', '앗 모르곘는데', '멍...', '앗 머라고?', '어려운걸! 이거 뭐지', '멀라 뭐야 이거 먹는거?' 라는 표정이 들어있다. 그걸 보면서 질문을 던지고 좀 더 내 추측이 확실해지면 그에 따라 부연설명을 하거나 속도를 조절한다.

하지만 아직 뭔가 많이 부족하다. 지난주 금요일 수원형 TDD 강의 때 많은 걸 배울 수 있었는데 TDD 보다는 강의 방식. 즉 교수법을 배울 수 있었다. 강의 내용은 분명 TDD 였지만 현재 나에게는 TDD 보다 수원형의 강의 진행 방식과 사소한 유머과 PPT에 더 관심이 갔다. 3시간이 어떻게 갔는지 모를정도로 순식간에 지나갔다. 그리고 하나도 지치지 않았다. 매우 재미있었다. 학습은 그렇게 재밌어야 한다. 배우는 맛이 있어야 한다. 그런데 과연 내 강의를 수강하는 학생들도 그만큼 재미있고 유익하게 학습하고 있는지 어떤지.. 그것 조차도 잘 모르고 있다. 그저 추축만 할 뿐..

그래서 보완할 방법을 마련했다.

하나는 수원형 TDD 강의때 본 즉석 피드백 수집 방법을 사용하는 것이다. 보통 강의가 끝나면 교육을 받은 업체에서 피드백을 받는다. 그러나 그 내용이 나에게 잘 전달되진 않는다. NHN에서 했던 강의 피드백은 동국님께서 전달해 주셔서 잘 볼 수 있었고 굉장히 유용했다. 하지만 한빛ENI에서 했던 교육의 피드백은 내가 받지 못해서 따로 요청해둔 상태이다. 이제는 방법을 바꿔서 나도 수원형처럼 즉석에서 피드백을 받으려고 한다. 그것도 편한 방법으로 말이다. 구글 양식을 이용하는 방법인데 자세한건 나중에 설명하기로 하고, 일단 오늘 받은 피드백은 이렇다.


이상하게 이름을 안적었는데도 읽어보면 어느게 누구 것인지 쉽게 알 수 있을 만큼 익명성이 철저히 보장된다. ㅋㅋㅋ 대부분 실습 위주의 강의에 매우 긍정적이고 시간이 부족하다는 것을 아쉬워했다. 사실 실습 시간이 부족한 것은 내가 너무 많은 내용을 전달하려고 하는 욕심 때문이기도 하고.. 실습한 내용이 한번에 익혀지는 만만한 내용도 아니라서 그럴 것이다. 이 부분은 앞으로 조금 강의 내용을 개선해서 고쳐나가야 할 부분이다.


 ps: 오랜만에 썼더니 굉장히 장문으로 써진다. (사실 이보다 더 많은 내용을 썼다가 지웠다.) 앞으로는 좀 더 자주 토해내야겠다.

저작자 표시
신고
top


토비의 스프링 3 북 오픈 기념샷

모하니?/Reading : 2010.08.17 21:31



음하핫.. 드디어 받았군요. 제가 마지막에 쿨하지 못해서 넣게된 추천사까지 볼 수 있고 알파리딩 때는 보지 못했던 토비님의 감사의 인사도 볼 수 있어서 감회가 새로웠습니다.  길게 쓰고 싶지만 운동갈 시간이라.. 짧게 남겨도 이해해 주세요.

책에는 이클립스 기준으로 소스코드 실행하는 방법이 있지만 전 인텔리J로 돌리렵니다. 메이븐 프로젝트도 아니니까 이클립스로 돌려도 무난하겠지만... 메이븐 프로젝트는 인텔리J가 백배 좋습니다.
저작자 표시
신고
top


이웃나라 (부동산) 이야기

모하니?/Thinking : 2010.08.13 17:27






이제 한국 차례.. 
저작자 표시
신고
top


템플릿-콜백 패턴으로 Try-Catch-Finally 블럭을 무찌르자.

모하니?/Coding : 2010.08.11 18:40


어제부터 계속 정리하고 싶었는데 어젠 이상하게 시간을 쏟아 버리는 바람에.. 이제 정리한다. 자세한 내용은 토비의 스프링 3에 나오는데 이번에 구글 캘린더 API 코딩하다가 써먹을 기회가 와서.. 적용해 봤다. 문제는 내 강의를 들었던 학생은 그걸 하지 못했다는게 아쉽다. 어디 한술에 배부르랴.. 그래도 내가 코딩한 걸 보고 그게 그건지 알아차렸으니.. 그걸로 만족한다.


구글 캘린더 API를 사용하려면 위에 있는 문서만 보면 된다. 친절하게 안내해주고 있어서 쓰기 편하다. 그런데 문제는 예외처리다. 


    public List<CalendarEntry> getMyCalendarList(){
        URL feedUrl = makeUrl(OWN_CALENDAR_URL);
        try {
            CalendarFeed resultFeed = calendarService.getFeed(feedUrl, CalendarFeed.class);
            return resultFeed.getEntries();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ServiceException e) {
            throw new RuntimeException(e);
        }
    }


저기서 호출하고 있는 calendarService는 구글에서 제공해주는 API로 IOException과 ServiceException을 던지는 메서드들을 왕창 가지고 있다. 또 그녀석들을 자주 쓰게 된다.

따라서 어떤 호출을 하더라도 위와같은 예외 처리 코드가 생기기 마련이다. 이걸 어떻게 하면 좋을까? 스프링 개발자라면 이런 코드를 스프링과 잘 어울리는 형태로 처리할 수 있어야 한다.

어떻게 할것인가? 어떻게 하면 저 지져분한 Try-Catch(-Filnally) 문에서 벗어날 것인가? 한번 도전 해보자...

결과는..

public List<CalendarEntry> getMyCalendarList(){
        return calendarServiceTemplate(new CalendarServiceCallBack<List<CalendarEntry>> () {
            public List<CalendarEntry> queryForObject() throws IOException, ServiceException {
                return calendarService.getFeed(makeUrl(OWN_CALENDAR_URL), CalendarFeed.class).getEntries();
            }
        });
    }

이것과 비슷한 형태가 될 것이다. 물론 중요한건 결과가 아니라 저렇게 바꾸는 프로세스.. 그걸 이해하고 자신의 스킬로 만드는 것이 중요하겠다. 토비의 스프링 3에서 아주 잘 배울 수 있으니 꼭.. 3장 템플릿을 정독하도록 하자. 연습하고. 또 연습하고. 또 연습하고. try-catch 문이 반복해서 나올 떄 마다 적용해 보도록 하자.

저작자 표시
신고
top


[BlackBerry] 헬로 Whiteship

모하니?/Coding : 2010.08.11 13:55



아이콘은 무료 아이콘 사이트에서 하나 다운 받았고.. 초간단 앱은 역시 헬로 월드.. 

public class HelloWorld extends UiApplication {
final class HelloWorldScreen extends MainScreen {
public HelloWorldScreen() {
super();
LabelField title = new LabelField("Hello App", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
setTitle(title);
add(new RichTextField("Hello Whiteship!!"));
}
public boolean onClose() {
Dialog.alert("바이바이!");
System.exit(0);
return true;
}
}

public static void main(String[] args) {
HelloWorld app = new HelloWorld();
app.enterEventDispatcher();
}
public HelloWorld() {
pushScreen(new HelloWorldScreen());
}

}

일단 앱은 UiApplication을 상속 받아서 만들고 우선.. 맨 아래에 있는 메서드 pushScreen을 사용해서 MainScreen을 상속해서 만든 화면을 뿌려주고,, enterEventDispatcher 메서드를 호출해서 이 앱에서 발생하는 이벤트들을 감지하도록 설정하는 것 같네요.

흠냐.. 뭘 만들어 볼까나..
저작자 표시
신고
top


[IBM DW 스크린캐스팅] 오브젝트와 의존관계 그리고 스프링3



출처 및 소스 코드: https://www.ibm.com/developerworks/mydeveloperworks/blogs/9e635b49-09e9-4c23-8999-a4d461aeace2/entry/264?lang=en





에이콘 출판사의 토비의 스프링 3의 1장 내용을 스크린캐스팅으로 찍어 봤습니다. 상당히 많은 내용을 압축해서 찍은거라 생략한 설명이나 과정이 많습니다. 책 내용에 대한 일종의 프리뷰라고 생각하시고 자세한 내용은 꼭 책으로 확인하시기 바랍니다.

ps: 오늘 토비님께서 블로그에 올려주셨더니 조회수가 확 뛰었네요. 캬..


저작자 표시
신고
top


JAOO 2010 YOW는 호주 브리스베인에서 12월 6~7일 컨퍼런스 8~9일 워크샵

모하니?/Planning : 2010.08.09 11:05


JAva Object Oriented 소프트웨어 개발 컨퍼런스란 뜻에서 JAOO라고 한다.

http://channel9.msdn.com/posts/Charles/JAOO-2007-Kresten-Krab-Thorup-JAOO-What-How-Why/

컨퍼런스 세부 일정은 아직 안나온듯.. 저기도 가고 싶다. 미국에서 하는 스프링 세미나 보다 호주에서 하는 YOW가 더 가보고 싶다. 이유는 워크샵 때문에.. 직접 실습 해본다고.. 캬.. 그리고 주제도 완전 다양하다.

나중에 스케줄 표라도 나오면 다시 수정해서 올려야지. 지금을 일단 기록용.
저작자 표시
신고
top

TAG JAOO

2010 SpringOne 2GX는 시카고에서 10월 19일부터 22일까지

모하니?/Planning : 2010.08.07 19:55


http://www.springone2gx.com/conference/chicago/2010/10/springone/event_schedule

2008년은 OSGi와 스프링 DM이 한참 뜨는가 했더니... 이번 컨퍼런스에서는 찾아보기 힘들다.  애초에 공부할때도 영.. 힘들다 싶었다. @_@;; 좀 더 사용하기 편해지고 뭔가 모듈화 가이드 라인이 확실해 지면 그떄가서나 다시 시도해볼까.. 그전엔 별로 하고 싶지 않다.

이번 컨퍼런스는 스프링 Roo와 클라우드 컴퓨팅이 대세인것 같다. 그 중에서 듣고 싶은 세션을 선택해 봤다. 아직 일정이 전부 공개된 상태가 아니라 별로 듣고 싶은 세션이 없는 시간대에는 빈곳을 선택해 뒀고.. 둘다 관심이 갈 땐 그냥 둘 다 칠해뒀다.

혹시라도 올해에도 가게되면.. 제작년처럼 한 주제로 올인하고 싶진 않다.



저작자 표시
신고
top


에그2를 샀다



몇일전 네이버에 스프링 3.0 강의를 하러 다녀왔다. 역시.. 똑똑한 분들이 많은 곳이라 그런지 이해력이 상상이셨던 분들이 많았다. 음.. 그런데 그런 좋은 회사들의 단점은.. 외부인의 인터넷 사용에 제약이 크다는 것이다. 이해한다. 외부인이 사내 네트워크에 접속해서 공유폴더라도 뒤지면... @_@.. 그래서 그냥 인터넷 없이 강의를 진행했다.

이미 강의에 필요한 모든 코딩 동영상, PPT, 소스 코드가 세팅되어 있는 맥북을 들고갔으니 굳이 인터넷이 필요하진 않았다. 그래도;; 가끔은 스프링 API 문서를 띄우거나 내 블로그에 정리했던 글을 띄워서 보여드리고 싶었지만 그럴 수 없는 것은 역시 조금 불편했다.

그래서 장만했다. 썬에그..

다 좋은데;; 이게 좀 뜨겁다;;; 


속도는 이정도.. 일단 업로드 속도가 매우 맘에 든다; 이제 집에서도 스크린캐스팅 업로드 할 수 있겠다;; 매번 회사가서 올리느라고 드랍박스로 옮기거나 USB로 옮겨다녔는데 그럴 필요 없어졌다.
저작자 표시
신고
top


[GAE 시리즈] 7. 스프링 @MVC

모하니?/Coding : 2010.08.04 04:42


GAE 시작하기 메뉴얼을 따라하면서 들었던 생각은 스프링을 어서 도입해봐야겠다는 것이었다. 특히 PMF 라는 클래스를 만들때 간절했다. JDO의 PersistenceManagerFacotry를 싱글톤으로 사용하려고 만든 클래스인데.. 전혀 좋은 코드가 아니었다. 그뿐아니라 자바 코드와 HTML이 섞여있는 guestbook.jsp도 마찬가지이고, HttpServlet을 직접 상속해서 구현한 GurestbookServlet과 SignGuestbookServlet도 스프링 @MVC 컨트롤러로 고치고 싶었다.

그래서 일단해야 할 일은 스프링의 초간단 @MVC 컨트롤러를 추가하고 그게 동작하는지 확인하는 일이었다. 이전에 라이브러리는 넣어둔 상태라 간단하게 설정만 조금 추가하면 됐다.

web.xml

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

spring-servlet.xml

<context:component-scan base-package="whiteship" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

applicationContext.xml

<context:component-scan base-package="whiteship">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

그리고 컨트롤러

@Controller
@RequestMapping("/hello")
public class GreetingController {

    @RequestMapping("/{name}")
    public String hello(@PathVariable String name, Model model){
        model.addAttribute("name", name);
        return "/WEB-INF/views/hello.jsp";
    }

}

그리고 뷰

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<html>
  <head><title>Simple jsp page</title></head>
  <body>잘잤니~ ${name}</body>
</html>

끝이다. 잘 돌아간다.



저작자 표시
신고
top


[GAE 시리즈] 6. 배포하기

모하니?/Coding : 2010.08.03 14:51


http://code.google.com/intl/ko-KR/appengine/docs/java/gettingstarted/uploading.html

드디어 GAE 시작하기 매뉴얼로는 마지막이군요. 하지만 아직 스프링 도입하기가 남았으니 GAE 시리즈는 계속 이어지겠지만 오늘은 오후에 일이 있어서 오늘로는 마지막 포스팅이 될듯 하군요.

https://appengine.google.com/

일단 저기에 접속해서 계정을 만들고 애플리케이션 ID를 생성합니다. 해당 ID를 웹 프로젝트의 appengine-web.xml의 <application> 엘리먼트에 설정해 줍니다.

그리고 이클립스나 인텔리J 같은 IDE에서 직접 업로드 하거나.. 콘솔에서 업로드 할 수도 있습니다. 저는 콘솔에서 해봤습니다. 

http://whiteshipgb.appspot.com



저작자 표시
신고
top

TAG GAE, 배포

[GAE 시리즈] 5. 정적 자원

모하니?/Coding : 2010.08.03 14:23


CSS 파일, JS 파일, 이미지, 플래시, 음악, 무비 등 정적 자원은 서블릿 컨테이너가 아닌 별도의 웹서버로 서비스를 사용해서 서비스 해준다. 

이때 WAR로 패키징되는 애플리케이션의 모든 자원 중 /WEB-INF 밑에 있는 JSP 파일들을 제외하고는 모두 정적 자원으로 처리해준다. 따라서 별도의 설정을 할 필요 없지만.. 만약에 별도로 정적 파일을 지정하고 싶다면 web.xml 근처에 있는 appengine-web.xml 파일에 설정해주면 된다.

appengine-web.xml에 설정파일에 대한 자세한 내용은 http://code.google.com/intl/ko-KR/appengine/docs/java/config/appconfig.html


저작자 표시
신고
top


[GAE 시리즈] 4. JDO

모하니?/Coding : 2010.08.03 13:15


http://code.google.com/intl/ko-KR/appengine/docs/java/gettingstarted/usingdatastore.html

 분산 웹 애플리케이션을 만들려면 고민할께 많은데 GAE를 사용하면 그럴 걱정은 할 필요 없단다. 매력적이다. 하지만 손수 분산 웹서버, 분산 DB 환경을 구축해보고 싶긴하다. 머 어쨋건;; 지금은 GAE 공부 중이니깐;; GAE가 알아서 분산, 복제, 로드 밸런싱을 해주기 때문에 개발자는 그냥 심플한 API만 사용해서 개발하면 분산 환경은 알아서 사용하게 된다.

GAE의 datastore도 그러한 서비스 중 하나인데 두 종류 API를 지원한다. 하나는 JDO 하나는 JPA. JDO는 오래전부터 표준이었고 JPA는 하이버네이트 영향으로 생긴 EJB 3의 표준인데... 어째 둘이 생긴게 비슷하다. JDO가 JPA를 따라서 변형된 것 같은 모습인데 실제로 그런건진 모르겠다. 그러거나 말거나.. 쓰기 편하고 기능이 좋으면 그만이다.

JPA를 쓸때 persistence.xml 설정 파일 만들듯이 JDO를 쓸땐 jdoconfig.xml 파일을 만든다. 이 파일에 대한 자세한 설명은 생략;

http://code.google.com/intl/ko-KR/appengine/docs/java/datastore/usingjdo.html

난 JPA를 쓰고 싶은데, 아니 사실은 하이버네이트를 직접 사용하고 싶은데;; 예제가 JDO라 어쩔 수 없이 일단은 따라해 보기로 했다. 

다음은 도메인 클래스를 만들고 매핑 정보를 애노테이션으로 설정한다. JPA랑 똑같다.  그 다음도 사실 똑같다. PersistenceManagerFactory에서 PersistenceMaanger를 가져가다 사용하면 된다. 하이버네이트로 치자면 SessionFactory에서 Session 가져다 쓰는거랑 비슷하다. JDO에도 HQL 같은 JDOQL이라는 쿼리 언어가 있다. 도무지;; JDO랑 JPA랑 구분이 되지 않는다. 똑같아 보인다. 이럴바엔 하나로 합치는 표준을 하나 만들고 그 API를 쓰게 하는게 좋치 않을까.. 



저작자 표시
신고
top

TAG GAE, JDO

세상에 공짜는 없다.

모하니?/Thinking : 2010.08.03 11:45


그래서 딱히 좋아할 것도 없고
그래서 딱히 아쉬울 것도 없다.
그러니 무척 열심히 살아야 된다. 

예를 들어, 누가 식당에 들어가서 밥을 먹고 우연히 계산을 안하고 나왔다 치자. 이사람은 공짜로 밥을 먹은 것일까? 아니다. 그 사람은 돈을 낼 수도 있는데 돈을 내지 않았다는 죄책감을 받았고, 종업원들로부터 그지같은XX라는 욕도 얻어먹었으니 절대로 공짜가 아니다.

자그럼 누군가 열심히 공부한것을 블로깅 하고 있다. 남들도 다 보라고. 공짜로 퍼주고 있는 것이다. 과연 그럴까? 아니다. 어차피 블로깅이야 내가 공부한 것을 정리하는 목적이었으니 소기의 목적을 달성한 성취감이 돌아오며, 차후 누군가 내 글이 그사람에게 도움이 됐다는 댓글 하나라도 달린다면.. 그게 또 얼마나 맛있는지 모른다.

어찌 생각하면 참으로 공평한 세상 같지만 어찌 생각하면 참으로 무서운 세상인거다. 자식에게 주는 부모님의 사랑. 부부간에 서로룰 존중하는 마음. 남을 배려하는 마음과 태도. 이게 다 눈에 안 보인다고 '공짜'라고 착각하는 사람들이 늘어나면 세상은 흉악해지고 볼품없어진다.

부모가 자식에게 무한대의 신뢰와 사랑을 주지 못하면 자식은 비뚤어지기 마련이고 범죄자가 될 가능성이 높다. 공부해도 모자를 시간에 게임이나 하며 허송세월 하다가는 돈많은 부모둬서 외국나가 띵까띵까 거리던 애들한테 평생 짓눌려 살 수가 밖에 없다. 그러니까 열심히 살아야 한다.

그렇치 기선아? 열심히 살자고.
저작자 표시
신고
top


[GAE 시리즈] 3. JSP와 로깅

모하니?/Coding : 2010.08.03 06:53


http://code.google.com/intl/ko-KR/appengine/docs/java/gettingstarted/usingjsps.html

GAE라고 해서 JSP에 특별한 머시기를 해주는건 아니고 그냥 일반적인 Servlet&JSP 코딩하듯이 코딩하면 된다.

JSP는 web 폴더 밑에 두면 자동으로 매핑 되니까 guestbook.jsp 같은걸 만들고, 그 안에서 직접 자바 코드 호출해서 사용하고 있다. (빨리 스프링 MVC 적용해서 걷어내고 싶다.)  그 다음엔 폼을 추가하고 그 폼 서브밋을 처리할 서블릿을 하나 만들고 (그안에서 로그인 확인 중복 코드 발생한다.) 로그인 여부에따라 java.util.logging.Logger를 사용해서 로그 메시지를 남기고 있다. 그 서블릿 매핑 정보를 web.xml에 추가한다. (이부분도 역시 어서 스프링 MVC를 도입하고 싶게 해주는 부분이다. 귀찮게 맨날 web.xml에 대여섯줄 씩 매핑 정보를;; @_@;)

자.. 이제 끝이 아니라. 로깅을 설정하는게 이게 조금 재밌다.

web/WEB-INF 폴더 밑에 보면 appengine-web.xml이 있는데 드디어 이녀석이 하는 일 중 하나가 밝혀진다. 바로 환경 변수 설정이다. 

    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
    </system-properties>

이런식으로 로깅 파일 위치를 설정해주면 GAE에서 해당 위치에 로깅 파일을 사용하여 어드민 콘솔 이라는 앱으로 GAE에 배포한 앱의 로그 메시지를 기록하고 간편하게 찾아볼 수 있는 서비스를 제공해준다. log4j 설정만 써보고 자바 Logger 설정은 안써봤는데; 의외로 간편하다.

.level = WARNING
whiteship.level = INFO

달랑 요거;


 


저작자 표시
신고
top


[GAE 시리즈] 2. 구글 로그인

모하니?/Coding : 2010.08.03 06:22


http://code.google.com/intl/ko-KR/appengine/docs/java/gettingstarted/usingusers.html

        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        if(user != null) {
            resp.setContentType("text/plain");
            resp.getWriter().println("Hello, " + user.getNickname());
        } else {
            resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
        }

이 코드가 핵심인데.. 많은 것들을 해준다.

1. 우선 무척이나 간단하다. 이렇게 쉽게 구글 로그인을 연동할 수 있다니... API도 직관적이라 어떤 일을 하는지 쉽게 알 수 있다. 마지막 줄의 코드가 로그인 한 다음 바로 로그인을 요청한 페이지로 이동하기 위한 API 인데 흠.. 괜찮은 것 같다. 권한 관리는 어떻게 하는지..  실제론 스프링 시큐리티랑 연동해서 쓰는지 아님 구글에서 제공하는 인증/권한 관리 API가 있는 것인지.. 있다면 권한 관리 설정은 편리한지 궁금하다.

2. 로그인 화면 자동생성. 로그인이 필요할 때 guestbook 예제에서 봤던 로그인 화면이 등장하는데 나는 그런 JSP 파일을 만든적도 없는데 알아서 만들어줬다. 편리하다.

3. 간편할 뿐 아니라 이 코드는 개발 환경과 배포 환경에 따라 동작 방식이 바뀐다. 오.. 놀라워라; 즉 개발환경에서는 아무런 아이디만 넣어도 로그인이 되고, 관리로 로그인하기 체크 박스가 존재한다. 하지만 GAE에 배포하는 순간 실제 구글 계정으로 로그인 한단다. 아직 GAE에 배포는 안해봤다. 그런데.. 개발할 때 실제 구글 계정으로 테스트해보고 싶으면 어쩌지?? 

4. 로그아웃 URL로 제공한다. userService.createLogoutURL()을 사용하면 된다.


저작자 표시
신고
top

TAG GAE, Java

[GAE 시리즈] 1. 구글 앱 엔진 + 메이븐 + IntelliJ 프로젝트 세팅

모하니?/Coding : 2010.08.03 05:21


구글 앱 엔진 시작하기 메뉴얼을 보며 예제를 실습해봤다. 그러나.. 내 입맛에 맞지 않는 구석이 몇개 있었다.

1. 라이브러리를 맘대로 추가할 수 있으니 코딩하는데는 문제가 안되는데 빌드가 보통 앤트를 사용하는 듯하다. 이건 불편하다. 그래서 메이븐을 썼다. GAE가 원하는 프로젝트 구조를 건드리지 않으면서도 필요한 라이브러리는 쉽게 가져다 쓸 수 있도록 메이븐을 설정했다. 이전에도 계속 써오던 형태라 대충 복사해서 붙여넣기고 당장 필요없는 라이브러리는 뺐다. (사실 스프링은 남겨뒀다;;)

2. 이클립스 종속적인 가이드였다. 인텔리J도 GAE 플러긴이 있으며 업데이트 사이트를 추가하는 귀찮은 작업 없이도 간편하게 플러그인을 찾아서 설치할 수 있었다.

3. 배포 설정

웹 서버에 배포할 때 프로젝트 이름/out 폴더 밑으로 웹 컨텐츠를 전부 복사해서 배포하게 되어 있는데 난 프로젝트/web에 배포하게 설정했다. 이래야 재배포 하지 않고도 JSP를 수정할 때 마다 바로바로 적용된다. 


저작자 표시
신고
top

TAG GAE, IntelliJ, Java

2010년 계획 (늦은) 중간 점검;;

모하니?/Planning : 2010.08.02 20:40


http://whiteship.me/2556 
  • IELTS general 6.0
  • Java Persistemce with Hibernate 번역
  • Spring Enterprise Recipe 번역
  • 몸무게 표준체형으로;;
  • 회사 시스템 여름까지 개발
  • 오픈소스 프로젝트 개발
  • 커뮤니티 활동 열심히
큰일이다. 이제 몇달 안남았는데 IELTS는 아직 시험도 안봤고 SER 번역은 절반 정도 하고 나서 무한정 쉬고 있고 운동은 전혀 안했고 회사 시스템은 개발중이긴 한데 과연 여름내에 끝낼 수 있을지 미지수.. 오픈소스 프로젝트는 10월까지 어떻게든 될 것 같다.

하아... 이대로 가다간 IELTS 6.0과 운동 그리고 SER 번역까지 미지수다. 번역은 그냥 하면 되니까 가장 쉬운편인데 가장 중요한건 운동과 IELTS 6.0이다. 이 두개에 더 신경을 써야겠다. 정신차려.. 기선아..

저작자 표시
신고
top


토비의 스프링 3

모하니?/Reading : 2010.07.27 10:32



http://www.yes24.com/24/goods/4020006

드디어 나왔네요. (사실 예판 시작한지는 꽤 됐는데 제가 블로깅을 깜빡하고 있었네요.ㅋㅋ 이미 한 줄 알았어요.) 제가 쿨하지 못해서 결국 제 추천사도 들어갔습니다. 온라인 서점에는 제 추천사를 볼 수 없지만 책을 사시면 제 추천사도 들어있을 겁니다. 캬캬캬.

날씨도 덥고 휴가철이라 공부하기 많이 힘드실 겁니다. 그런데 사실 이럴때가 더 공부하기 좋은 때 입니다. 남들이 덥다고 놀고 지쳐있을 때.. 그럴 때 꾸준하게 달리면.. 두배나 빠르게 달리는 거나 마찬가지 거든요. 마침 다음주부터 매주 토요일 4주 과정으로 한빛교육센터에서 이 책으로 강의를 시작합니다.

강의를 들으시는 분들께는 교재삼아 '토비의 스프링 3'이 지급될 겁니다. 교재비는 따로 내는 것 같진 않더군요. 무더운 스프링을 토비의 스프링 3으로 이겨내시죠. 이열치열삼아...
저작자 표시
신고
top


주말 강의는 2주 연기

모하니?/Thinking : 2010.07.20 21:05


휴가철이라 그런지 수강생이 10명이 채 안되서 주말 강의를 부득이 하게 2주 연기하게 되었습니다. 스프링 강의 뿐 아니라 아이폰까지도 그런걸 보면 제 잘못은 아닙니다. ㅋㅋ 전 정말 열심히 준비 했고 열심히 강의 했습니다. 물론 부족한 점도 많았지만 앞으로 계속 조금씩 보완해 나가겠습니다. 2주가 연기되서 오히려 좋은 점도 있습니다. 잘하면 토비님 책을 들고 바로 수업을 시작할 수 있을 것 같습니다. 

거럼 다음 강의 때 뵐께요~

저작자 표시
신고
top


[스프링 3 이해와 선택] 2차 강의 진행합니다.

모하니?/Planning : 2010.07.19 15:52


이번주 토요일부터 시작입니다.

http://www.hanbitedu.co.kr/incumbent/shortContent.do?index=1097

강의 준비하느라 홍보를 게을리 했더니 수강생이 몇 분 안되는 듯 합니다. ㅠ.ㅠ
아니면 휴가철이라 그럴지도...

강의는 토비의 스프링 3을 교재로 진행하고, 대략 일정은 다음과 같습니다.

1주차
- 오브젝트와 의존관계
- 테스트
- 템플릿

2주차
- 예외
- 서비스 추상화
- AOP

3주차
- IoC 컨테이너와 DI
- 데이터 엑세스 기술

4주차
- 스프링 웹 기술과 스프링 MVC
- 스프링 @MVC
- 스프링 기타기술

소스코드, 코딩 동영상, PPT 까지 준비 된 상태이고 앞으로는 게임이나 퀴즈 같은 게임 요소를 추가할 생각입니다. 무더운 날씨에도 즐겁게 공부해 봅시다.
저작자 표시
신고
top


네가 있어서 정말 감사하다.

모하니?/Thinking : 2010.07.12 23:32


지난 주말 장모님 댁에 갔을 때 '오늘 하루도 눈을 뜨면 그 자체로 너무 감사하고 고맙다.'라는 말을 들었다. '네'라고 대답은 했지만 사뭇 이해가 되지 않았다. 어떤 뜻인지는 머리로는 이해가 되는데 가슴으로는 와닿질 않았다. 나는 요즘 눈을 뜨면 '오늘은 적어도 이걸 해야되는구나...  아.. 저것까지도 하면 좋겠는데..' 이런 생각을 제일 먼저 한다. '내가 건강한 상태로 지금 오늘을 맞이 할 수 있어서 정말 고맙다.' 이런 생각은 거의 안해본것 같다. 오히려 불만이 더 많았다. '난 왜 이것도 못하지... 난 왜 이것 밖에 안돼지.. 난 왜.. 난 왜.. 난 왜..."  이런 생각만 하고 살아왔다고 해도 과언이 아니다.

그런데, 오늘 문득 성윤이를 만나고 돌아오는 길에 그런 생각이 들었다. '성윤이를 만난건 정말 대단한 행운이구나. 고맙다.'라는 생각이 들었다. 성윤이가 봄싹에서 열심히 활동해 준 것도 고마운 사실이지만 사실 성윤이가 스터디에서 활동한 것 보다는 김성윤이라는 개발자를 알게 된 것 자체가 고맙게 느껴졌다. 정말 치열하게 삶에 도전하고 노력하는 성윤이 같은 개발자가 내 옆에 있었다는 사실이 고맙게 느껴졌다.

이제 몇일이 지나면 온라인으로밖에 볼 수 없는 사이가 되겠지만... 뭐 설마 영영 못보겠어? 다시 볼 그날까지 절대로 너에게 부끄러운 모습이 되지 않도록 유념하며 살겠다. 그러니 너도 잘 살고 있어야 돼. 

고맙다.

나중에 만나서 라이브 코딩으로 한판 겨뤄보자꾸나.. 통키와 타이거처럼.. 말이지..





저작자 표시
신고
top


버즈 버그 미투 장애




1. 사진 안나옴
2. 난 '좋아요'를 취소 했는데... 아직도 좋아요 상태.

자기들도 알테니.. 열심히 고쳐주겠지. 어이 구글~ 잘못하면 웨이브 꼴 나는거야... 열심히 해줘...
그나저나 첫날은 8시간을 자라는데.. 그럼 난 무조건 지각인데;; 흠... 10시에 자야되나.. 1시간 남았네;; @_@


미투는 아에 장애다... 장애;;; 흠.. 어감이 별로네. 서비스 "점검중"이 훨씬 좋겠다.  

흠... 미투 가입할때 주민번호를 넣었던가.. 안넣은것 같기도 하고. 암튼 한국 사이트들은 제대로 지켜줄꺼 아니면 주민번호좀 그만 받아라. 주민번호 누출시켰으면 제대로 보상이나 뒷처리를 해주던가... 아! 그것도 무슨 법 때문에 그런거라고 들은것 같은데 잘 기억은 안나네.. 흠...


저작자 표시
신고
top

TAG 버즈

[이전글에 이어지는 이야기] 숫자에서 객체로...

모하니?/Coding : 2010.07.07 13:21


... 윗부분 생략 
               double qtyIn = invInDao.getQtyOf(today, item, location);
                // 금일 출고량 조사
                double qtyOut = invOutDao.getQtyOf(today, item, location);
                // 금일 재고량 계산
                double qtyEnd = qtyStart + qtyIn - qtyOut;

                if(isEmpty(qtyStart, qtyIn)){
                    continue;
                }

                InvDailyClosing invDailyClosing = new InvDailyClosing();
                invDailyClosing.setDate(today);
                invDailyClosing.setLocation(location);
                invDailyClosing.setItem(item);
                invDailyClosing.setQtyStart(qtyStart);
                invDailyClosing.setQtyIn(qtyIn);
                invDailyClosing.setQtyOut(qtyOut);
                invDailyClosing.setQtyEnd(qtyEnd);
...아래도 생략

쓰고나서 생각하니 약간 위험한 글을 썼다는 생각에 괜히 불안했는데..  아니나 다를까... 대용량 데이터베이스를 공부하고, 자바 코드로 치우져서 보는거 아니냐, 벽을 세워놓고 한쪽만 보는건 좋치 않다. 라는 글이 달렸었는데 사라졌다.

하아.. 본문에도 적었지만 사실 내가 대용량 DB를 다루는 SQL을 잘 못하는건 사실이다. 근데 어쩌겠는가.. SQL을 하고 싶지 않아서 안하는게 아니라 SQL을 작성할 일이 별로 없는데다, 대용량 데이터는 내가 만지고 싶다고 만질 수 있는 것도 아니다. 난 이럴 때 마다 떠올리며 나를 위로하는 문구가 있는데.. 켄트벡이 쓴 "테스트 주도 개발" 뒷부분 어딘가 보면 그런 말이 있다. 아.. 이런.. 문제의 크기와 해결방법에 관한 거였는데.. 까먹었다. 암튼 0과 1을 떠올리게 하는거였는데 ㅠ.ㅠ

생각해보니, 재고 마감 데이터가 입고와 출고 수량만 들고 있는게 아니라, 해당 마감 데이터에 해당하는 입고 목록과 출고 목록을 들고 있는게 더 유용하겠다는 생각이 들었다. 그렇게 해야 "재고 마감 뷰"에서 해당 마감에 대한 입고 내역과 출고 내역을 보여주기 편할 것 같다. 아니면 마감 데이터를 가지고 해당 마감에 해당하는 입고목록과 출고 목록을 가져오는 기능을 입고DAO와 출고DAO에 추가해줘야 하는데... 글쎄... 흠냐.. 그거 만들기 귀찮아서 기능을 고치고 있는 기분도 들지만, 왠지.. 설계상으론 더 객체 지향적이고 멋진 것 같다.

이런 로직을 반영하려면 숫자보다 객체를 들고 있게 하는게 편하고.. SQL 보다.. 위와 같은 자바 코드를 수정하는게 더 편한데...그건 내가 그렇다는 것이고...  사람에 따라, 상황에 따라, 대용량인지 아닌지에 따라.. 달라질 수 있겠다..

                List<InvIn> invInList = invInDao.listOf(today, item, location);
             List<InvOut> invOutList = invOutDao.listOf(today, item. location);

                if(isEmpty(qtyStart, invInList)){
                    continue;
                }

                InvDailyClosing invDailyClosing = new InvDailyClosing();
                invDailyClosing.setDate(today);
                invDailyClosing.setLocation(location);
                invDailyClosing.setItem(item);
                invDailyClosing.setQtyStart(qtyStart);
                invDailyClosing.setInvInList(invInList);
                invDailyClosing.setInvOutList(invOutList);
                invDailyClosing.closing();

                dao.add(invDailyClosing);

결국은 이렇게 바뀔 것 같다. InvDailyClosing 도메인 객체의 closing() 메소드에서 입고 목록, 출고 목록, 전날 재고를 가지고 금일 재고를 계산하도록...말이다. 물론.. 이정도 쯤이야. SQL로도 간단하게 할 수 있겠다(?). 난 잘 모르겠지만..

저작자 표시
신고
top


복잡한 로직은 복잡한 DAO로 직결되는가?

모하니?/Coding : 2010.07.07 10:14


아니지 않을까... 비즈니스 로직이 복잡하다고 해서 SQL이 복잡해 질 필요는 없다.

재고 마감 로직을 생각해보자. 모든 창고에 들어있는 모든 상품들의 전일 재고량, 금일 입고량, 금일 출고량을 가져와서 금일 재고량을 계산한다고 치자. 이걸 가지도 또 상품 카테고리 별로 묶고 창고 별로 묶어서 집계를 내야 하는데.. 일단은 그 전 단계까지만 해보자.

Location - Inventory
Item - Inventory
Item - InvIn
Item - InvOut
Item - InvDailyClosing

이렇게 관계가 맺어져 있으니 SQL로 join을 하던 sub select를 하던 어떻게든 SQL 한방으로 어떤 창고에 있는 어떤 상품의 '전일 재고량', '금일 입고량', '금일 출고량'을 한방에 가져올 수 있을 것 같다.

근데 난 그렇게 하지 않는다. 사실 그렇게 복잡한걸 만들지도 못한다. 만들라면 공부해가면서 만들겠지만 무지 오래 걸릴 것 같다. 그래서 난 그냥 자바 코드로 SQL을 대신한다.

        dao.delelteAllAt(today);

        for(Location location : locationDao.getAll()) {
            // 모든 상품 마다
            for(Item item : itemDao.getAll()){
                // 전일 재고량 조사
                double qtyStart = inventoryDao.getQtyOf(yesterday(today), item, location);
                // 금일 입고량 조사
                double qtyIn = invInDao.getQtyOf(today, item, location);
                // 금일 출고량 조사
                double qtyOut = invOutDao.getQtyOf(today, item, location);
                // 금일 재고량 계산
                double qtyEnd = qtyStart + qtyIn - qtyOut;

               나머진 생략...
            }
        }

즉 이런식으로 짠다. 굵은 글씨 부분은 DAO test를 해서 해당 기능이 내가 원한대로 동작하는지 일일히 확인해다. DBUnit을 사용해서 테스트용 데이터를 넣고 저 기능을 실행해보는 방식이다. 이렇게 구현하니까 상당히 마음이 놓인다. 저걸 만약 한방에 SQL로 구현했다던지.. 테스트 없이 구현했다면.. 글쎄.... 그렇겐 못했을 것 같다.

암튼 이래서.. 복잡한 로직을 처리하는 DAO 코드라 할지라도 단순해진다. 이런걸 디바이드 앤 퀀쿼 라고 하던가.. 몰겠다. 머라하든.

    public double getQtyOf(Date date, Item item, Location location) {
        Object result = getSession().createQuery("select sum(qty) from InvIn where date = :date and item = :item and location = :location group by item")
                .setDate("date", DateUtils.getDateOnly(date))
                .setEntity("item", item)
                .setEntity("location", location)
                .uniqueResult();
        if(result == null)
            return 0.0;
        return (Double) result;
    }

대충 이정도 코드가 생기는데.. 이정도야 뭐.. 초간단 SQL 수준 아닌가..

이렇게 짜면 걱정되는게.. 성능인데... DB에 자주 다녀올수록 더 많은 부하가 생기는건 사실이지만 어차피 복잡한 쿼리 자체도 join 여러번 하면서 부하가 생길테니.. SQL 도사가 아닌 이상 차라리 성능을 조금 포기하고 유지 보수 가능하고 알아보기 쉬운 코드로 나눠서 작성하는게 더 좋치 않을까 싶다.





저작자 표시
신고
top


스프링 DAO 3파전

모하니?/Coding : 2010.07.02 13:00


JDBC를 사용하는 부류가 있고, iBatis를 사용하는 부류가 있고, 하이버네이트를 사용하는 부류가 있다. 사실 이보다 더 다양한 영속화 기술들이 있지만.. 이 세 부류로 간추려 보려고 한다. 자 이들은 각각 어떻게 코딩을 하고 있을까.

public interface MemberDao {
void add(Member member);
void update(Member member);
Member get(int id);
List<Member> list();
void delete(int id);

}

이런 인터페이스를 각 부류에서 구현한다고 생각해보자.

아참, 전제는 스프링을 사용한다는 것이다.

1. JDBC

@Repository
public class MemberDaoJdbc implements MemberDao{
@Autowired SimpleJdbcTemplate jdbcTemplate;
public void setMemberMapper(RowMapper<Member> memberMapper) {
this.memberMapper = memberMapper;
}

RowMapper<Member> memberMapper = new RowMapper<Member>(){
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member member = new Member();
member.setId(rs.getInt("id"));
member.setName(rs.getString("name"));
member.setJoined(rs.getDate("joined"));
return member;
}};
public void add(Member member) {
jdbcTemplate.update("insert into member(id, name, joined) values (?, ?, ?)", 
member.getId(), member.getName(), member.getJoined());
}

public void delete(int id) {
jdbcTemplate.update("delete from member where id = ?", id);
}

public Member get(int id) {
return jdbcTemplate.queryForObject("select * from member where id = ?", memberMapper, id);
}

public List<Member> list() {
return jdbcTemplate.query("select * from member", memberMapper);
}

public void update(Member member) {
jdbcTemplate.update(
"update member set name = :name, joined = :joined where id = :id", 
new BeanPropertySqlParameterSource(member));
}

}

대충 이런 코드가 된다. 스프링이 제공해주는 SimplJdbcTemplate은 멀티 쓰레드 환경에서 공유하면서 사용해도 안전한 객체이다. 따라서 빈으로 등록해놓고 주입받아서 쓴다고 한들 문제될 것이 없다. 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
@Transactional
public class MemberDaoJdbcTest {
@Autowired MemberDaoJdbc memberDao;
@Test
public void di(){
assertThat(memberDao, is(notNullValue()));
}
@Test
public void crud(){
Member member = new Member();
member.setId(1);
member.setName("whiteship");
member.setJoined(new Date());
memberDao.add(member);
assertThat(memberDao.list().size(), is(1));
member.setName("기선");
memberDao.update(member);
assertThat(memberDao.get(1).getName(), is("기선"));
memberDao.delete(1);
assertThat(memberDao.list().size(), is(0));
}
}

테스트는 대충 만들었기 때문에 너그럽게 봐주시길...^_^;;;

2. iBatis

스프링에 iBatis의 SqlMapClient를 만들어 주는 팩토리빈을 등록해야 한다.
   
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="SqlMapConfig.xml" />
</bean>

아이바티스 설정 파일도 추가한다. 저 설정에 보이는 SqlMapConfig.xml이 필요하다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
<sqlMap resource="sample/ibatis/Member.xml" />
</sqlMapConfig>

그 다음 Member와 관련있는 SQL을 모아둔 Member.xml 파일을 만든다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Member">
<typeAlias alias="Member" type="sample.domain.Member" />

<delete id="delete" parameterClass="int">
delete from member where id = #id#
</delete>

<insert id="add" parameterClass="Member">
insert into member (id, name, joined) values(#id#, #name#, #joined#)
  </insert>
 
<update id="update" parameterClass="Member">
update member set name = #name#, joined = #joined# where id = #id#
</update>
 
<select id="get" parameterClass="int" resultClass="Member">
select * from member where id = #id#
  </select>

<select id="list" resultClass="Member">
select * from member order by id
  </select>
</sqlMap>

XML 엘리먼트와 어트리뷰트는 별도의 학습이 필요하지 않을만큼 직관적이다.. 이제 DAO 코드를 작성하자.

@Repository
public class MemberDaoIbatis implements MemberDao {
@Autowired SqlMapClientTemplate sqlMapClientTemplate;
public void add(Member member) {
sqlMapClientTemplate.insert("add", member);
}

public void delete(int id) {
sqlMapClientTemplate.delete("delete", id);
}

public Member get(int id) {
return (Member) sqlMapClientTemplate.queryForObject("get", id);
}

@SuppressWarnings("unchecked")
public List<Member> list() {
return sqlMapClientTemplate.queryForList("list");
}

public void update(Member member) {
sqlMapClientTemplate.update("update", member);
}

}

흠 많이 짧아졌다. 그런데.. 전체 코드량은 더 많이 늘은것 같지 않은가? 코드량이 척도의 전부는 아니지만.. 왠지 작업이 줄었다가 보다는 DAO에서 할일을 설정파일로 미뤘다는 느낌이 강하다. 아참 여기서 사용한 SqlMapClientTemplate도 SimleJdbcTemplate과 마찬가지로 빈으로 등록해서 사용해도 별 지장이 없는 쓰레드-안전한 클래스기 때문에 빈으로 등록해놓고 사용했다.

3. Hibernate

이것도 역시 빈을 하나 설정해줘야한다.
 
   <!-- ============================================================= -->
    <!--  Hibernate                                                    -->
    <!-- ============================================================= -->
    <bean id="transactionManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager"
          p:sessionFactory-ref="sessionFactory"/>

    <bean id="sessionFactory"
          class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="sample.domain" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

이번건 설정이 제법 길다. 그리고 빈이 하나가 아니라 두갠데.. 그건 나중에 TransactionManager에 대한 글을 올릴 때 설명해야겠다. 아니면 그냥 토비님 책을 보기 바란다. 11장에 자세히 설명해주시고 있다. TransactionManager와 기반 기술의 관계(?)랄까나.. 암튼.. 이제 바로 DAO를 만들 수 있다. 아 아니다 일단 Member 클래스에 애노테이션 부터 추가하자.

@Entity
public class Member {

@Id
int id;

...
}

이렇게 두 군데에 각각 하나씩만 붙여주면 된다. 이제 DAO를 만들자.

@Repository
public class MemberDaoHibernate implements MemberDao{
@Autowired SessionFactory sessionFactory;

public void add(Member member) {
getSession().save(member);
}

public void delete(int id) {
getSession().createQuery("delete from Member where id = ?")
.setInteger(0, id)
.executeUpdate();
}

public Member get(int id) {
return (Member) getCriteria()
.add(Restrictions.eq("id", id))
.uniqueResult();
}

@SuppressWarnings("unchecked")
public List<Member> list() {
return getCriteria().list();
}

public void update(Member member) {
getSession().update(member);
}

private Criteria getCriteria() {
return getSession().createCriteria(Member.class);
}

private Session getSession() {
return sessionFactory.getCurrentSession();
}
}

SQL이 없다. SQL처럼 보이는 HQL(굵은 글씨)만 보인다. 이렇게만 하면 정말 DAO가 구현되는지 의심스럽겠지만 정말 구현이 끝난다. 하지만 하이버네이트 Session과 Criteria API는 약간 학습이 필요하다. 자주 쓰는 API는 몇개 안되기 떄문에 대략 1시간 정도면 익힐 수 있다.

셋 개 다 해본결과.. 난 역시 하이버네이트가 편하다.
저작자 표시
신고
top


전자정부 프레임워크 공통 컴포넌트 실행 성공(?)

모하니?/Coding : 2010.06.25 15:13



이 화면 보기가 너무 힘들다;

OSAF 예제 애플리케이션 띄우는거 보다 100배는 올래거리는것 같다. 

그나마 이 화면에서 다음으로 전개도 안된다. 왜냐면 DB가 세팅되지 않았기 떄문에;;

전자 정부 사이트에서 받은 mysql용 sql 파일들을 돌리다 보면 계속 에러가 난다. 자주 보이는 건 주키가 너무 길다는 에러인데 이건 주키 컬럼 사이즈(보통 메서드 이름이 200으로 잡혀 있었다.)를 줄여가면서 지나갔다. 그런데 두번째 sql 파일의 에러는 도무지 모르겠다; MySQL을 설치한지 오래되서 새 버전으로 올린 담에 해봐야 하는건지.. 그냥 오라클로 해야하는건지... 아흑..

맞다. DB만 만들다고 돌아가는것도 아니다. globals.properties 파일을 C:\Documents and Settings\MyHome\egovProps 이 위치에 넣어줘야 하고 이걸 제대로 쓰려면 그 파일에 있는 각종 설정 내용을 다 손봐줘야 한다.

이거.. 아무래도 내가 너무 무모만 것에 손을 댄것 같다. 덕분에 전자 정부 프레임워크 구조가 어떤지 파악할 수 있었다.

개발 환경쪽에서 '구현도구'라고 되어있는 이클립스를 받아서 전자정부 웹 프로젝트를 만들어야지 필요한 pom.xml이 나오지만 사실상 이건 제대로 된 pom.xml파일이 아닌것 같다. 그래도 일단 이렇게 받는다.

http://www.egovframe.org/wiki/doku.php?id=egovframework:배포_패키지_구성안

여기에서 공통여부 Y로 체크되어 있는 것은 무엇을 클릭하던 똑같이 egovframework-common-1.0.0를 받게 된다. 저 안에 수많은 공통 기능이 들어가 있다. 즉 저것을 넣어서 앱을 실행하면 전자정부 프레임워크 도입을 완수한거나 마찬가지다. 거기에 부가적으로 게시판이나 통계등을 넣고 싶다면 해당 메뉴를 클릭해서 소스를 받은 다음 프로젝트에 추가해줘야 한다. 

이 "공통 컴포넌트"라고 하는 서비스들은 "실행 환경"을 기반으로 하고 있다. 실행 환경 코드는 다시 네가지로 나뉜다. 공통기반, 데이터처리, 연계통합, 화면처리.. 이 중에서 웹 관련 기능이 궁금하다면 "화면 처리" 코드를 받아서 보면 된다.

하지만 안타깝게도 이 "실행 환경"에서 받는 코드들은 pom.xml이 없다. 빌드가 되지 않는다. 아참;; 위에서 설명하려다 까먹었는데.. "개발 환경"에서 자동으로 만들어준 pom.xml은 버리고 "공통 컴포넌트" 중에서도 "공통"에 해당하는 egov~~-common-1.0.0을 받으면 들어있는 pom.xml이 있다. 그걸 쓰면 "공통 컴포넌트"에 필요한 의존성까지 설정되어 있으니 무난히 빌드할 수 있다. 어쨋거나 이 코드들은 그냥 쌩으로 봐야한다. 빌드가 안되니.. 별도의 jar 파일을 만들수도 없다. (원래 안만들어도 된다. jar 파일만 따로 다운 받을 수도 있고, 공통 컴포넌트의 pom.xml에서 의존성으로 알아서 가져오게 되어 있다.) 정... 하고 싶으면 pom.xml 만들고 필요한 의존성 다 붙여주면 되는데.. 글쎄;; 별로..

소스 중에 유일하게 살펴본 코드로는 "화면처리(ptl)"에 들어있는 SimpleUrlAnnotationHandlerMapping이 있는데 이름에서는 추측하기 어려운 일을 해준다. 핸들러 매핑 마다 일괄적용되는 인터셉터가 부담스러워서 그걸 url 리스트를 사용해서 걸러주는 작업이다. 그런데 토비님 책을 보면 스프링 3.0의 <mvc:inteceptor>로 해결이 가능하다. 글로벌한 인터셉터 설정이기 때문에 핸들러 매핑을 기준으로 생각할 필요가 없어졌다. 아마도 저 클래스는 주석에도 적혀있듯이 3.0 가면서 deprecated 될 것 같다.
저작자 표시
신고
top




: 1 : 2 : 3 : 4 : ··· : 32 :





티스토리 툴바