Whiteship's Note


봄싹 관련 사이트 정리



봄싹 홈페이지: http://springsprout.org
봄싹 그룹스: http://groups.google.co.kr/group/springsprout?hl=ko
봄싹 이슈트래커: http://jira.springsprout.org/browse/SSD
봄싹 위키: http://wiki.springsprout.org
봄싹 코드: http://code.springsprout.org/browse/SpringSprout

이밖에도 몇개 더 있지만... 점점 취미활동 범위를 넘어서는 것 같다...
아니 어쩌면 이미 진작에 넘었는지도 모르겠다...
저작자 표시
신고
top

TAG 봄싹

봄싹은 마치 경차같은...

모하니?/Thinking : 2010.03.02 11:18




커뮤니티의 규모가 작다고해서 그 구성원들의 실력이나 커뮤니티의 내실이 허술한 건 아니죠. 

흠.. 그래도 이러한 사회적 착각이 팽배한 사회라면... 어차피 유지비도 그게 그거라던데 대형차로 갈아타는 것도 편할 것 같습니다.

걍 그렇다구요.ㅋㅋ 
저작자 표시
신고
top

TAG 봄싹

2010 대한민국 매쉬업 참가했습니다.

모하니?/Coding : 2010.01.20 16:30


"개발 용어 한글화 프로젝트 DevTerms"로 참가했습니다. 이 녀석을 어제 배포하고 밤새 나머지 주요 기능 중 하나였던 '관심 용어'까지 구현한 뒤 배포하고 참가 신청까지 완료했습니다. 2010 매쉬업 참가 목록에서 보실 수 있습니다.


위에 보시면 아시겠지만 작년 11월부터 이미 DevTerms를 만들고 싶다는 이야기를 봄싹 그룹스에서 했었습니다. 그러던 중 매쉬업 소식을 듣게 되었고 DevTerms에 오픈 API를 적용해서 내보내게 된 겁니다. 1석 2조가 됐지요. 어차피 봄싹에 새 기능으로 추가할 계획이었고 그 기능에 필요한 오픈 API를 적용해서 매쉬업까지 나갔으니 말이죠.

그래서 그런지 제가 제출한 제품은 매쉬업이 메인이 아니라 '개발 용어 한글화' 서비스가 메인입니다. (벌써 43개나 제출됐네요.. 캬오.)그걸 보조하는 수단으로 사전 API와 트위터 API 사용하고 있죠. 사전 API는 기대 했던 것 보다 효과가 좋다고 생각하고 있습니다. 개발 용어는 영어 사전으로 검색한 결과를 보여주고 한글 용어는 한글 사전으로 검색한 결과를 보여주고 있습니다. 트위터 API를 이용하여 등록되는 용어들을 트위터 메시지로 등록해주고 링크를 타고 봄싹 DevTerms로 올 수 있게 해뒀습니다. 트위터 서비스만 해두면 사용자들이 트위터 RSS 피드나 노티 애플리케이션을 이용해서 등록되는 용어들을 실시간으로 받아 볼 수도 있지요.

http://twitter.com/devterms

사실 중간에 매쉬업 참가를 포기할까도 고민했습니다. 혼자서 디자인까지 신경쓰면서 기능 구현을 하자니 중간에 탁탁 끊기는 느낌이고 누군가 제가 집중해서 기능을 구현하고 있으면 그 동안 만든 페이지들 디자인을 점검하고 개선해주면 좋겠다 싶어서 봄싹 팀원에게 도움을 요청했습니다. 다행히 그 친구가 흔쾌히 승낙하고 휴가까지 반납하고 우리 회사로 찾아와 개발을 해주었기 때문에 일정과 품질을 다 기대했던 것 만큼 맞출 수 있었다고 생각합니다. 회사나 계약 등으로 묶여서 같이 일하는 것이 아니라 순수한 열정으로 묶여서 '함께 일한다'는 것이 무엇인지 조금은 알 수 있을 것 같은 기분입니다.

개발에 투자한 일수는 얼마 되지 않습니다. 1월 초까지도 번역을 하고 있었고 JSF를 공부하던 중에 갑자기 매쉬업이 생각나서 저번주부터 오늘까지 한 10일 정도 달린 것 같습니다. 하지만 투자한 시간은 거의 한달 정도 회사일에 투자한는 시간이었던 것 같습니다. 아침 10시부터 새벽 5시까지 전철 타고 밥먹는 시간 뺴고 코딩만 해본건 처음이었습니다. @_@ (어제와 오늘은 출근 길에도 전철에서 코딩을 했습니다. 아흑.. '쟤 모야... '이런 사람들의 시선도 무시한 채 꾿꾿히..) 이렇게 빠져버린 날 이해해준 아내에게 그저 고맙고 미안할 뿐입니다.

원래 계획은 1월 20일. 오늘부터 다시 번역에 집중해서 2월 달 안에 번역을 마무리하는게 계획이었습니다. 그런데 왠걸.. 24일까지 수정할 수 있게 해준다는군요. 뭐 기존에 생각했던 기능들은 다 만들었지만 막상 써보니까 생기는 요구사항들을 무시할 순 없을 것 같습니다. 24일까지만 손을 대고 후딱 번역을 마무리 한 다음 3월부터 진정한 2010년을 맞이해야겠습니다. 후아...

결과가 어찌될지 몰겠지만 수고했다. 기선아. 조금만 더 하고 마무리하자.





신고
top


개발 용어 한글화 프로젝트 "DevTerms"

모하니?/Coding : 2010.01.19 19:34


봄싹에서 진행하는 프로젝트 중 하나입니다. 저번 주부터 이녀석 개발하느라 번역도 안하고 회사일도 미루고 잠도 줄이면서 올인했습니다. 아직도 좀 더 만들어야 하는데 일단 사용할 수 있을 정도가 됐다는 판단하에 배포했습니다. (그런데 오판이었어요. 고치고 만들께 아직도 많네요. @_@)

이 프로젝트의 목적은 다음과 같습니다.

- 공동 역자들의 용어 통일화
- 개발 용어에 대한 이해
- 개발 용어 한글화에 대한 근거 확보
- 다수가 선호하는 한글 용어 식별
- 개발 용어 태그 정리

http://springsprout.org/term/index.do



사용해 보시고 의견 주세요~




신고
top


봄싹 Career Path

모하니?/Planning : 2009.12.17 15:19


저는 봄싹 대표가 아니라 운영진 중 한명으로써 봄싹 스터디를 어떻게 키워나갈지 항상 고민하고 있습니다. 사실 대표가 왜 필요한지도 잘 모르겠어요. 규모가 작아서 그런가.. 아무튼 성윤군과 정우형 등 팀원들이 잘 도와주고 있어서 별다른 어려움은 못 느끼고 있습니다.

어쨋거나, 그건 그렇고 봄싹 커리어 패스를 생각해봤습니다.


현재 스터디 모임을 벗어나 개발자 모임으로 성장했다고 생각합니다. 이 단계에서 아직 못 이룬 것이 있다면 "세미나"입니다. 요즘 날이 추워서;; 내년 봄에 지금까지 봄싹에서 진행한 스터디와 프로젝트 내용을 종합하여 세미나를 가질 생각입니다. 아직 구체적으로는 계획하진 않았지만 꼭 할 겁니다.

2009년은 개발자 모임으로 진화했다면 2010년에는 좀 더 새로운 모습으로 진화하는 한 해가 되었으면 하는 바램입니다. 현재 스프링 3.0 레퍼런스 번역과 스프링소스 블로그 번역은 자체적으로 진행 중이며, 프로 스프링 2.5 베타리딩과 하이버네이트 베타리딩을 맡아 진행 중입니다. 그 외에도 저술과 원서 번역 계획을 가지고는 있지만 역시 이것도 아직 구체적으로 계획된 것은 없습니다. 하지만 아마도.. 할 것 같습니다.

물론, 진화를 한다고 해서 이전에 하던 것들을 모두 중단하지는 않습니다. 개발자 모임으로 바뀌었지만, 최근까지 오리지널 스프링 스터디를 진행했으며, 계속해서 새로운 스터디 주제거리(하이버네이트, 자바스크립트, JSF 등)가 생겨나고 있고, 새로운 스터디 방식을 모색 중입니다.

2010년에는 어떤 모습으로 변할지 기대 됩니다.
하지만 아직은 그 단계를 뭐라고 불러야 할지 떠오르질 않네요.

머라고 해야하지? @_@ "수퍼 울트라 캡숑 모임?"
신고
top


[봄싹] 점진적인 개발

모하니?/Coding : 2009.11.30 13:52


봄싹에서 Agile 방법론을 공부한 적은 없지만, 자연스럽게 그와 비슷한 형태의 개발이 진행되는걸 보는 재미가 쏠쏠 합니다. 그 중 하나로 점진적인 개발을 들 수 있습니다. 다들 바쁜 생업을 하는 중에 짬을 내서 개발을 하는 중인데다가, 배포 주기를 될 수 있으면 짧게 가져가고 있기 때문에 '설계'에 많은 시간을 투자할 여유도 없거니와 전부 개발자이자 고객이기 때문에 '요구사항 정리'나 '문서화'에 시간을 들여야 할 이유가 별로 없습니다. 그 대신 구글 그룹스에서 활발한 토론을 통해서 필요한 기능에 대한 대충의 윤곽을 잡은 다음, 해당 기능을 만들고 싶은 개발자가 스스로 원하는데로 만듭니다. 그 뒤에 누군가 피드백을 주면, 다시 개발자는 그 피드백을 고객의 요구사항이라고 생각하고 되도록이면 반영해줍니다. 또는 피드백을 준 개발자가 직접 해당 기능을 손보기도 합니다. 그 과정 중에 자연스럽게 점진적인 개발을 실천하게 됩니다.

봄싹 사이트 0.9

지금 보시는 화면은 봄싹 0.9 버전의 메인 화면입니다. 전부가 정적인 구성요소로 HTML 파일로 만든것과 다를바 없는 JSP 파일이었습니다.

현재는 아래처럼 바뀌었습니다.

1. 제일 처음 디자인이 바뀌었습니다. 페이지는 여전히 HTML과 다를바 없었습니다. 낙서장, 공지사항, 스터디, 위키, 세미나, 커버플로우, 협찬 로고 등 아무것도 동적인 데이터는 없었습니다.

2. 그러다 낙서장 기능이 추가됩니다. 낙서장도 처음에는 정적인 디자인부터 시작했고, 동적으로 li를 추가하게 바뀌었습니다. 여기서 사용한 기술이 조금 재미있습니다. 페이지 릴로딩을 하지 않고 Ajax로 요청을 주기적으로 보내서 HTML을 업데이트 하는 방식입니다. 사용자는 가만히 첫 페이지를 열어두면 다른 사람들의 낙서가 업데이트 되는걸 볼 수 있습니다.

3. 다음은 공지 사항이 추가되었습니다. 그러면서 낙서장은 계속해서 디자인이 바뀌고 스크롤 방식이 바뀌어 나갑니다. 공지는 제이쿼리 플러긴을 이용해서 이쁜 팝업을 띄우게 되었고, 공지 목록이 길어지면 스크롤링을 하기 위해 처음부터 모든 데이터를 가져오지 않고 애초에 Ajax로 필요한 만큼의 데이터만 가져옵니다. 하지만 아직 스크롤링이 완전히 구현되어 있지는 않습니다. 아직도 개발 중인거죠.

4. 다음은 스터디 목록을 추가했습니다. 이 부부는 Ajax를 사용하지 않았었습니다. 처음에는 스터디 목록만 전부 읽어와서 랜더링 될 때 보여주고 끝이었습니다. 그러나 조금 뒤에 바뀌게 됩니다. 공간이 넉넉하고 스터디에 속한 모임을 주로 참조하는 관계로, 모임 목록까지 보여줘야할 필요가 생겼습니다. 하지만 사용자가 어떤 스터디의 모임목록을 원하는지도 모르면서 모든 모임 목록을 가져오고 싶지는 않았습니다. 그래서 Ajax를 적용했고, 하이버네이트 쿼리 캐쉬를 적용해서, 일단 한번 DB에서 가져온 모임 목록은 일정 시간동안 다시 쿼리를 날리지 않고도 보여주게 했습니다. Ajax 요청 캐시까지 적용하면 더욱 좋겠지만, 그건 아직 다음 과제로 남겨뒀습니다.

5. 마지막은 위키였습니다. 위키 목록은 스터디 목록을 뿌리는 것과 동일했습니다. 다만 위키 제목이 길어질 여지가 있어서 길이를 어느정도로 짜른다음 ...을 붙이도록 개선했습니다.

이와 같이 메인 페이지를 구성하는 것들 중에 어느 하나도 한 번에 개발이 끝난것이 없으며, 지금도 사실 완전히 끝났다고 볼 수 없는 기능들이 많습니다. 메인 페이지의 구성요소 하나 하나도 자세히 히스트로리를 들여다보면 점진적으로 개발되고 있는 모습을 볼 수 있습니다. 낙서장이 대표적입니다. 처음에는 정적인 리스트였다가. Ajax로 추가할 수 있게 바뀌고, 스크롤바를 추가했다가, 지금은 마우스 드래그로 바뀌었고, 무한 드래그에서 끝이 막히는 드래그로 바뀌었습니다. 공지, 스터디, 위키도 그렇게 매우 자연스럽게 진화를 거듭하고 있습니다.

조금씩.. 쓸 수 있는 상태를 유지하면서.. 발전하기.

바로 이런게 점진적인 개발 아닐까요?

참조: 롤러스케이트 구현
신고
top


봄싹 사이트 1.0 M1 오픈 임박!!

모하니?/Coding : 2009.11.27 08:35


현재 봄싹 사이트(0.9)에서 보다 더 스터디 관리 기능을 보강했으며, 위키 디자인을 개선하여 편의성을 높였습니다. 트위터와 이메링을 비롯한 다양한 알림 서비스도 이용하실 수 있습니다. 특히 구글 토크를 사용하시는 분들은 스터디나 모임이 있을 때 메시지를 받을 실 수 있는것은 기본이고, 채팅창에서 study? meeting? 으로 현재 진행중인 스터디와 모임 정보를 확인하실 수도 있습니다. 홈 페이지에는 낙서장과 공지 사항을 추가했으며 스터디-모임 목록, 위키 목록으로 바로 이동할 수 도 있습니다. 또한 컨텐츠 작업으로, 스프링 3.0 레퍼런스 번역이 활발히 진행중입니다. 위키를 더 개선하고나면 저도 본격적으로 봄싹 컨텐츠 만들기 작업에 돌입할 생각입니다. 스프링소스 블로그 번역, 각종 웹 아티클 번역 자료를 봄싹 위키에 정리할 겁니다. 아무래도 제 블로그 보다는 위키가 찾아보기 편하니까요. (블로그에도 올리긴 할 겁니다.ㅋ)

내용적인 면이나 기능적인 면을 떠나서 이번 배포의 가장 큰 주안점은 바로 디자인입니다.

불과 두 달 사이에 획기적으로 달라진 봄싹 1.0 M1은 내일 낮에 오픈합니다.


Develop with passion! Evolve with SpringSprout!!




신고
top

TAG 1.0 M1, 봄싹

봄싹을 알리러 갑니다.

모하니?/Planning : 2009.11.24 10:47


http://www.ibm.com//developerworks/kr/event/seminar/dwlive_1205/index.html
http://www-903.ibm.com/kr/event/seminar/seminar.jsp?seminar_id=440

오늘 저녁에는 KSUG 모임에 가서 봄싹 사이트 개발과 관련된 내용을 요약해서 발표합니다.

다음주 토요일에는 한국 IBM "웹 개발 다반사"라는 행사에서 봄싹에 대해 발표 하고자 제의한 상태입니다. 페차쿠차 형식으로 발표를 진행한다는데.. 뭔지 다들 아시겠죠? 한 장을 20초 내로 넘기면서 총 20장 정도로 약 6.7분간 발표하는 독특한 발표형식입니다.

내년 봄에 날이 좀 따뜻해지기 시작하면, 봄싹 세미나를 할 계획을 가지고 있는데, 위 두 가지 활동은 그 사전 준비에 해당하는 활동이라고 볼 수 있습니다. 이밖에도 각종 행사에 봄싹 타이틀을 걸고 출전할 계획도 가지고 있습니다.

봄싹은 더이상 스터디만 하는 커뮤니티가 아닙니다. 온라인에서 잡담만 나누는 커뮤니티도 아닙니다. 이미 올해 중반부터는 스터디 보다는 개발에 더 많은 비중을 두고 있고, 현재도 스터디 계획 못지 않게 여러가지 개발 계획을 가지고 있습니다. 개발 뿐인가요? 번역과 베타리딩에 대한 계획도 있고, 각종 대회 출전 계획도 있습니다. 모임의 형태가 완전히 달라졌습니다. 한마디로 진보했습니다. 그리고 그 속에서 팀원들의 스킬도 여러 면에서 향상되고 있습니다. 단순히 개발 스킬 뿐 아니라, 커뮤니테이션 스킬과 발표 스킬 그리고 운영 능력을 키우고 있습니다.

이러한 발전을 이룩한건 전부 다 봄싹 팀원들이 각자 열심히 노력한 결과이자 과정이며, 그것들을 여과나 포장없이 순수하게 공유하고 받아들이는 팀원들의 마인드가 중요했다고 생각합니다. 이러한 발전 속에서 기술적으로 혹은 문화적으로 어떠한 일들이 있었는지 내용들을 정리해서 발표해야겠습니다.

궁금하신 분들은 KSUG는 장소가 협소하니, 다음주 "웹 개발 다반사 행사"에서 뵐 수 있을지도;

ps: 아직 발표 주제로 채택도 안 됐는데 이렇게 써도 될라나.ㅋㅋㅋ
신고

'모하니? > Planning' 카테고리의 다른 글

백기선's 2010 Weekly Report - 2/23  (2) 2010.02.23
목표 실천은 진행 중  (12) 2010.02.17
백기선 2010 목표  (12) 2010.02.15
봄싹 Career Path  (6) 2009.12.17
이번주 토요일 IBM dW "웹 개발 다반사"  (2) 2009.12.03
봄싹을 알리러 갑니다.  (6) 2009.11.24
[Atlassian] 이직 계획  (2) 2009.11.02
[ToDo] 20091016  (0) 2009.10.16
[ToDo] 오늘 할 일 - 할일(예상 소요 시간)(실제 소요 시간)  (4) 2009.10.15
2009년 마무리로 할 일  (4) 2009.10.08
9월에 할 일 정리  (10) 2009.08.31
top


[봄싹 축하] 제 9회 다음 DevDay 대상! (다음 에디터 플러긴 WordAssist)

모하니?/Thinking : 2009.11.16 11:38


다음 에디터 plugin 계발 계획? 생각? 삽질?
다음 에디터 PulgIn !! wordAssist

봄싹에서 같이 스터디 중인 분들 중에 총 세 분이 출전해서, 그 중 두 분이 한 팀으로 만든 다음 에디터 플러그인이 대상을 탔습니다. 상품으로 닌텐도 Wii를 받아왔고, 그것을 현금화 한 금액 중에서 참가 경비를 제외한 거의 전액을 봄싹에 기부했습니다.

저역시 지난번 제주도에서 열린 다음 DebDay에 참석하고 왔었지만, 사실 상에는 관심이 없었고 와이프랑 제주도로 놀러 갈 생각이었기 때문에 이런 성과는 기대도 하지 않았었는데, 이번에 참가한 팀은 아이디어도 멋졌고 그걸 매우 짧은 시간 안에 만들고 그것으로 상까지 받아왔다는 소식에 정말 놀라지 않을 수 없었습니다. 게다가 전액 기부라니 너무 완벽해서 샘이 날 정도입니다.

이번에 입상한 에디터 플러그인은 봄싹에서 별도의 프로젝트로 계속 관리를 해 나갈 것이며, 다음 에디터 및 WordAssist는 봄싹 사이트에 최대한 빨리 적용할 겁니다. (아마도 위키쪽에..)

흑.. 너무 멋지자나. ㅠ.ㅠ
신고
top


[봄싹] 커뮤니티 지원 요청 실패

모하니?/Thinking : 2009.11.09 21:33


D모 업체에 오픈 소스 커뮤니티 호스팅을 지원해주는 서비스가 있길래, 봄싹 커뮤니티를 지원해 주십사 요청을 했었지만, 실패했다. 제한된 리소스로 말미암아 좀 더 대중적으로 영향력 있고 관심가질 만한 커뮤니티를 지원해줘야하는데, 봄싹은 현재 부적절하다고 판단한 듯 하다.

그렇긴 하다. 현재 봄싹 스터디는 이제 막 1년을 넘긴 새싹과도 같은 커뮤니티이고, 그 특성상 유명세나 회원수 부풀리기에는 관심이 없는 커뮤니티이다. 현재로써는 스프링, 하이버네이트, 스프링 웹 플로우, 스프링 시큐리티, Maven, Nexus, Git, SVN, CI 및 개발 환경(Wiki, IntelliJ, Redmine, Github, Atlassian의 모든 제품) 등을 실험적으로 사이트 개발에 적용하고 그 소스 및 과정을 오픈하고 있다는 것 외에는 딱히 이렇다할 오픈 소스 제품이 없는 것도 사실이다.

하지만 미래를 볼 때, 봄싹 스터디는 충분히 지원을 받을 만한 가치가 있는 커뮤니티라고 생각한다. 개발자는 그 어느 직종 보다도 꾸준한 학습이 필요한 직종이 아닌가 생각한다. 그런면에서 봄싹은 1년이 넘도록 꾸준히 스프링을 중심으로 자바 개발에 관한 학습을 했으며, 지금 이 시간에도 계속해서 학습을 하고 있다. 물론 앞으로도 계속해서 학습을 해 나갈 것이다. 그리고 중요한 것은 그 학습한 내용들을 될수 있는한 모두 공개하고 있다는 것이다. 봄싹 스터디에 직접 참여하지 못하는 분들일지라도 온라인을 통해 충분히 학습 내용을 간접경험할 수 있다. 음성 녹화부터 최근에는 캠코더 촬영까지 갖은 방법을 동원하고 있다.

현재 봄싹 사이트는 내가 다니고 있는 회사 서버에 올려져 있다. 봄싹의 새 이슈 트래커(Jira), Nexus, 구 이슈 트래커(Redmine) 등은 봄싹 스터디 회원팀원 중 한명의 개인 컴퓨터를 개발 서버로 세팅해놓고 쓰고 있다. 램이 1G다. JIra가 먹는 메모리만 400M가까이 되서 최근에 자신이 쓰던 컴터의 2G 램을 떼어서 서버에 붙였다. 도메인은 위키북스의 Pro Spring 2.5 책을 베타리딩하고 받은 사례금으로 장만했다. 스터디 장소는 한빛교육센터의 도움으로 간간히 장소비 없이 스터디를 할 수 있게 되었다.

이런 환경에서도 봄싹은 매주 토요일 오전 10시 ~ 오후 1시 꾸준히 활동하고 있다. 매주다. 매주. 한 주는 스프링 스터디를 하고 한 주는 사이트 개발을 하고 있다. 주중에 일하고 주말 중 토요일을 하루 종일 스터디에 투자하는 회원팀원도 있다. 오프라인 모임만 매주 하는 것이지 사실 온라인에서는 매일 개발과 관련된 토론이 오고가며, 개인적으로 사이트 개발을 진행하거나 학습한 것을 공유하고 있다.

나는 절대로 한번도 그렇게 해달라고 요청한 적이 없다. 모두 스스로가 하고 싶어서 자발적으로 참여하는 것이고 그렇게 하지 못한다고 눈총을 주거나 면박을 주지도 않는다. 오히려 그렇게 열심히 학습하고 있는 개발자를 응원하고 그 회원팀원으로부터 자극을 받는 듯 하다. 나는 봄싹 스터디의 운영진 중 한 명으로써 그렇게 열심히 참여하는 사람들에게 좀 더 쾌적한 스터디 환경을 마련해주고 싶다. 그래서 항상 고민한다.

어떻게 하면 돈을 덜 들이고 스터디에 참여할 수 있을까? 어떻게 하면 조용하고 코딩하기 좋은 장소를 얻을 수 없을까? 발표자에게 어떤식으로 보상을 해줘야 할까? 발표자료는 어떻게 보관하고 공유할까? 어떤 형태로 발표를 기록해 주어야 할까? 어떻게 스터디 일정을 알리고 공유할까? 어떻게 하면 스터디 관리를 쉽게 할 수 있을까? 등등의 고민을 항상하고 있고, 그 해결책을 계속해서 구상하고 있다. 여태까지 모색한 방법 중 하나가 바로 봄싹 사이트 개발이고, 또 다른 방법 하나는 이번에 시도했던 커뮤니티 지원을 받는것이다. 그나마 다행으로 봄싹 사이트 개발은 어느 정도 효과를 보고 있는 것 같다. 하지만 그것으로는 부족하다.

봄싹은 분명히 보다 좋은 환경이 필요하다. 봄싹 스터디에 참여하는 개발자들이 편하게 스터디를 할 수 있는 공간이 필요하며, 편하게 필요한 애플리케이션을 돌려볼만한 웹 서버와 호스팅이 필요하다. 환경적인 기회를 강조한 "아웃라이어"라는 책을 봤다면 이해할 수 있을 것이다. 봄싹은 어떻게든 지금처럼 이어나갈 수 있을지도 모르겠다. 그러나 더 좋은 환경에서 자랄 수 있게 도와준다면 봄싹은 더 빨리 더 무성한 꽃을 피울 수 있을 것이다.

뭐.. 어쨋거나 하나가 실패했으니 다른 방법을 더 열심히 잘 준비해야겠다.

출처: http://noandnot.tistory.com/41

봄싹 파이팅!!!
신고
top


개발 관련 Q&A 사이트 StackOverFlow!!

Good Tools : 2009.10.31 23:13


http://stackoverflow.com/

사이트 이름부터가 굉장하지 않은가요. 일반적인 포럼 보다는 훨씬 재미있게 만든 사이트로 위키처럼 질문과 답변을 누구나 수정할 수 있고 밷지과 포임트로 보상을 해줍니다. ㅋㅋㅋ밷지 모으는 재미가 쏠쏠합니다. 질문에 대한 답변 채택과 추천/비추 등의 기능도 해당 질문에 대해 가장 적절한 답변을 바로 찾아 볼 수 있다는 점이 눈에 띄이며, 질문 자체에도 추천과 비추를 할 수 있다는 것이 특히 굳입니다. 사실.. 우문우답이라고, 좋은 질문을 해야 좋은 답변을 들을 수 있는게 당연한 이치죠.


이런식으로 질문에도 추천/비추 기능이 있는데, 저 질문은 3개의 추천을 받았군요.


이건, 제가 작성한 답변은데 4개의 추천을 받았고, 질문 작성자로부터 답변으로 채택을 받았습니다. 그리고 이 답변에 오타가 있어서 Robert가 수정을 해줬고, Jherico가 댓글로 중요한 추가사항을 첨부해 줬습니다.

하지만... 도무지 극복할 수 없는 단점이 하나 있는데..

바로 .. 영어라는 겁니다.

이 좋은 사이트에 한글로 의사표현을 할 수 없다는 것은 정말 괴로운 일입니다.

그래서 봄싹에서는 StackOverFlow를 본따 그와 비스무리 재밌게 만든, NullPE(NullPointerException)를 만들기로 결정했습니다. 다음 릴리즈(11월 30일)에는 포함되어 있지 않지만, 내년 초나 중순 중으로 NullPE를 오픈하겠습니다.

그렇다고해서 별도의 사이트는 아니고, 봄싹 사이트의 일부 모듈로 들어가게 될 겁니다. 지금 있는 사이트에 NullPE 메뉴만 하나 추가가 되겠죠.

흠.. 그러려면 어서 지금 정리중인 스터디쪽부터 마무리를 해야겠습니다. ㄱㄱ

ps: 사실 요즘같아서는 내가 부자여서 돈을 안 벌어도 된다면 직장도 그만두고 봄싹 사이트 개발에만 전념하고 싶습니다.
신고
top


[봄싹] XP 적용 시나리오 3. 개발하기

모하니?/Coding : 2009.10.29 00:57


본격적으로 개발을 해야하는데, 봄싹에서는 오프라인에서 페어로 작업을 해보기도 했지만, 그렇게 자주 충분히 페어 프로그래밍을 했다고 볼 수는 없습니다. 앞으로도 좀 더 꾸준히 시도를 해봐야 그 효용이나 장단점을 파악할 수 있을 것 같습니다. 개인적으로는 뭔가 대화를 나누면서 코딩할 상대가 있어서 안심이 되긴 합니다. DB update 쿼리가 어떻게 되더라? 이거 무슨 리팩토링이지? 이 메서드 이름 맘에 들어? 여기 중복인데 어떻게 제거하면 좋을지 잘 모르겠네.. 같은 식으로 대화를 나눌 수 상대와 함께라면 좋치 않겠어요?


먼저 개발을 진행하기에 앞서 구현하려는 기능을 한 번도 만들어 본적이 없다면, 어느 정도 자신있게 개발을 진행할만큼의 학습이 필요합니다. 그 과정을 파일럿이고 표현했는데, XP 책에서도 파일럿이라고 헀었는지 잘 모르겠습니다. (뭐라고 했는지 찾아보려고 다시 살펴 봤는데 못 찾아서 그냥 썼습니다.)

그다음 과정은 좀 특이하게 바로 개발을 진행하지 않고, 인수 테스트를 만듭니다. 고객이 해당 작업이 완료 됐다는 것을 확인할 수 있는 모종의 장치를 마련하는 것이죠. 고객이 코드를 볼 수 있다면 아주 행복할텐데, 봄싹은 다행히(?) 고객이 전부 개발자 입니다. 굳이 엑셀로 이쁜 포맷을 만들고, 테스트에서 엑셀 로딩해서, 결과를 엑셀에 다시 찍어주고, 고객은 엑셀에서 수식 비교로 해당 테스트가 잘 됐나 안 됐나 확인하는 귀찮은 일은 할 필요가 없습니다. 그렇치만, 인수 테스트 코드가 고객이 원하는 시나리오를 제대로 표현해주지 못하거나, 고객이 개발자인데도 테스트 코드를 읽기가 난해하다면 테스트를 수정해야겠죠.

그다음은 페어 프로그래밍과 TDD로 해당 작업을 구현하는 일입니다. 페어 프로그래밍은 사실 오프라인에서 만났을 때의 얘기지 주중 저녁이나 회사에서 틈틈히 코딩을 하는 봄싹 개발자에데는 다소 난해한 일입니다. 그래도 메신저등을 통해서 의견은 주고 받을 수 있으니 그것도 페어 프로그래밍으로 치도록 하죠.

그렇게헤서 작업이 끝나면, 담당자 두 명은 자신들이 예상했던 난이도와 시간에 비해 실제로는 난이도가 어땠으며 실제로 소요된 시간은 어느정도인지 기록합니다. 고객은 해당 작업 결과를 본 뒤 간략한 피드백을 줍니다. "담부턴 더 빨리 만들어 주세요" 라던지.. "참 잘했어요" 라던지 ㅋ

신고
top


[봄싹] XP 적용 시나리오 2. 배포 계획하기

모하니?/Coding : 2009.10.29 00:43


봄싹이 언제 배포됐었더라... 기억이 가물가물 합니다. 8월 30일이었나. 이제 두 달을 향해가고 있군요. 다음 배포 일정은 임의로 11월 30일로 잡아두었습니다. 세 달은 지나치게 긴 것 같습니다. 이미 봄싹 개발자들끼리는 새로운 UI를 만끽하고 있는데 봄싹 회원들에게 멋진 UI를 빨리 보여드리지 못하는게 아쉽습니다. 배포 일정과 스코프를 잘못 계획했기 때문입니다. UI 개선만을 1차 유지보수 스코프로 정하고 배포했다면 이미 봄싹 회원들은 멋진 UI를 감상하고 계실텐데 말이죠...


먼저 배포 일정을 잡은 다음, 모든 개발자들의 측정이 완료된 스토리 카드 중에서 해당 일정 안에 개발을 할 수 있을 것으로 보이는 스토리 카드들을 고릅니다. 이 일은 전적으로 고객이 합니다. 고객 생각에 어떤 것이 가장 필요하고 비즈니스에 도움이 되는지 생각해서 고르면 되겠죠. 일단 최대한 빨리 중요한 것부터 서비스하고 싶다면 다소 어렵고 일정이 긴 스토리 하나만 고를 수 있겠고, 중요한 건 나중에 공개하고 일단은 기반이 되는 소소한 것들 부터 서비스하고 싶다면, 쉽고, 개발 일정이 짧게 걸릴 것으로 측정된 것들을 고르면 되겠습니다.

그런다음, 하나의 스토리를 구현하는데 필요한 세부 작업들을 개발자들과 논의합니다.

"발표 도메인 객체를 추가해야겠습니다."
"발표와 모임 객체에 연관 관계를 설정해야 겠어요."
"발표에 댓글/첨부자료/발표자 정보가 필요하겠군요."
"새로운 모임을 추가할 때 아예 발표 정보도 추가할 수 있도록 하죠."
"스프링 웹 플로우 학습이 필요할 것 같습니다."
"발표정보 추가할 때 발표자를 선택하는 부분에서는 Ajax를 도입할 수도 있겠네요."
...

이런식으로 하나의 스토리를 구현하는데 필요한 세부적인 작업목록들을 만들어 나갑니다. 이때, 개발자들이 의견을 많이 주어야 하며, 작업 목록 작성은 고객이 담당합니다.

고객이 작업 목록 하나를 작성할 때 마다, 스토리를 등록했을 때 처럼, 평가하는 과정을 거칩니다. 해당 작업은 덩어리가 너무 크다거나, 좀 더 명시적으로 수정해 달라거나 의견을 제시하면서 투표를 할 수 있죠. 혹은 고객이 명시한 작업을 코딩할 수 있겠다는 판단이 들면, 난이도, 걸리는 시간, 같이 작업하고 싶은 사람을 적어서 측정해줍니다.

고객은 가장 낮은 난이도를 제시한 개발자, 가장 낮은 시간을 제시한 개발자, 가장 많은 지명도를 가진 개발자 등의 정보 통계를 보고 해당 작업의 적입자를 찾아서 작업 담당자와 그 파트너를 지정해줍니다. 이렇게해서 하나의 작업에 두 명의 담당자를 지정해 주는겁니다.

그럼 이제 그 두명의 담당자는 서로 의견을 나눠가며 개발을 진행하면 되겠죠!

다음은 개발 과정에 대해 생각해보죠.
신고
top


[봄싹] 모임 추가 시나리오 - web flow (구현)

모하니?/Coding : 2009.10.23 17:57


<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <secured attributes="ROLE_MEMBER" />
   
    <input name="studyId" required="true" type="java.lang.Integer" />
   
    <on-start>
        <evaluate expression="meetingService.createMeeting(studyId)" result="flowScope.meeting" />
    </on-start>
   
    <view-state id="addMeetingForm" model="meeting" view="add.jsp">
        <binder>
            <binding property="openDate" converter="shortDate" required="true" />
            <binding property="closeDate" converter="shortDate" required="true" />
            <binding property="openTime" converter="shortTime" required="true" />
            <binding property="closeTime" converter="shortTime" required="true" />
            <binding property="title" required="true" />
            <binding property="maximum" required="true" />
            <binding property="location" required="true" />
            <binding property="contents" required="true" />
        </binder>
        <transition on="proceed" to="addPresentationForm" />
        <transition on="submit" to="confrimMeetingDetail" />
        <transition on="cancel" to="cancel" bind="false" validate="false" />
    </view-state>
   
    <view-state id="addPresentationForm" model="presentation" view="presentation/add.jsp">
        <binder>
            <binding property="key" required="true" />
            <binding property="title" required="true"/>
            <binding property="topic" required="true"/>
            <binding property="summary" required="true"/>
            <binding property="presenter" converter="memberConverter"/>
        </binder>
        <on-render>
            <evaluate expression="meetingService.createPresentation(meeting)" result="viewScope.presentation"/>
        </on-render>
        <transition on="proceed" to="presentationList" history="discard">
            <evaluate expression="meetingService.addPresentation(meeting, presentation)"/>
        </transition>
        <transition on="cancel" to="cancel" bind="false" validate="false" />
    </view-state>

    <view-state id="presentationList" view="presentation/list.jsp">
        <transition on="delete" to="presentationList">
            <set name="requestScope.presentationKey" value="requestParameters.presentationKey" />
            <evaluate expression="meetingService.deletePresentation(meeting, presentationKey)" />
        </transition>
        <transition on="new" to="addPresentationForm" />
        <transition on="submit" to="confrimMeetingDetail" />
        <transition on="cancel" to="cancel" bind="false" validate="false" />
    </view-state>

    <view-state id="confrimMeetingDetail" view="confirmMeeting.jsp">
        <transition on="submit" to="submit" />
        <transition on="cancel" to="cancel" bind="false" validate="false" />
    </view-state>
   
    <end-state id="meetingEnd" view="externalRedirect:contextRelative:/study/view/${studyId}.do" />
   
    <end-state id="submit" commit="true" parent="#meetingEnd">
        <on-entry>
            <evaluate expression="meetingService.addMeeting(studyId, meeting)"/>       
        </on-entry>
    </end-state>

    <end-state id="cancel" parent="#meetingEnd" />

</flow>

일단, 이 플로우로 진입하면, addMeetingForm 뷰로 이동, 여기서 나온 transition에 따라 contirmMeetingDetail로 바로 가거나, addPresentationForm으로 이동.

addPresentationForm에서 presentationList로 이동하고, 여기서는 back할 수 없도록 history를 discard로 설정함.

대략 80 줄 정도의 XML 설정으로 아침에 구상한 플로우를 구현했습니다. 이 시나리오를 구현하는데 필요한 자바 코드는 서비스 메서드 몇 개 정도. 컨트롤러 코드는 하나도 없습니다. 만약 웹 플로우 없이, 스프링 MVC만을 이용해서 비슷한 플로우를 구현했다면 훨씬 복잡하고 코드도 길었을 텐데 다행입니다. 웹 플로우 사용법도 생각보다 간편하고 쉬웠던 것 같네요.

이제는 웹 플로우 테스트와 <persistent-context />에 대해 좀 알아봐야겠습니다.

신고
top


[봄싹] 모임 추가 시나리오 - web flow

모하니?/Coding : 2009.10.23 11:49


모임을 추가할 때, 해당 모임에 있을 발표에 관한 정보도 추가하도록 웹 플로우를 구상했습니다. 단순 폼 처리보다 훨씬 복잡해질 수 있어서, 스프링 웹 플로우를 도입하기로 했죠. 그런데 막상 기본적인 사용법을 보고나니, 시나리오가 정해지지 않으면 개발을 진행하지 못하겠더군요. 그래서 구상에 들어갔습니다.

모임을 추가하고나서, 발표를 추가해야지.. 발표가 하나만 있는건 아니자나.. 그럼 한 화면에서 여러개를 추가할까?? 에이.. 뭔가 좀 거시기 하네.. 그럼 발표를 하나 추가하고, 발표 목록을 본 다음에 다시 하나 더 추가하고 이렇게 할까?


그래서 그린게 위와 같은 그림입니다. 그런데, 발표자가 확정되지 않았거나, 특정 발표 없이 진행되는 모임이라면 어찌할까? 그때도 무조건 발표 입력 폼을 들려야 하나.. 파란 부분을 서브 플로우로 묶었을 때, MeetingDetial에서 PresentationList로 back 할 수 있을까?  흠 뭐. 일단은 된다는 가정하에.

발표 정보가 한 개 있다면, MF -> PF -> PL -> MD
발표 정보가 두 개 있다면, MF -> PF -> PL -> PF -> PL -> MD
발표 정보가 없다면, MF -> PF -> PL -> MD

이상해.. @_@ 발표정보가 없는데 발표 폼이랑 발표 리스트를 들려야 하다니... 만약에 발표 폼 바인딩에 validation을 해야 하는 상황이면, 발표가 한 개있을 떄랑 발표가 없을 떄를 어떻게 구분한담... @_@ 안돼 안돼..

흠.. 그럼 PresentationList를 먼저 보여주면 어찌 될까나? 그려보지뭐..


발표 정보가 한 개 있다면, MF -> PL -> PF -> PL -> MD
발표 정보가 두 개 있다면, MF -> PL -> PF -> PL -> PF -> PL -> MD
발표 정보가 없다면, MF -> PL -> MD

아... 아닌데, 발표도 없는데 PL을 들릴 필요는 없자나..
그리고 발표를 추가할껀데, PL 부터 들리는 것도 불편하고.
이건 뭐.. 이전 보다 오히려 들려야 하는 폼 수가 늘어났자나.. @_@;;

0. 다시 PF가 진입점이 되도록 수정.
1. MF에서 MD로 바로 갈 수 있는 transition 추가.
2. MD에서 PL로 진입할 수 있는지 확인.(진입할 수 없다면, 서브 플로우 포기)


보자...

발표가 한 개 일 때, MF -> PF -> PL -> MD
발표가 두 개 일 때, MF -> PF -> PL -> PF -> PL -> MD
발표가 없을 때, MF -> MD

오퀘.. 이렇게 가야겠군!!!

신고
top


[봄싹 버그]] JSON 뷰와 하이버가 가져온 Proxy 객체

모하니?/Coding : 2009.10.15 18:27


JSON뷰랑 하이버 Proxy 객체가 만나면 JSON 뷰를 만들다 에러가 납니다.

하이버 객체가 Lazy 로딩을 할 수 없는 지점에서 Proxy 객체를 통해 collection에 접근해서 JSON 뷰로 만들 수 없는 데이터에 접근하여 발생하는 에러로 추측하고 있습니다. 에러가 좀 깔끔하게 떨어지면 해결책이나 원인을 찾기도 쉬울텐데.. 이건 뭐.. StackOverFlow 입니다. Q&A 게시판이 아니라. 정말 그 에러입니다.

이런 일이 발생한 대표적인 시나리오는 현재까지 세 군대 정도 됩니다.
- 로그인
- 출석체크
- 낙서장

이중에서 출석체크와 낙서장은 제가 해결했는데 그 방법이 비슷하지만 살짝 다릅니다.

먼저, 출첵의 경우 proxy객체를 직렬화 하는데, 필요 없는 객체를 JSON 뷰로 넘기고 있었습니다. @SessionAttribute에 등록한 객체들이 Model model 객체에 기본으로 들어가 있었고, 그 객체들(study, member, meeting)을 JSON 뷰로 직렬화 하다가 에러가 났습니다. 그래서 Model model을 깨끗하게 비워버리고 JSON 뷰로 넘겨주도록 헬퍼를 만들어 사용했습니다.

    @RequestMapping("/study/{studyId}/meeting/{meetingId}/confirm/{attendanceId}")
    public ModelAndView confirmMember(Model model, @PathVariable int studyId,
            @PathVariable int meetingId, @PathVariable int attendanceId,
            HttpSession session) {
        service.confirmAttendanceById(attendanceId);
        return JsonHelper.jsonViewWithCleanMap(model);
    }

두 번째 낙서장은 제가 맡은 부분은 아닌데, 계속 눈에 걸려서... 암튼 보니까 필요한건 Grafitty의 comments 뿐인데, Graffiy의 작성자(Member)를 포함한 모든 속성들을 다 가져오더군요. 그래서 JSON 뷰에서는 또 타고 타고 들어가다가 접근 못하는 부분(아마도 Member가 들고 있는 Set<Role> 타입의 프로퍼티)에서 JSON 뷰를 만들다 직렬화 에러를 냈을 겁니다. 이번에는 DAO에서 하이버네이트의 Projection을 이용해서 필요한 것만 가져오도록 쿼리를 수정해서 처리했습니다.

    @SuppressWarnings("unchecked")
    public List<Graffiti> getByWriteDate(Date writeDate) throws DataAccessException {
        Criteria c = getCurrentSession().createCriteria(Graffiti.class)
            .add(Expression.ge("writeDate", writeDate))
            .addOrder(Order.asc("writeDate"))
            .setProjection(Property.forName("contents"));
        return c.list();
    }

    @SuppressWarnings("unchecked")
    public List<Graffiti> getRecent10Contents() {
        Criteria c = getCurrentSession().createCriteria(Graffiti.class)
            .setMaxResults(10)
            .addOrder(Order.asc("writeDate"))
            .setProjection(Property.forName("contents"));
        return c.list();
    }

이 방법들은 완전한 대책이 아니라, 적당히 필요한 데이터만 간추리다보니 해결이 된겁니다. 땜빵이라고 하기도 좀 뭐하지만.. 해결책이라고 하기도 좀 뭐하지요.

좀 더 궁극적인 해결책을 생각해 봤는데;;

OSIV Fileter가 MappingJacksonJsonView와 뭔가 잘 안 맞는것 같습니다. JSON이 빌드할 때도 트랜잭션 경계 안에 들어있는 상태라면 하이버 프록시 객체에서 타고 타고 타고 들어갈 수 있는건데... 그게 안 되서 에러가 나는 거겠죠?? 결국은 AOP로 MappingJacksonJsonView의 특정 메서드를 실행하기 전에 트랜잭션을 열고.. 작업을 끝낸다음 트랜잭션을 닫는 작업을 해줘야 하는거 아닌지.. 고민입니다.

아이고;; 번역 헀어야 하는데.. 봄싹에 손을 대버리다니... 큰일이네... 큰일이야.. 에휴... 봄싹 중독인가. @_@

신고
top


[제이쿼리] 마우스 오버/아웃 이벤트 사용하기

모하니?/Coding : 2009.10.12 20:59


출석체크를 할 때, 체크 모양의 버튼을 누르면 결석이 되고.. 결석 버튼을 누르면 출석이 되는 형태의... 비 직관적인 뷰를 만들었었습니다.

버튼을 두 개 만들기 귀찮아서 버튼 하나를 두고 On/Off 버튼 식으로 만들었는데, 현재 상태를 체크 모양 자체가 현재 상태를 나타내고, 그것을 한 번 누르면 결석으로 바뀌게 한 것이죠.

만든 저야.. 로직까지 포함해서 잘 이해가 되지만, 첨보는 팀원은 굉장히 햇갈려 하더군요. 이해합니다. 곰곰히 생각하다가 어제 맥북으로 사진 정리하다가 iPhoto에서 얼국 인식을 하는데, 내 얼굴인지 아닌지 확인할 때의 UI가 떠올랐습니다. 딱.. 그 UI가 출석체크와 비슷한 로직이었습니다.

다른 것은 하나.. 마우스가 올라갈 때, 해당 버튼이 어떤 이벤트를 할 지 알려준다는 것입니다.

"본인이면 클릭하세요." 에서 마우스를 클릭하면 "백기선님으로 확인되었습니다."로 바뀌고 거기서 마우스가 올라가면 "백기선님이 아닙니까?"로 바뀌죠. 그걸 또 다시 클릭하면, "백기선님이 아닙니다."로 바뀝니다.

오호.. mouse over 이벤트만 사용하면 되겠군...  생각하고 적용해봤습니다.

    $(".btn_attend_member").mouseover(function(){
        $(this).attr("src", "<c:url value='/images/remove-16x16.png'/>");
    }).mouseout(function(){
        $(this).attr("src", "<c:url value='/images/accept-16x16.png'/>");
    });

    $(".btn_absend_member").mouseover(function(){
        $(this).attr("src", "<c:url value='/images/accept-16x16.png'/>");
    }).mouseout(function(){
        $(this).attr("src", "<c:url value='/images/remove-16x16.png'/>");
    });

버튼이 아니라;; 이미지를 사용하고 있어서 좀.. 그렇긴 하지만 그건 나중에 바꾸기로 하고.. 일단 저렇게 이벤트를 등록해놓고 마우스를 올렸다 내렸다 해봤더니.. 잘 되는겁니다. ㅋㅋㅋ 그때까진 좋았죠.

하지만...

Ajax 요청을 보내고 나서 결석 상태를 출석으로 바꾸고 났을 때, 출석 상태인데도 마치 결석 상태처럼 마우스가 밖에 있으면 결석(현재 상태), 마우스가 이미지로 올라가면(다음 이벤트) 출석 상태를 보여주는 겁니다. @_@

문제 원인은 페이지 로딩시에 저 이벤트를 한 번 등록해두면 설령 Ajax 요청 처리에서 css를 바꾼다 하더라도 저 이벤트들을 다시 등록하진 않기 때문입니다.(좀 더럽지만... 화장실에서 볼 일 보며 곰곰히 생각해보니.. 왜 그런지 알겠더군요.)

그래서..

var changeImageSrcWhenMouseOverOut = function () {
    $(".btn_attend_member").mouseover(function(){
        $(this).attr("src", "<c:url value='/images/remove-16x16.png'/>");
    }).mouseout(function(){
        $(this).attr("src", "<c:url value='/images/accept-16x16.png'/>");
    });

    $(".btn_absend_member").mouseover(function(){
        $(this).attr("src", "<c:url value='/images/accept-16x16.png'/>");
    }).mouseout(function(){
        $(this).attr("src", "<c:url value='/images/remove-16x16.png'/>");
    });
};

이렇게 함수를 하나 만들고, 이 녀석을 페이지 로딩 할 때 한 번, Ajax 요청을 처리한 뒤 한 번 호출 하도록 코딩했더니.. 원하던데로 동작하게 되었습니다. 음하핫;;

안타깝지만, 관리자만 할 수 있는 기능이라 여러분을 볼 수가 없겠군요... @_@
신고
top


[봄싹] 새 기능 소개

모하니?/Coding : 2009.09.29 18:41


1. 트위터 서비스!

http://twitter.com/springsprout

봄싹 트위터를 통해서 스터디와 모임 개설/변경 소식을 실시간으로 전해드립니다. 트위터 RSS를 구족하시면 RSS 리더기를 통해서도 스터디와 모임 정보를 쉽게 받아 보실 수 있겠죠.

2. 구글 토크 알리미!

s2cmailer@gmail.com

이 주소를 구글토크에 친구로 추가해두고, 구글 토크에서 사용하는 이메일로 봄싹에 가입했다면,
스터디와 모임 메시지를 바로 바로 받을 수 있습니다.

그것 뿐 아니라, 대화형 기능을 제공하여 study? 라고 입력하면 현재 운영중인 스터디 목록을 보여주고, meeting? 이라고 입력하면 현재 개설되어 있는 모임 목록을 보여줍니다.


3. 통계 기능 추가!

스터디에 얼마나 열성적으로 참석하는지..
스터디 별로 참석률은 어떤지..
모임 참가 신청을 하고나서 자주 불참하는 회원은 아닌지..
스터디 별로 신청을 해놓고 얼마나 약속을 잘 지키는지..

한눈에 알 수 있는 기능을 추가했습니다. (테스트 데이터가 엉망이라 통계가 좀 이상합니다.)


나중에는 참석률과 신뢰도를 게이지 형태로 디자인해서 마치.. 게임 캐릭터의 체력과 마력을 나타내듯이 표시할 생각입니다. ㅋㅋ

셋 다 제가 코딩했고 만들면서 많이 고민하고 재미를 느꼈던 기능들입니다.

- 트위터 알리미를 만들 때는 인터페이스 사용의 혜택을 만끽해 보았으며,

- 구글 토크 서비스를 만들 때는 smack API를 이용하는 JabberService를 만들면서 스프링 DI를 어떻게 하면 잘 활용할 수 있을까 고민할 수 있는 계기가 되었습니다.

- 마지막으로 통계 기능을 만들 때는 별로 안 해봤엇던 하이버네이트에 Map<Entity, Primitive Type> 형태의 맵핑도 해보고, 어떤 콜렉션 타입이 좋을지 고민도 해보고, EL로 map안에 있는 데이터 꺼내오기도 해봤네요. 하지만 뭐니뭐니해도 테스트를 통해서 얻을 수 있는 안정감.. 그걸 느껴볼 수 있었습니다.

현재 봄싹은 제가 만든 새로운 기능 말고도 다른 분들이 만들고 있는 새 기능도 많이 있습니다. 본격적인 운영은 추석이 지나고나서 될 것 같네요. 그전까지 지금 상태 그대로 갑니다.

모두 명절 잘 보내세요~
신고
top


[봄싹] 매주 토요일




이러고 지낸답니다. 스터디도 하고 개발도 하다보면 주말이 정말 금방 끝나버립니다. 주 6일 근무 하는 것과 비슷한 기분이지요. 그래도 즐겁답니다. 매번 새로 오시는 분들과 매주 조금씩 발전하는 봄싹 사이트를 보면 정말 뿌듯합니다.

매주 스터디에 나가도 불평 한마디 없이 오히려 배려해주고 신경써주는 와이프와
봄싹에 참여하여 자신의 생각과 코드를 공유해주시는 분들이 있어서 정말 즐겁습니다.

모두 즐거운 한 주 되시고 토요일에 또 뵈요.ㅋ


신고
top


[봄싹] 스프링 레퍼런스 3.0 번역 시작



http://springsprout.org/wiki/464.do

3.0 레퍼런스 번역을 꾸준히 하겠습니다. 그동안 블로그에 조금씩 번역해서 올려두기도 했었는데 아무래도 레퍼런스 글은 블로그에서 찾아보는게 불편해서 봄싹 위키에 정리하기로 했습니다.

일단은 저 혼자 시작합니다. 하지만 봄싹 회원이라면 누구나 위키 페이지를 추가/수정/이동 시킬 수 있기 때문에 자유롭게 참여하실 수 있습니다.

정해진 틀도 없고 파트를 나누지도 않았지만, 봄싹 사이트도 처음에는 이런 방법으로 개발을 시작했습니다. 지금은 제법 틀도 갖춰져 있고, 특정 모듈 또는 기능 담당자(? 라기 보단 스스로 책임을 느끼시는 분들)도 있습니다. 수직 구조로 누가 누구에게 지시하거나 일을 나눠주지 않고 수평구조로 서로 토론하며 자신이 만들고 싶은 기능을 마음대로 구현해 넣고 있습니다. 레퍼런스도 이런 방법으로 번역을 완성할 겁니다.

기여(?).. 흠. 참여하고 싶으신 분들은 언제나 대환영입니다.

파이팅!

ps: 위키 수정/추가시 포인트를 계산해서 위키 기여도를 측정해야겠군요. 가장 많이 기여한 분에게 봄싹 티셔츠라도...

ps: 위키 미리 보기 화면과 실제 화면이 좀 다른데;; 아마도 조만간 소내기형이 수정해주지 않을까 싶네요... 형 수정해주세요.. ㅠ.ㅠ


신고
top


[봄싹] 간단하지 않은 회원 관리

모하니?/Coding : 2009.08.11 12:37


봄싹 시즌 2 개발 중에 자연스래 담당하는 모듈이 나뉘어져서 요즘은 주로 회원 관리 모듈만 개발하고 있습니다. 처음엔 뭐 간단하겠지.. 별거 있나.. CRUD만 하면 되겠지.. 라고 생각했었는데 그게 아니더군요.

일단 회원 관리와 더불어 인증/권한까지 같이 담당하게 되었는데, 사용자가 회원 가입과 로그인을 하고 그 사용자에게 권한을 부여하는 관리자 기능까지 생각해보면 할 일이 심심치는 않았습니다.

1. 회원 가입

로그인과 더불어 사용자가 가장 빨리 접하는 기능 중 하나 일 겁니다. 그래서 디자인에도 조금 신경을 써야했습니다. 그리고 스팸 사용자도 막고 싶었습니다. 캡차를 쓸 수도 있겠지만, 이메일 인증 방법을 사용하기로 결정했습니다. 회원 가입을 서브밋 하면 인증 메일을 전송하고, 사용자가 인증 메일의 링크를 클릭하면 사용자 상태를 인증 된 상태로 바꿔주는 겁니다. 그 전에는 로그인이 되지 않습니다.

검증은 2단계로 화면단에서 한 번, 서버 단에서 한 번 그렇게 두 번 걸러집니다. 이때, 클라이언트 쪽 검증은 제이쿼리의 validation 플러긴을 사용했으며, 중요한 검증 작업 중 하나로 email 중복 체크가 있습니다. 이 부분이 제대로 동작하지 않더라도 최종적으로는 DB단에서 unique 제약 위반으로 에러가 나고 해당 회원 정보는 추가되지 않을 겁니다. 하지만, 그 에러 메시지를 만나게 하기 전에 사용자가 email만 입력한 상태에서 검증을 해주고 싶습니다. Ajax가 필요한 시점입니다. 하지만 요청을 너무 자주 보내고 싶진 않기 때문에, 기본적인 email 형태를 갖췄는지 validation을 한 뒤에 해당 검증을 잘 통과 했을 경우에만 ajax로 요청을 보내서 중복 된 email이 아닌지 확인해 줍니다.

이렇게 화면단/서버단 검증이 잘 끝나서 회원 가입을 진행하게 되면 이메일을 전송하느라 3~5초 정도 시간이 걸리는데 이 시간 동안 사용자에게 뭔가 진행중이라는 사실을 알려주고 화면을 블러킹해줍니다. 이 때 아이튠즈의 블러킹 화면과 비슷한 화면을 보여주도록 했습니다.ㅋㅋ 단, IE에서는 모서리가 각져서 보인다는 거... FF나 Safari에서는 잘 보였습니다.

회원 가입 폼 처리가 끝난 뒤, 회원 가입 인증 대기 화면을 보여줍니다.

2. 가입 승인 대기

회원 가입 인증 메일을 전송했기 때문에, 이제 사용자는 해당 메일을 확인하고 그 메일에 들어있는 링크를 클릭하여 회원 가입 인증을 거칠 수 있습니다.

하지만 만약 사용자가 메일을 한 번 받아놓고 다른 일을 하다가 메일이 쌓여서 봄싹이 보낸 메일이 어딨는지 못 찾았다면? 혹은 메일을 실수로 지웠다면? 해당 사용자는 답답해 할 겁니다. 그래서 인증 메일 재전송 기능이 필요했습니다.

또한 현재 페이지에서 회원이 사용중인 메일 서비스로 바로 이동할 수 있는 링크도 유용할 겁니다.

마지막으로 승인을 받은 사용자에게 기본 권한을 설정해줍니다. 기본으로 모든 사용자는 USER라는 role을 가지도록 구현해 줬습니다. 그래야 익명 사용자와 가입한 사용자를 구분할 수 있을테니 말이죠.

스팸 사용자가 발생할 수 있습니다. 인증을 거치지 않고 계속 가입만 한 사용자들이 DB에 쌓일 수 있죠. 그럴 경우에 대비해서 주기적으로 배치를 실행해서 인증을 거치지 않은 사용자 정보를 삭제해 줍니다.

2. 로그인

여차 저차해서 회원 가입 인증까지 끝낸 사용자는 로그인 화면을 보게 될 겁니다. 회원 가입 인증 메일에 들어있던 링크가 로그인 화면으로 보내주면서 내부에서는 인증 작업을 해주는 것이죠.

이제부터는 스프링 시큐리티와 관련이 있는데, 그다지 어렵진 않았습니다. 스프링 시큐리티를 공부하는게 아니라 그냥 간략하게 사용만 하는 것이니까요. 그다지 어려울 것은 없습니다. 인증 방법은 여러가지가 있는데 일단은 가장 흔한 폼 인증 방식을 선택했습니다. 다음에는 OpenID로 지원해볼 생각이지만, 당장은 아닙니다.

아직 가입을 하지 않은 사용자가 로그인 화면에 들어온 경우가 있을 수 있기 때문에 회원 가입 화면으로 가능 링크가 필요합니다.

또한 가입은 했지만 아직 인증을 거치지 않은 사용자가 있을 수 있는데, 그런 경우 가입 승인 대기 화면으로 포워딩을 하고, 이메일 인증을 받도록 합니다.

비밀 번호를 잊어버렸을 수도 있는데, 이런 경우 가입시 입력한 이메일을 다시 입력받아서 해당 이메일로 비밀번호를 전송해 줍니다. 이 떄 입력하는 이메일도 검증 작업이 필요하겠죠.

3. 관리자

다행히(?) 이 부분은 제 담당이 아닙니다. 성윤군이 담당하고 있는데 제이쿼리를 이용해서 드래그앤드랍으로 권한을 변경할 수 있게 해준다니.. 기대중입니다.

회원 전체 목록 조회.

회원 정보/권한 조회.

회원 정보/권한 변경.

회원 삭제.

모든 목록을 뽑아낸 것이 아니라, 지금까지 완료한 작업이나 오늘 내일 처리할 작업까지만 정리한 것입니다. 아마도 생각하지 못한 작업들이 더 있겠지요. 간단해 보였던 회원 관리가 이렇게도 할 일이 많았다니.. 다른 모듈들은 어떨지 걱정입니다. 이번 주 내로 회원 관리를 정리하고 일손이 모자른 스터디 모듈이나 관리자 모듈쪽에 붙어야겠습니다. 그쪽도 아주 재밌을텐데 말이죠.
신고
top


[하이버네이트] 애매한 에러 메시지 때문에 삽질.. @_@

Hibernate/etc : 2009.08.07 21:50


DEBUG - OpenSessionInViewFilter.doFilterInternal(207) | Closing single Hibernate Session in OpenSessionInViewFilter
DEBUG - SessionFactoryUtils.closeSession(784) | Closing Hibernate Session
2009. 8. 7 오후 9:30:52 org.apache.catalina.core.StandardWrapperValve invoke
심각: Servlet.service() for servlet springsprout threw exception
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: springsprout.domain.Member.studies, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    at org.hibernate.collection.PersistentSet.add(PersistentSet.java:189)
    at springsprout.domain.Member.addManegedStudy(Member.java:154)
    at springsprout.modules.study.StudyService.add(StudyService.java:24)
    at springsprout.modules.study.StudyService$$FastClassByCGLIB$$6d06dbc0.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
...

에러의 원인이 무엇일까? 에러 로그에서 가장 중요한 부분이라고 생각하는 부분을 진하게 표시했다. 제 1의 단서는 에러 메시지이고, 제 2의 단서는 에러가 발생한 지점 중 내가 코딩을 한 부분이다. 스프링, 하이버는 많은 유저와 테스트 그리고 지속적인 관리를 통해 내가 작성한 코드보다 더 신빙성이 높기 때문이다.

어쨋든.. 생각해보자. 에러 메시지가 뭐라고 하는가?? 세션이 없다고?? 왜??? 난 분명 @Transactional을 사용했다. 트랜잭션이 없을리 없는데.. 왜 그럴까.. 이해가 되지 않는다. 세션이 닫혔다고?? 왜??? 이해가 되지 않는다. 이런 일이 발생한 적은 없었다.

혹시나해서 DEBUG 모드로 스프링 로그를 찍어보았다. 해당 에러가 나기 직전에 이러한 로그를 볼 수 있다.

DEBUG - HibernateTransactionManager.doBegin(504) | Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@7650bc]
DEBUG - HibernateTransactionManager.doBegin(569) | Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection@a681c3]
DEBUG - HibernateTransactionManager.doGetTransaction(437) | Found thread-bound Session [org.hibernate.impl.SessionImpl@7650bc] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(468) | Participating in existing transaction

분명 Session을 잘 가져왔고, 세션이 닫힌다는 얘기도 없다. 이 바로 다음에 에러가 발생한다. 막막하군.. 그럼 이제 내가 작성한 코드를 살펴보자.

    public void add(Study study) {
        Member currentMember = securityService.getCurrentMember();
        currentMember.addManegedStudy(study);
        repository.add(study);
    }

    public void addManegedStudy(Study study) {
        getStudies().add(study);
        study.addMember(this);
        getManagedStudies().add(study);
        study.setManager(this);
    }

빨간색으로 표시한 부분이 에러가 발생하는 지점이고 최종적으로 getStudies()를 호출할 때 발생한다. 모르겠다. 무엇이 문제일까?

테스트를 만들어보자.

    @Test
    public void add() throws Exception {
        Study study = new Study();
        Member member = new Member();
        memberService.addWithoutConfirm(member);
       
        service.add(study, member);

        assertEquals(member, study.getManager());
        assertTrue(study.getMembers().contains(member));
    }

스프링 통합 테스트를 만들어서 테스트해보았다. 이 테스트는 잘 돌아간다. 더 미궁속으로 빠져든다. 그런데, 테스트와 실제 코드가 같지 않다. 테스트를 편하게 하기 위해 조금 다른 코드를 이용했다. 둘의 차이는 무엇일까?

테스트에서의 member 객체 상태는 Persistent다. 그러나... 실제 코드에서 member 객체 상태는 어떨까? 아차차.. 이런.. 문제의 실마리가 보이는 듯 하다.

그렇다. 실제 코드에서 currentMember 객체는 detached 상태인 것이다. 아.. 이런.. 단서에 너무 의존하다가 눈앞에 있는 객체 상태를 보지 못했다. 나의 실수다. 하이버네이트를 다룰 때 가장 중요한 것 중 하나가 바로 객체의 상태인데. 그것을 못 보다니 한심하다는 생각이 밀려온다. 이미 지난 일이다. 어쩔 수 없다. 다음번엔 잘 찾아내야지.

단 하나.. 바라는게 있다면, 세션이 없다는 얼토당토 않은 에러 메시지 말고, detached 객체에서 lazy loading이 발생한다고 메시지를 출력해주면 좋겠다. 그랬다면... 좀 더 쉽게 해결할 수 있었을 법한 문제였다.
신고
top


[봄싹]기트 도입 실패 사례

모하니?/Coding : 2009.08.06 18:59


봄싹 스터디에서 Git라는 분산 VCS를 사용해 보기로 결정하고, 사전 조사를 거친다음, 간단한 사용법을 공유하고, 개발을 시작했다. 그러나 개발은 더뎠다. 얼마전 더디다 못해 거의 진척이 없다시피 하는 모습을 보고 Git에서 SVN으로 버전 관리 시스템을 바꿨다. 그리고 프로젝트의 데드라인도 설정했다. 그러자... 이게 왠일인가..


불과 2주 만에 총 9명의 개발자가 온/오프라인에서 뜨겁게 개발에 참여하고 있다. 현재 이 모습은 내가 봄싹 구글 그룹스를 처음 만들 때 상상하던 모습이다. 이대로만 간다면, 8월 29일 데드라인 안에 사이트 1차 개발을 마칠 수 있을 것 같다.

바뀐 요인은 딱 두 가지. 1. 데드라인 설정. 2. 개발자에게 보다 편리한 개발 환경으로 전환. 어쩌면 2번은 1번으로 인해 불가피 했을지도 모르겠다. 처음에는 느긋하게 기트에 적응해가자면서 개발을 하자고 생각했었다. 하지만 그것은 오산이었다.

기트를 사용하고 있지만, 기트를 사용하는 시나리오는 예전 SVN을 사용하던 때와 별반 다르지 않았다. 수시로 branching/merging을 하지 않을 꺼라면 굳이 Git를 사용할 필요가 없다는 것을 몸소 체험했으며, 중간 관리자를 거쳐야만 하는 대규모 개발도 아니기 때문에 한방에 서버로 바로 커밋/업데이트하는 SVN이 그립기도 했다. 또한 이클립스 툴 지원이 아직도 미약했다. 마지막으로 별도의 기트 서버를 운영하지 않고 GitHub를 이용했는데, 나중에는 사용자가 많아져서 계정 관리하는 것이 어려웠다. 이 부분은 아마도 봄싹에서 GitHub를 잘못이용한 것이 아닌가 하는 생각이 든다. 애초에 내 계정에 다른 개발자들의 공개키를 등록하는것이 아니라, 프로젝트에서 별도의 브랜치를 따다가 자기 계정에서 관리하는 형태로 프로젝트를 진행했어야 하는 듯 하다.


그래서 모두에게 익숙한 SVN으로 넘어왔다. 결국은 기트 도입이 실패했지만, 프로젝트는 실패하지 않았다. 어쩌면 그로인해 프로젝트 성공의 길로 한 걸음 더 다가간 것 같이 느껴진다. 비록 이번에는 기트 도입이 실패했지만, 다음에 적절한 상황이 오면 다시 시도해 볼 생각이다. 다음에는 기트허브에서 새로운 방식으로 개발을 진행하던지, 별도의 기트 서버 환경을 구축한 뒤에 해볼 생각이다. 그때가 되면 이클립스 툴도 조금은 진전이 있겠지...??

ps: 예상외로 메이븐 도입에 대해서는 다들 잘 수긍하는 편이었다. 처음부터 메이븐 리파지토리, 플러긴, 페이스, 골 등의 개념 설명을 한 적이 없고, 필요한 명령어만 몇개 알려드리고, pom.xml에 의존성 추가하는 것만 알려드렸다. 기트가 워낙 충격적이어서 그랬나...? 아무튼 메이븐은 기트에 비하면 도입이 쉬운편이었다. 봄싹에선 말이다.



신고
top


게시판에서 글 검색 기능은 어떻게 만들까?



이번주 봄싹 스터디에서는 검색 기능을 구현해 가려고 합니다. 원랜 페이징까지 구현해 가려고 했는데 요즘 번역이 좀 밀려서 번역에 에너지를 쏟았더니 눈이 아파서 코딩을 못하겠네요.

어쩃든, 검색 기능을 어떻게 구현할지 생각해 봤습니다. 제가 주로 이용하던 검색은 구글이나 네이버 같이 어떤 글을 검색할 땐 키워드 하나면 충분합니다. 그 키워드가 어떤 글의 내용이 될 수도 있고 작성자나 글 제목이 될 수도 있겠죠. 그래서 좀 더 세분화 하기 위해서 어떤 필드(제목, 내용, 글쓴이)를 검색할 키워드로 사용할 것인지를 선택할 수 있도록 기능을 제공해야겠다는 생각이 들었습니다.

다음은 글을 쓴 날짜가 관건인데 이 부분은 고민이 좀 됐습니다. 날짜를 두 개씩 받아서 Between으로 검색을 하자니 매번 날짜 입력하기도 참 불편하고 그렇다고 날짜가 없으면 가져오는 데이터가 너무 많고 그래서 샤워하다가 생각난 것이 은행 사이트의 거래 내역 조회입니다. 은행 사이트에서 거래 내역 조회할 때 보통 기본값으로 1주일이나 한 달치가 검색이 되고 어떤 사이트는 최대 Between을 세 달로 제한해서 검색 대상이 되는 데이터의 범위를 줄여놨습니다. 이걸 게시판에 응용해볼 생각입니다.

검색 조건 파라미터를 나타내는 클래스의 필드는 총 다섯개 입니다.

String keyword
Stringp[] filedNames
Date baseDate
DateSearchingTerm dateSearchingTerm
DateSearchingType dateSearchingType

필드 이름은 String 타입의 속성 이름 배열이 되고 그 중에서 keyword를 가진 녀석들을 검색할 겁니다. 그리고 날짜는 baseDate를 기준으로 type에 따라 하향(from), 상향(to), 중심(around)으로 term 만큼 검색을 할 겁니다. UI 기술이 좀 받쳐주면 아주 잼난 UI를 만들 수 있겠는데 일단은 단순 입력으로 가야겠죠. 전 UI에 약합니다. ㅠ.ㅠ

여기서 재밌는게 DateSearchingTerm 이랑 DateSearchingType 인데, 이 녀석들은 enum으로 만들 겁니다. enum으로 선택지를 만들어 두고 enum이 제공하는 name()과 values() 메소드를 이용해서 화면에 뿌릴 이름을 toString()을 재정의 해서 보여줄 것이고 선택지 컬렉션을 화면에 전달할 겁니다. 이 녀석들은 기본 타입이 아니라 스프링이 어떻게 바인딩 해야 하는지 당연히 모르겠죠. Date도 마찬가지 입니다. 그래서 커스텀 에디터를 만들어서 등록해주고, 차후에는 Date 검색 부분만 따로 분리해서 다른 도메인의 검색 파라미터에서도 재사용하기 쉽도록 해야겠습니다.

오늘은 맥주를 마셨으니 코딩은 내일로 미루고 오늘은 피아노나 조금 치다가 자야겠습니다. Good Night~
신고
top







티스토리 툴바