[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

2016년 6월 30일 목요일

[Book] HTML & CSS..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

HTML & CSS - 8점
존 두켓 지음
홍영표 옮김
에이콘출판

한 참동안 프론트앤드쪽에 신경을 많이 못쓰고 있었고 HTML5가 나오면서 추적할게 너무 많아져서 그동안 좀 방치하고 있었기 때문에 다시 정리하는 차원에서 선택한 책이다. 아마존에서 1위를 차지하고 있다는 말에도 약간 끌리기도 했고... 일단 HTML이나 CSS에 대해서 기본적인 내용들은 알고 있기 때문에 배경지식이 전혀 없는 사람을 대상으로 한 것으로 보이는 이 책은 나에게는 좀 쉬운 편이었고 그래서 상당히 빠르게 읽었다.

말했듯이 이 책은 HTML이나 CSS 혹은 웹에 대한 지식이 전혀 없는 사람을 대상으로 한 책이기 때문에 고급 테크닉에 대한 설명은 많이 없고 기본적인 내용에 충실하다. 그래서 실무에서 HTML이나 CSS를 활용해야 하는 사람이 보았을때는 기본기는 다질 수 있지만(항상 중요!) 그 이상을 하려면 다른 책이나 문서를 참고해 보아야 할 것같다. 하지만 기존의 좀 딱딱하게 느껴지는 HTML에 비해서 흡사 디자인책인가 싶은 느낌이 들 정도로 설명과 코드와 결과화면이 잘 구성되어 있다. 구구절절 설명이 많지도 않으면서 핵심을 잘 설명하고 있기 때문에 HTML을 새로 배워보려고 하거나 개발자가 아닌 기획자나 디자이너가 HTML에 대한 지식을 쌓을때는 상당히 도움이 되지 싶다. 특히 책이 나온 시기상 HTML, CSS 설명가운데 적절하게 HTML5나 CSS3외에도 구 브라우저 호환성 문제에 대한 언급들이 적재적소에 들어가 있어서 가벼운 마음으로 HTML+CSS의 기본을 정리하는데 도움이 된다. 레퍼런스 식으로 설명할 수 밖에 없는 HTML과 CSS를 지루하지 않게 설명한다는 점이 이 책의 가장 큰 장점인듯 하다.

초반에는 HTML을 설명하고 뒤에서 CSS를 설명한다. HTML이 어떻게 구조적으로 마크업을 구성하고 각 태그들을 어떤 용도로 써야 하는지에 대해서 설명한 뒤에 각 태그 들을 CSS로 꾸미는 방법을 설명하고 있기 때문에 구성은 괜찮은 편이라고 생각한다. HTML이 용도별로 잘 구분되어 있고 브라우저 호환이나 신경써야 할 부분, 과거에 잘못사용하던 사례들도 중간중간 어느정도 설명이 되어 있다. 


My Comment..
HTML 과 CSS 는 웹 개발자라고 한다면 자연스럽게 접하고 당연히 알아야 되는 부분이긴 하다.. 나도 과거에는 상당히 많이 접했다고 해야되나.. 음.. 많이 접한편이다.. 그런데 지금은 퍼블리셔와 개발자 그리고 DBA 가 명확하게 나뉘어진 상황에서 근무를 하다보니..

아무래도 조금은 등안시하는게 사실이긴 하다.. 그래도 햄은 보면 항상 책을 통해서라도 끈을 놓지 않고 있는거보면 신기하기도 하다.. ㅎㅎㅎ..

[Talk] Aaron Swartz, Rest In Peace..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

지난 11일[2013년의 일] Aaron Swartz라는 개발자가 자살로 죽음을 선택했다. 사실 그 이전까지는 Aaron Swartz에 대해서 아는 바가 없었지만 그의 삶이나 죽음까지의 과정을 알게되었을 때 개발자로써 추모글을 남겨야겠다는 생각이 들었다. 그의 죽음이 안타깝기도 하고 개발자로써 Jobs의 죽음에 대해서도 추모글을 남겼었는데 Aaron은 그냥 넘어기에는 뭔가 부끄러웠고 또 원래 잘 알고 있던 사람이 아니었기 때문에 시간이 지나면 그냥 잊어버릴것 같았다.

일단 Aaron이 한 일들을 보자.

  • RSS-DEV 워킹그룹에서 RSS 1.0 스펙을 공동 작성함.
    Reddit의 공동창업자로 Reddit의 전신인 Infogami를 창업함.
  • Markdown 설계에 참여함.
  • MIT에서 Tim Berners-Lee와 RDF 코어 개발에 참여함.
  • Creative Commons의 창업자 Lawrence Lessig가 Creative Commons를 만드는데 기여함.
  • SOPA를 반대하는 캠페인으로 알려진 온라인그룹 Demand Progress를 만듦
대표적인 것들만 봐도 이정도 들이고 RSS나 마크다운이나 Creative Commons 모두 지금 내가 잘 쓰고 있는 것들이라서 몰랐음에도 그가 나한테 얼마나 많은 영향을 끼쳤는지 알수 있다. Aaron이 RSS 스펙에 참여했을 때가 14세였다고 한다. 이렇게 뛰어난 개발자가 26세라는 나이에 죽음을 선택했다는 것은 정말 안타까운 일이다. 그가 살아있었다면 세상에 좋은 영향을 얼마나 많이 끼쳤을까....

그의 죽음이 안타까운 이유는 그의 죽음이 제도적 타살에 가깝다는데 있는데 블로터닷넷의 아론 슈와츠의 죽음을 슬퍼해야 하는 까닭라는 글에 그 내용이 정리되어 있다. The Tech에 JSTOR의 사건이 정리되어 있긴 한데 법정용어가 많아서 자세히는 모르겠고 2010년 Aaron이 JSTOR에서 다운로드를 시작하고 JSTOR 측에서 막았지만 누차 시도해서 다운받아간다. 이에 대해서 불법 네트워크 침입 및 480만건의 문서 불법 다운로드로 계속해서 기소를 당하게 되고 여기에 1년여를 버티다가 죽음을 선택하게 된다. 물론 Aaron의 행동이 법적인 문제의 소지가 있는 것은 확실하지만 35년형을 받을만할 정도인지는 판단하기 어렵고 과하다는 느낌을 지울 수 없다. The Truth about Aaron Swartz’s “Crime”에 해킹에 대한 내용이 좀 더 자세히 나오긴 하는데 Aaron이 JSTOR에 해를 가할 의도는 없었다는 것이다. 문서를 받아서 판매를 한다거나 개인의 이득을 취하려고 한 정황은 발견되지 않는다.

해커는 규칙을 따르지 않는다. 그것이 해킹의 본질이고 아메리카의 본질이기도 하다.
hackers are unruly. That is the essence of hacking. And it is also the essence of Americanness.
- Paul Graham

Aaron Swartz, American hero에서는 폴그래함이 말한 위의 말이 Aaron에 대한 정확한 표현이라고 하고 있다. Aaron의 행보를 보면 개발자이면서 사회적인 부분에 관심이 많았던것 같다.(대표적으로 SOPA 반대...) 사회가 좋은 방향으로 가기 위해서 어떻게 해야하는지에 관심이 많았고 실제로 그런 부분에 많은 참여를 했다. 이제 우리는 그를 잃었다.

팀 버너스리가 Aaron을 추모하며 남긴 짧은 글은 많은 생각과 슬프을 안겨준다.

Aaron is dead.

Wanderers in this crazy world,
we have lost a mentor, a wise elder.

Hackers for right, we are one down,
we have lost one of our own.

Nurtures, careers, listeners, feeders,
parents all,
we have lost a child.

Let us all weep.


timbl

Image by Sage Ross in Flickr

Rest In Peace. Aaron Swartz

My Comment..
난 이사람을 모른다.. 그런데 글은 가져왔다.. 이유는 머 항상 그렇지만 이러한 사람 있었고, 많은 일을 해왔던 개발자를 과거에는 몰랐지만 지금이라도 햄의 블로그를 보면서 알게 되었다면 가져와서 내 공간에도 기록을 남겨두자라는 생각에서다..

한편으로는 내가 나이를 먹고 있다는 반증인것인지.. 사람이 죽거나 하면 그냥 그러련히 했는데 지금은 명확하지 않은 많은 생각을 하게 된다..

그리고 늦게나마 개발에 관심을 두려고 조금씩 노력하는 와중에 글을 봐서 그런것인지.. 개발자 혹은 IT 관련 누군가 병으로 죽었거나 자살을 하고 이런 글을 보면 마음 한켠이 좀 그러하다..

2016년 6월 25일 토요일

[EP] RT:FM, 나는 프로그래머다 참석 후기..

저번주에 이어서 이번주[24일/금요일]에도 세미나를 다녀왔다.. 세미나는 이전에 등록 소개를 했던 나는 프로그래머다 라고 하는 세미나이다..

세미나는 13:00 ~ 18:00 인데 12:20 부터 참가등록을 진행한다고 안내 메세지가 왔다.. 그래서 나도 그 시각에 맞춰서 갔다.. 이번 세미나는 항상 같이 참여하고 놀던 B 군 이외에 S 군도 왠일로 참석을 했다..

세미나 장소가 이전에 참석했던 스프링캠프 2016 세미나 장소와 똑같은 광화문 더케이트윈타워 였는데.. 그래도 한 번 가봐서 그런지 익숙하게 장소까지 찾아가게 됬다..

도착해서 우선 사전등록을 하고 그에 따른 기념품, 명찰도 받았다.. 생각보다 사람이 진짜 많았는데 이런 세미나에 사람들의 관심이 날이 갈수록 늘어나는 듯한 기분이다..





이번에는 사은품 다운??? 그것이 목적이 아니긴 하지만.. 머그컵과 책을 받았다.. 책도 나중에 읽어서 꼭 후기를 남겨보리라.. ㅋㅋㅋ.. 흠.. 잘 될런지는 ㅡㅡ..

12:50 쯤이 되자 사회자를 소개하고 대략적인 세미나 시간표를 설명하고 그랬는데 나는 세미나 참석하면서 전문 사회자를 초빙한 것은 처음 보았다.. 사회자는 조은나래 님이란 분인데.. 상당히 이쁘셨다능.. 후훗..



드디어 13:00 에 조은나래님의 진행으로 세미나가 시작 되었다.. 살짝 소개만 하고 가셔서 너무 아쉽긴 했지만 처음보는 장면이라 신선했다.. ㅎㅎㅎ..

Session 1. 정개발 "나도 프로그래머다"
첫 세션의 주제는 원래 "나프다 미트업 2016 키노트:개발자의 생존전략에 대하여" 였지만 현실감에 맞게끔 바꿨다고 하셨다..


정개발님은 일본을 건너가서 10년간의 SI 개발을 하셨다고 한다.. 그 때는 JAVA 를 기반으로 모든지 시키는건 다 했다고.. 대단..;;; 다 할 수 있다는 것 자체가.. ㅎㅎ

하지만 2013년에 컨설팅 회사로 이직을 결정하셨는데 이직 후 경험을 얘기 해주셨다..
  • 지식의 부족으로 스스로에게 많은 충격을 받게 되고..
  • 선임에게 적성에 맞지 않는다는 평가까지 받음..
  • JSON 창시자 Douglas Crockford 를 만나는 기회도 얻음..
  • 세계적인 컨퍼런스에서 유명인을 만나면서 영어에 대한 갈증을 느끼게 되었다..
  • 위 사건이 동기부여의 계기라고 볼 수 있음..

또한, 본인은 http://www.moreagile.net/ 을 운영하게 되었는데 지금이라면 more 가 아니라 nomore 로 사이트 명을 했을거라며.. ㅋㅋㅋ..
  • 홍보를 좀 해보자해서 SNS 를 시작하였다..
  • 구글플러스에서는 염산악 님을 만나고..
  • 페이스북에서는 임작가 님을 만나게 되었다..

위 두분을 만나면서 나프다[나는 프로그래머다]를 결성하고 시작하게 되었다고 한다.. 그러면서 곁다리로 나프다에 대한 방송 프로세스, 나프다 구성 서비스와 운영비용 등을 말씀하셨다.. 운영비용이 1년에 1백만원도 안되더라능.. ㅋㅋㅋ..

나도 이번 세미나를 통해서 나프다라는 방송이 있다는 것을 처음 알게 되었는데 나프다 구성원이라고 할 수 있는 세분이 정말 유쾌하셨다.. 나중에 꼭 들어봐야겠다능.. 이제 새롭게 시즌 2 도 하신다고 하니.. ㅎㅎㅎ..

앞서서 다른 얘기들을 하시다가 드디어 진짜 주제인 "나도 프로그래머다" 에 대해서 말씀하셨는데.. 앞에서 너무 많은 시간을 소비하다보니 좀 짧게 발표하고 지나간 것이 정말 아쉬웠다..
  • 100 번 듣는것보다 한번의 발표가 본인에게 도움이 된다..
  • 나프다에 요청을 하면, 무엇이 되었건 지원하겠다..
  • 나프다 시즌2 예정이다..
  • 나프다 시즌2 에는 본인의 서울생활에 따른 적응을 위하여 잠시 하차를 한다..

그렇게 세션 1이 끝나고 세션 2로 넘어갔는데 세션 2는 공개방송 형태로 진행이 되는 시간이었다..

Session 2. 나프다[나는 프로그래머다] 공개방송
팟캐스트에서 하는 것에 대한 내용인데 약간 머라고 할까.. 과거 지나간 방송들에 대해서 간략히 소개하는 시간..?? 그리고 이런 방송이구나 하면서 느낄 수 있는..?? 시간들이었다.. 말씀들 자체가 너무 재밌게 하셔서 그런지 웃고 즐기면서 여유를 갖고 지나가는 시간이었다..


사진에서 왼쪽부터 순서대로 데니스 님, 임작가 님, 정개발 님 이다..

Session 3. 호시노 순스케 "일본 최대 e커머스 기업 라쿠텐"
일본 최대 소셜 e커머스 기업이라고 한다.. 사이트를 봐도 이러한 기업이 있는지는 처음 알았다.. 그래서 그런 것인지 발표자도 목표 자체가 회사를 대한민국에 많이 알리고 인지도를 높이기 위함이라고 하셨는데..



하지만 해당 발표가 아쉬웠던 점은 처음 소개시에는 일본어로 발표를 하다보니 통역을 할 것이라고 했는데 그런 것이 전혀 없었다는 것이다..

그리고 호시노 순스케님의 발표 이후에는 일본에서 근무하는 한국인 직원이 나와서 자기가 일하고 있는 부서와 하는 일에 대한 소개를 하더니 끝이 났다.. 개인적으로 이러한 회사가 있구나.. 하고서 알게 된 것은 좋지만 구성적인 면에서 상당히 아쉬운 세션이었다..



Session 4. 데니스 "저렴이 클라우드 사용하기"
나프다 멤버이기도 한 데니스 님이 개인 발표를 하는 시간이었다..

주제를 체리 피킹하기라고 하셨는데 처음에 듣고서 이게 당췌 먼말인지 알 수가 없었다.. 데니스 님 말대로 개념을 설명하자면, 케잌 위에 생크림이 조금 있는데 친구가 얄밉게 그 부분만 쏙 빼먹는 상황이라고 하셨다..



그래서 검색을 해보니 체리 피킹(cherry picking)이란 모순될 만한 중요한 비율의 관련있는 사례나 자료를 무시한 채, 본인의 논증에 유리한 사례만 취사선택하는 행위를 말한다. 이것의 가장 흔한 예는 확증편향이다. 용어는 배경은 체리를 수확하는 과정에서 왔다. 라는 의미였다..

체리피킹하기를 통해서 저렴이 클라우드, 고렴이 클라우드 에 대한 소개를 해주시고 성능차이라던지 기능차이 등등을 알려주셨는데.. 우리처럼 자본이 적은 서민들은 저렴이 클라우드를 사용해야 된다며 저렴이 클라우드를 많이 알려주셨다..

저렴이 클라우드 사용시 고려사항..
  • vCore Per Price..
  • vTraffic Per Price..

본격적인 체리피킹하기..
  • VM : fortacloud.co 에 대한 소개..
  • Free : IBM Catalyst [매월 1천 달러] 에 대한 소개..
  • PaaS : Azure.com APP 소개..
  • Free : Azure ML 은 공짜지만 최대용량이 10GB 에 불과하며, 웹 기반이고 마켓플레이스가 장점이다..
  • Free : Google Firebase 는 PaaS 로 VM 기반과 달리 데이터 통신기반 과금이다..
  • Free : SoftLayer Security Sean 에 대한 소개..

Security TIP 에 대해서 설명을 해주셨는데 내가 경험을 해본 것은 별루 없었으나 저러한 것들을 알고 있는다면 좋은 지식이 될 것임에는 틀림 없었다..
  • 대부분 ssh 포트가 열려있는데 상당히 취약한 포트이다..
  • beta.facebook.com 처럼 url 앞에 beta 를 붙여서 들어가보면 보안취약이 노출 되는 곳이 많다..
  • 워드프로세서도 보안취약이 심하기 때문에 IP를 고정화해서 하거나 2FACT 인증을 통해서 하는 것을 추천한다..
  • 저렴이 클라우드 사용시에는 보안모니터링 측면에서 많이 누락이 되므로 특히 보안에 신경을 써야되는데.. 저렴이라는 특성이 회사가 언제 망할지 모르기 때문에 정기적으로 백업을 하는 것을 제일 추천한다..

Session 5 구글 염제현 "이력서, 인터뷰 및 코딩 테스트 꿀팁"
발표 앞 부분은 화장실 다녀오고 하다보니 살짝 놓쳤다.. 화장실에 사람이 어찌나 많던지.. 고속도로 휴게소에서나 볼법한 줄 서서 볼일 보기를 해야했다.. ㅡㅡ.. 된장스럽게 진짜;; 긴장되서 잘 나오지도 않고 말이지.. 쩝;;;

이력서 제출에 대한 내용 작성 방법을 설명해주셨는데.. 어찌보면 이력서 제출 관련이나 인터뷰 하는 방법에 대한 노하우 대부분은 다른 세미나에서 선배님들이 많이 조언을 해주셨던 내용과 거의 비슷했다고 생각한다.. 그래서 비슷한 내용은 스킵하고 좀 틀렸던..?? 마음에 와 다았던..?? 내용 두가지만 적어보려고 한다..
  • 이력서에 거짓말을 하지 않기를 당부한다..
  • 인터뷰시에 본인의 이력서 내용을 확실하게 숙지하라.. 인터뷰 하다보면 본인의 이력서 내용도 몰라서 "제가요..??", "제가 그렇게 썼나요..??" 등의 질문을 하는 분이 있다고..


화이트 보드 코딩 테스트에 대한 방법 그리고 대처.. 해당 부분에서는 상황극을 해주셨는데.. ㅋㅋㅋㅋ.. 이런 상황을 처음 보기도 했지만 진짜.. 웃겼다.. 어떻게 저런 놀라운 발상으로 세미나에서 보여주실 생각을 하셨는지.. ㅎㅎㅎ..
  • 자신감 있게 풀어야되며, 흐름? 리듬? 을 잘 타야된다..
  • 메소드 하나 하나 사소한 것을 테스트 언어에 맞춰서 신경을 써야된다.. Ex. 변수 명칭, 메소드 명칭 등등..
  • 화이트 보드에서는 Tool 처럼 에러를 찾아주지 않기 때문에  작성하는데 있어서 신중해야 된다..
  • 코딩 테스트 하는데 있어서 처음부터 완벽하게 코드를 짜려고 하지말고, 우선은 시간내에 만드는 것이 좋다..

그리고 세션을 마무리하면서 말씀하신게 있었는데 면접관에게 개기지말고 겸손하게 해라.. 왜냐면 면접관은 당신의 적이 아니기 때문에 구태여 적대감을 갖고서 상대하거나 그럴필요가 없다는 것이다..

그리고 코딩 테스트나 면접을 잘 보기 위해서는 스터디 그룹을 통해서 서로가 입장을 바꿔서 해보면 자신이 무엇이 부족한지를 알게 된다고 한다.. 특히나 리크루터는 내가 채용이 되면 본인에게 이득이 되기 때문에 최소한 내 편이므로 잘 활용을 해보자는 것이다..

세션은 이렇게 마무리가 되었는데 발표자 염제현 님은 인상이 너무 좋으셨다.. 약간 개구스럽기도 하면서 꼭 케릭터 같은 인상을 주셨는데 상당히 좋은 분 같아 보였다.. ㅎㅎㅎ.. 은근 매력 있으시다능..

Session 6. 정민영 CTO "커뮤니티 활동"
이번 세션은 개발자들의 커뮤니티 활동에 관련해서 말씀을 하셨는데 상당히 어려보이셨는데 CTO 라고 하더라.. 대단하신 듯한 인상을..


본인이 활동하고 있는 AWS 한국 사용자 모임에 대해서 취지와 발전과정에 대해 간략하게 소개를 해주셨다..
  • 2011년 IRC 에서 비공식적으로 시작을 함..
  • 2012년 더 많은 발전과 살마들에게 다가가기 위해서 페이스북으로 이전 함..
  • 이후 50명이던 그룹이 세미나 발표 전날 기준 7,800 명의 그룹으로 발전..

그렇다면 왜 커뮤니티를 해야 되는 것인가..
  • 좋아하는 것을 사람들과 대화하려고 하는 것은 사람의 본능이라고 생각한다..
  • 개발자들이 좋아해야 될 기술들은 너무 많다..
  • 덕질의 필요성..?? 기술이 좋아지면 전도하고 싶어지고 그러다보면 좋아하는 사람이 증가하고 그로인해 재미있는 일이 증가한다.. 이 패턴이 계속 무한루프가 된다.. 그러다보니 덕질을.. ㅋㅋㅋ..
  • 자신의 커리어에 도움이 된다.. 해외에 오가며 발표를 할 수도 있고 많은 사람을 많나게 된다.. 무엇보다 기술에 대한 다양한 기회가 생긴다..
  • 취직, 채용, 집필..?? 다양한 기회가 발생한다..

정민영 님은 사람들이 커뮤니티를 어렵게 생각하는데 커뮤니티의 형태는 아주 다양하며 그것은 행사 참여, 지원봉사, 각종 포스팅 등등 이라고 하셨다.. 모두가 가벼운 마음으로 참여 했으면 좋겠다고 하셨는데.. 나도 어찌보면 그런 관점에서 세미나 그리고 포스팅 등을 하게 되는 듯 하다..

마지막으로 한 글귀를 남겨주셨는데 꽤 공감이 되는 글이었다..

커뮤니티는 열심히 할 수록
무엇보다 나에게 많은 것을 남깁니다..

Session 7. 골드만삭스 이주원 "본인의 개발이야기"
이주원 님은 골드만삭스라는 해외 회사에 다니고 계시는데 싱가폴에서 근무를 하고 계신다고 한다.. 그런데 이번 세미나 때문에 휴가를 내셔서 오셨다고 하니 열정이 대단하시기도 하고 그러한 시간을 내주신것에 감사를 드린다..

다만, 아쉬운 점은 회사 방침으로 인해서 발표 모습을 영상으로 담는 것은 상관이 없지만 doc 는 공개가 불가능하다고 하셨다.. 그래서 자료 없이 그냥 발표를 진행하셨다..

본인의 업무에 대해서 소개를 하셨는데 기업내 트레이딩 시스템 개발을 한다고 하셨다.. 근데 트레이딩..?? 이런 용어를 처음 들어봐서 검색해봤는데.. 주식, 선물, 옵션에 매매함에 있어 사용자가 정해놓은 규칙에 맞게끔 컴퓨터가 주식을 사고 파는 방법 이라고 한다.. 흠.. 저런것도 있구나 싶은 생각.. ㅎㅎㅎ..



업무에 대한 소개가 끝나고 금융권에 일하면서 본인이 느낀점에 대해서 말씀 하셨는데..
  • 피드백이 빨라서 좋다.. 빠른 패턴의 업무로 인해서 대응능력이 좋아지고, 커뮤니케이션 능력 또한 향상 되었다..
  • 개발자를 중요시하는 방향으로 가고 있다고 본다.. 이유는 전세계적으로 금융권에 개발자가 점차 늘어나고 있으며, 골드만삭스도 약 3만 5천여명 직원 중에 약 8천 ~ 1만여명이 엔지니어라는 것이 그것을 입증한다고 본다..

마지막으로 취업과 이직에 대해서 말씀해주셨는데 본인은 국내에서 일을 한적이 없고 해외에서만 약 7년여간 근무를 하다보니 국내 실정과는 차이가 있을것이라고 하셨다.. 그래서 국내 취업보단 해외 취업을 고민하거나 계획적인 분을 대상으로 노하우를 전해주고 싶다고 하셨다..
  • 링크드인 프로필이 상당히 중요하다..
  • 해외에서는 링크드인을 통해 구인구직이 이루어지는 경우가 상당히 많다..
  • 우리나라 사람은 링크드인 사진이 너무 정적이기게 그 부분을 좀 자연스럽게 바꿨으면 좋겠다..
  • 경력사항을 일정한 패턴에 의해서 작성하는데 특히 내용중에 직급 같은건 크게 의미가 없다..
  • 경력사항에 어떤 기술을 통해서 어떤일을 했는지가 중요하다..
  • 때론 그 일을 하면서 경제적이라던지 동시접속자수 등의 효과를 표현하는 것도 좋다..
  • 본인 기술에 대한 마케팅이 필요하다.. 스스로 한 프로젝트 경험이라던지 먼가를 배우고 있다면, 그것에 대한 티를 내는 것을 추천한다..

내가 비록 외국계 기업을 간다던지 해외취업을 준비하는 것은 아니지만 자신의 기술에 대한 마케팅의 필요성에 대해서는 상당히 공감을 했던 세션이었다..

Session 8. 임백준[임작가] "개발자는 무엇으로 사는가..??"
이번 세션에는 세션 4에서처럼 나프다 멤버중 한명이신 임작가님의 개인 발표였다..


해당 세션은 발표라기보단 세미나 전반적인 그리고 본인의 고민거리 등등 Q&A 시간이라고 보는 것이 더 정확한 세션의 목표이자 주제였다고 생각한다.. 하지만, 오히려 그렇게 진행 된 것이 더 자유롭게 얘기하고 답변하고 해서 그런지 상당히 즐거운 시간이 됬다..

많은 질문이 나오고 답변도 나오고 했지만 약간 본인의 감상평이나 몇몇 질문을 빼고서 정리를 해보려고 한다..

Q. 비전공자인데 석사를 언어쪽으로 나왔는데 그런 부분에 대한 조언을 듣고 싶다.. 
A. 비전공자라고 하더라도 상대적으로 비전공자가 이쪽 분야에서 할 수 있는 일은 많다.. 그 일들을 찾아가면 충분하다고 본다..

Q. 비전공자인데 공부하는 노하우는..??
A. 공부의 우선순위를 너무 멀게 잡지말고, 앞에 있는 근처의 것부터 잡아서 실행하는게 좋다..


Q. 개발자로써 중년으로 넘어가는 시기를 잘 극복하는 방안은..??
A. 나프다를 듣고[해당 부분에서 완전 다들 빵터짐 ㅋㅋㅋㅋ..], 세미나를 자주 참석하면서 본인 스스로에게 자극도 주고 리프레쉬를 시켜라..

Q. 나프데 데니스 님은 방송을 들어보면 세상 모든 프레임워크를 이건 좋다 안좋다 말씀하시는데.. 정말 다 써보신건가..
A. 과거 빚을 갚기 위해서 정말 미친듯이 일을 많이 했다.. 그러다보니 많은 프레임워크를 사용해봤고, 방송에서 얘기하는 부분들에 대한 내용은 다 써본 것을 얘기하는 것이다..


Q. 시즌2에서 어떤식으로 학습을 해왔고, 어떻게 이 위치까지 도달할 수 있는지 등에 대한 노하우를 소개하는 것은 어떤가..
A. 의견을 반영해서 고려해보도록 하겠다.. 다만, 그러한 패턴으로 꾸몄는데 방송이 망하면 당신 책임이다.. [다들 또 터짐.. ㅋㅋㅋㅋㅋㅋ..]

그리고 나도 질문을 했다.. 질문을 할까 말까 진짜 고민을 많이 했는데 언제까지 항상 두려워하고, 주저하면서 지낼 수는 없다고 생각했고, 무엇보다 이러한 세미나와서 적극적으로 참여하는게 좋다고 생각을 해서 질문을 했다.. 다만 꼭 대중 앞에서 얘기를 하면 목소리가 살짝 떨리는게 아쉬웠지만 이 또한 점점 좋아지리라 생각한다.. 아래는 내 질문 내용과 답이다.. 내거니까 좀 색감 있게.. ㅋㅋㅋ


Q. 임작가 님을 이곳에 와서 처음 뵜는데 음성이 너무 멋지시고, 말씀을 하실 때 천천히 여유있게 말씀을 하셔서 너무 좋았다.. 그리고 질문이 있는데 아까 구글면접 관련 세션에서 면접관들은 당신을 붙이려고 한다라고 하셨는데 의외로 회사에서는 압박면접을 많이 한다.. 압박면접을 받을 때 노하우가 있을까요..??

임작가님에게 질문을 했지만, 갑자기 정개발님이 나오셔서 ㅋㅋㅋ.. 답변을 대신 해주셨다..

A. 압박면접을 하는 회사는 입사를 해서도 그 압박을 받을 것이다..[또 한번 큰 웃음을 주셨다.. ㅋㅋㅋㅋㅋ.. 개공감.. ㅋㅋㅋ] 만약 압박면접을 보고서도 그 회사가 좋다면 들어가면 되고 아니라면 걍 안들어가면 된다..

이렇게 모든 세션이 끝나고 다음은 피자, 치킨, 맥주를 먹으면서 즐기는 Networking Party 시간 이었다.. 하지만 난 개인사정으로 인해서 해당 행사에는 참석을 하지 못했다.. 나오면서 잠시 봤는데 사람들이 생각보다 많이 모여서 먹고 즐기고 있더란..

나프다 세미나가 거의 매년 하는듯 한데.. 다음 세미나 때 참석을 한다면 그 때는 꼭 참석해서 즐거운 시간을 나도 만끽하고 싶다..

그리고 이번 세미나는 다른 세미나를 갔을 때보다 유독 좀 즐겁게 지난간 듯 했다.. 시간 가는 줄도 몰랐고 말이지.. 사회자 말로는 06월 30일날 발표자료를 참여자 각각의 메일로 보내준다고 한다.. 받으면 해당 자료를 각 세션별로 링크하도록 해야겠다.. 동영상 자료는 편집이 좀 더 걸리는 관계로 조금 더 늦어진다고 한다..

마지막으로 나프다 방송 시즌2에서도 대박나시길 바라고, 정개발님도 어서 서울생활에 적응하셔서 컴백하시길 바랍니다.. 무엇보다 이렇게 뜻깊고 즐거운 세미나를 마련해주신 나프다 이하 모든 관계자님과 후원사에게도 감사의 뜻을 전합니다.. 내년에도 또 뵐수 있기를 희망해봅니다.. (__)

2016.07.07 오늘 받은 발표자료 링크를 추가한다..

2016년 6월 22일 수요일

[EP] 먹고 코딩하고 사랑하기, 오래하려면 어떻게 해야할까? 참여 후..

일전에 올렸던 세미나 신청 및 소개 글을 올린 후 드디어 후기를 올리게 되었다.. 원래는 당일에 올리려고 했지만 그날 칭구 B군과 술을 너무 많이 먹는 바람에.. ㅠㅜ..

각설하고 주제는 "먹고 코딩하고 사랑하기, 오래하면 어떻게 해야할까?" 였다.. 이번 세미나는 다른 것보다 멘토님들과의 토론이 있다고 해서 더욱 관심이 갔었던 세미나이기도 하다..

사이트에 공지된 세미나 시간은 13:00 ~ 18:00 였으나 실질적으로는 조금 일찍시작한 모양이다.. 내가 갔을 때는 이미 조금 진행이 된 후였다.. ㅡㅡ.. 조금 더 일찍 갈것을 살짝 아쉬웠다.. 아래 사진을 보면 알겠지만 예상했던 것 보다 사람이 상당히 많이 참석했다.. 소규모 세미나고 해서 사람이 이렇게 많이 모일것이라곤 생각도 못했는데.. 흐미;;;














세미나에 참석을 하기 위해서 세미나실로 들어가자마자 사람이 많은 관계로 앞자리 쪽에 앉았는데 그 자리에 아웃사이더 햄이 앉아 있었다.. 이게 왠열.. ㅋㅋㅋ.. 햄과 간단하게 인사를 하고 첫 세션은 그곳에서 들었다..

1. 옐로트래블랩스MAY LEE 이정희 님..
난 이분을 잘 모르지만 여성분으로써 본인의 개발 경험담과 이직 그리고 연봉의 변화 등을 얘기하시는 듯 했다.. 고등학교 졸업 이후 개발자 생활을 했다고 하는데 대단하고 용기 있는 분이라는 생각을 했다..



무엇보다 본인의 경험담을 생동감 있게 설명하셨고, 본인이 지금까지의 자리에 오기위해서 어떠한 노력을 했는지를 알려주셨다..

본인은 Facebook 을 통해서 커뮤니티를 참여하고, 그것을 기반으로 여러 커뮤니티를 참가하게 되고 본인의 Skill Up 을 이뤄낼 수 있었다고 한다.. 비록 나이는 어리지만 본인의 앞날을 위해서 그렇게 실행을 하시는 점 그리고 열정을 담아서 발표한 부분들이 상당히 인상적이었다..













2. 아웃사이더 변정훈 님..
이번 세션부터는 친구 B 군이 있는 곳으로 자리를 옮겨서 듣게 되었다..

햄은 과거 첫 회사에서부터 인연도 있기도 하고, 내가 블로그를 하게 된 계기도 이러한 세미나를 참여하게 된 계기도 햄에게서 상당부분 영향을 받았기에 조금 더 집중을 하고 보게 되었다..

아 근데 다른분들이 연예인 개발자라고 하더란.. ㅋㅋㅋ 아무래도 블로그에서도 유명하고 커뮤니티를 많이하면서 인맥과 유명세가 많아지고 해서 그런게 아닌가 싶다.. 항상 느끼지만 대단한 형이다..

주제는 더 나은 개발자 되기 였는데 이 부분에 대한 발표라던지 햄이 말하는 부분들 그리고 어떻게 해왔는지에 대한 부분들에 대해서 상당부분 공감을 하면서 들었다..









햄은 개발자라면 들어서 좋을만한 것을 A-Z 까지 전반적으로 발표를 해주셨다.. 인상적이었던 부분을 정리해보면..

신입 때 사용하던 기술을 현재 사용하는 것은 거의 없다..
  • 그만큼 하나를 배워서 살아가기 힘든 세상이기에 장거리 달리기처럼 차근 차근 본인의 페이스와 스타일에 맞게 꾸준히 해야 된다는 것이다..
왜 공부를 해야 되는 것인가..
  • 개발자에게는 개발실력이 가장 중요하다..
  • 상위 1% 의 목표가 아닌 어제보다 나은 개발자가 되기 위해서 꾸준히 노력을 하자는 것이다..
주변에 개발자 없어요..??
  • 회사는 개발잘하고 일잘하고 커뮤니케이션도 잘 되는 사람을 찾는다..
  • 개발자는 많지만 회사에서 원하는 개발자를 찾기란 상당히 어렵다..
잘할 것 같은 개발자는 무엇인가..??
  • 열정있고 빨리 배우고 가르치면 잘 할 것 같은 사람을 뜻한다..
  • 즉, 회사는 그런 사람을 원하는 것이다..
면접은 50% 이상이 운이다..
  • 본인의 컨디션도 중요하고 면접관과 자신과의 캐미도 중요하고 운에 좌우되는 경우도 꽤 된다..
  • 코딩 테스트도 쉬운문제가 나올 수도 있고 어려운 문제가 나올 수도 있다..
여기서 본인의 Tip..!!!
  • 배운것을 기록해라.. 블로그 등등 공개된 것을 사용하도록 해라..
  • 공개 블로그를 하다보면 설명을 해야되고, 그로 인해서 더 자세히 공부해야되고, 본인 스스로 모르는 것을 파악하게 되기 때문에 더 많은 것을 배우게 된다..

대략적인 큰 카테고리는 저정도였다.. 무엇보다 햄은 발표를 하면서 자주 강조한 것이 있다..


  • 꾸준히 공부를 해야된다..
  • 본인의 속도와 페이스에 맞춰서 해야 된다..
  • 공개 블로그를 통해서 스스로의 배움을 확인해라..
  • 나 뿐 아니라 다른 사람을 가르치면서 발전해라..
  • 인터넷 뿐만 아니라 독서를 통해 지식을 습득해라..
  • 모든 기술을 알지는 못하더라도 시대 흐름을 파악해라..

이정도라고 볼 수 있는데 햄은 진짜.. 개발을 위해서 태어난 사람 같았다.. 그런 햄을 본받으면서 지금 나도 새롭게 무엇인가를 시작하고 시도도 해보곤 하지만 항상 배울것이 많은 분이라고 생각한다..

비록 햄이 발표한 내용들이 어느정도 내가 공감하면서 시행하고 있는 것도 있지만 대단한 사람이라고 항상 느끼고 있다.. 아직도 노력할 것 투성이다..

그나저나 햄은 시간 관리를 좀 하셔야겠음.. 시간 겁니 오버하셔서 운영진들이 앞에서 시간 알려주고 하시는데 엄청 웃겼다.. ㅋㅋㅋ..

3. 임성현 님..
이분은 이전에 스프링 세미나를 갔다가 뵜던 분이어서 그런지 왠지 모르게 더 반가운 면이 있었다.. 꼴랑 세미나 2번 가고서 아는 사람이 또 보이니 어지간히 반가웠다.. ㅋㅋㅋ..

하지만 아쉽게도 발표 내용들이 일전에 들었던 내용과 거의 흡사해서 집중을 많이 하지는 않고서 들었다.. 나 스스로에게는 약간의 쉬는 타임이라고 해야될까..















발표를 해주신 큰 골자만 정리해보면 다음과 같다.. 내용은 과거와 비슷해서 해당 세미나 내용을 따로 정리하지는 않는다..


  • 이직에 관련된 부분들..
  • 대기업에서 중소기업, 중소기업에서 대기업의 차이..
  • 경력직의 이력서에 대한 부분들..
  • 채용절차가 어떻게 진행되는지..
  • 본인의 이력서 관리를 어떻게 할 것인가..
  • 멘토님들의 이력서 리뷰시간..
  • 이직에 대한 시기와 면접을 볼 때..

하지만 발표를 들으면서 또 들게 된 생각은 역시나.. 이력서를 다시금 업데이트하고 다듬어야 겠다는 생각.. ㅋㅋㅋ..

4. NAVER LABS 의 최영목 님..
발표라기 보단 네이버 랩스에서 구인구직을 위해서 나와서 설명을 해주셨다.. 머 상황만 되면 가보고 싶은 곳이긴 하지만 아직 나의 실력과 현상으로는 힘든게 사실이다.. 그래도 부럽긴 했다.. 책임근무제라던지 운동지원이라던지..




5. 우아한형제들 CTO 김범준 님..
해당 세션 역시 구인구직이었는데 배달의민족을 아시는 분들은 아.. 라고 하실듯하다.. 난 처음에 몰라서 검색을 해보고서 알게 되었다는..

2015년에 Food E-Commerce 1등을 하셔다는데 매출액이 자그마치 1조 2천억이었다고 한다.. 새로운 분야이고 해서 잘은 모르지만 그래도 대단한 듯.. 가고 싶은 곳이지만 역시나 이놈의 내 실력이 문제라능.. ㅜㅠ




6. 패널들과의 토론시간..
어찌보면 내가 가장 기다린 시간이라고 할 수 있다.. 이유는 일반적인 세션보다 살아있는..?? 멘토님들과 개발자들간의 대화이기 때문인데..

멘토님 성함이 다 맞는지 모르겠지만 맨 왼쪽부터 말해보면..

사회를 맡으신 유명환님, 박성철님, 자바지기 박재성님, 임성현님, MAY LEE 라고 불리우시는 이정희님, 토비의 스프링으로 유명하신 이일민님, 강대명님, 나의 호프이자 아웃사이더 연예인 개발자 변정훈님 순이다..













이 시간은 개발자들이 온라인상에 질문을 남겨주면 사회자가 적절한 질문을 질의하고 멘토님들이 대답을 해주시는 형태였는데 모든 질문을 다 듣고 기록을 하지는 못했지만 대략적으로 포스팅 하려고 한다..














멘토님들처럼 오래 개발을 하려면 어떻게 해야될까..
  • 본인이 좋은 일이라면 꾸준히 공부하고, 본인이 갖고 있는 것을 포기하면서라도 공부를 할 수 있는 열정이 중요하다고 생각한다..
첫 회사가 스타트업인데 경력이 과연 될 수 있을까..
  • 해당 부분은 딱히 문제가 안되는 듯하다..
  • 스타트업이라면 오히려 대형 개발사보다 더 많은 것을 배우고 맨땅에 헤딩하면서 개발을 하기 때문에 더 얻는 것이 많다고 본다..
경력자로 입사시에 기존 직원과의 차별에 대해서..
  • 그 부분은 어떤 회사에 가도 똑같을 것이고 인정을 하는 것이 좋다고 본다..
  • 만약 내가 팀장보다 연봉이 많다고 해보자.. 그럴 때 상대는 어떻겠는가..
  • 기본 직원은 입사시절부터 열심히해서 그 위치까지 왔는데 경력으로 입사해서 들어온다면 당연히 반발감이 생길 수 있다고 본다..
  • 차별에 대해서 인정을하고 본인이 선택한 회사이니 만큼 녹아들어가려고 노력을 하는 것이 현명하다고 볼 수 있다..
비전공자와 전공자..
  • 기본적으로 전공자의 유리함을 인정하고 시작하는 것이 좋다고 본다..
  • 또한, 비전공자여서 실망하기 이전에 본인이 얼마나 노력했는가를 봐라.. 나는 기초를 포기하고 프레임워크 부터 접근해서 누구보다 열심히했고 죽을만큼 했다..
  • 그 이후에 공부를 하다보니 기초도 눈에 들어왔고, 현 위치까지 왔다..
  • 처음에 시작하는 위치는 당연히 차이가 있지만 극복하지 못할것은 아니며, 자신이 무엇인가를 얻기 위해서 죽을만큼 노력한다면 충분히 그 위치에 도달할 수 있다..
공부를 어떻게 해야될까..
  • IT 업계에는 똑똑한 사람이 너무 많다.. 한 번 듣고 나에게 설명해주는 사람도 있을 정도로.. 그렇기에 나는 시간을 많이 투자해서 이루어냈다..
  • 회사에 일을 해결한 사람이 있다면, 쫒아가서 해결한 일에 대한 원인과 결과 그리고 과정 모든 것을 물어보고 내것으로 만들었다..
  • 나의 공부패턴을 정의하고 그 이후에는 레퍼런스 등을 이해될때까지 반복학습을 한 후에 접근하면 조금 더 쉽다..
  • 싫증도 잘내고 새로운 것에는 관심도 많기에 내가 하고 싶은것을 하고 싫증나는것은 그만하고 하다보면 어느새 기술이 내것이 되어있다..
  • 예제로 나온 코드들은 다 이유가 있다.. 그 예제를 하면서 왜 이 예제를 썼는지를 파악하다보면 공부가 자연스럽게 될 것이다..

My Comment..
오후 13:00 ~ 18:00 까지 세미나가 다 종료되었다.. 정말 뜻 깊은 시간이었고, 누군가의 기술을 듣는것도 중요하지만 경력은 나보다 짧더라도 조금 더 올바른 길을 혹은 공부하는 길을 간 사람과 선배들의 얘기를 듣는것이 더 중요하다고 느꼈다..

왜냐면 내가 생각하기에 기술이란 것은.. 코딩이란 것은.. 급하면 어떻게 해서든 하게 되고, 주변에 물어서라도 하면 해결 자체는 가능하다고 본다..


다만, 그런 해결하는 과정속에서 어떻게 내것을 만들어가느냐.. 어떠한 식으로 접근을 하느냐.. 공부를 어떻게 하느냐.. 나의 커리어를 어떻게 쌓아 가느냐 등등이 중요하다고 생각한다.. 그렇게 내공을 쌓다보면 기술이란 것은 따라오기 마련이라고 생각하기 때문이다..


이번 세미나에서는 그러한 부분을 많이 느끼고 많이 생각하게 된 계기여서 참 좋았던 시간들이었다..


아래 사진은 세미나 후에 받은 기념품을 찍은 것이다.. 머 특별한게 있는 것은 아니지만 세미나 참석후에 이런 것을 받으면 왠지 모르게 기분이 좋고 뿌듯해진다..


다음 세미나 참석을 또 기약해본다.. 그리고..

세미나를 준비해주신 운영진 여러분께 감사드립니다..


















[DB] RTRIM 을 써보자..

이번 포스팅은 프로젝트 수행 중 사용하게 된 RTRIM 에 대해서 얘기를 해보고자 한다.. 보통 인터넷에서 검색을 해보면 RTRIM LTRIM 은 아주 간단한 함수 예제 중 하나이다..

R 과 L 은 Right 와 Left 의 약자로 각각 오른쪽에 있는 공백 그리고 왼쪽에 있는 공백을 삭제하는 함수라고 보면 된다..

난 쿼리문에서 해당 부분을 사용하게 되었는데 사용하게 된 계기는 함수 정의와는 약간 틀리다고 봐야된다.. 보통은 순수하게 공백을 삭제하기 위해서 쓰는 듯 하다.. 설명들도 그렇고 말이지..

나는 프로젝트 수행 중 SELECT Query 를 코딩하고 있었고, 해당 쿼리문의 WHERE 절에 조건이 세개가 들어갔다.. 그런데 거기서 유독 두개의 조건이 적용이 안되는 것이다.. 아래가 그 쿼리의 일부분인데.. 앞부분이야 머 뻔하게 데이터를 가져오는 부분이라 생략했다..

WHERE ColumnA LIKE ? AND ColumnB = ? AND Column C = ?

그런데 저 조건에서 ColumnA 와 ColumnB 에 대한 쿼리가 제대로 적용이 안되더란 말이지.. 명확히 얘기하면 SQL Tool 에서는 돌아가지만, Java 에서 해당 쿼리 수행 후 while(rs.next()) 를 하면 계속 false 가 나오는 것이다..[다들 알겠지만 혹시 모르니.. false 면 데이터가 현재 없다는 것이고, true 면 데이터가 존재한다는 것이다..] 한마디로 저 세가지 조건에 대해서 데이터가 없다는 것이지.. 그런데 막상 돌리면 위에 말한것처럼 SQL Tool 에서는 쿼리 결과가 잘보인다.. ㅋㅋ.. -_-;;;

이것저것 바꿔봐도 지속적으로 그러한 문제가 생겨서 혹시나 하는?? 그냥?? 별 생각없는?? 마음에 테이블 속성을 살펴봤다..

DESC TableName

속성을 보니 ColumnA 와 ColumnB 는 CHAR 타입이고, ColumnC 는 VARCHAR 타입이었던 것.. CHAR 타입은 사이즈를 정해두기 때문에 내가 검색하는 데이터가 사이즈보다 작게되면 자연스럽게 공백이 생기는 것이 이유였다..

예를 들면 CHAR(8) 인데.. 내가 검색하려는 문구가 820207 이라면, 실제 받아들이기는 '820207  ' 이렇게 되는 것이다.. 뒤에 공백이 나머지 길이만큼 생성이 된다는 것..

아뿔싸!!! 그래서 쿼리를 바꿔봤다.. 어떻게..?? 검색 조건이 안되는 부분에만 RTRIM 을 걸어줬다..

WHERE RTRIM(ColumnA) LIKE ? AND RTRIM(ColumnB) = ? AND Column C = ?

위와 같이 빨강색 표시된 부분처럼 해주니 바로 나오더란 SQL Tool 에서야 WHERE 절에 조건이 '820207' 이런식으로 공백이 없었으니 당연히 잘 나오고, Java 를 통해서 데이터 확인을 해보니 드디어 while(rs.next()) 가 true 였다..

별거 아닌 것으로 삽질을 좀 했는데 어찌보면 내가 기초가 부족해서 그런것일지도 모르겠다.. RTRIM LTRIM 자체는 알고 있고 들어도 봤지만, Oracle 에서의 테이블 내 속성 타입에 대한 정의나 개념을 100% 숙지하지 못했기에 해당 오류를 수정하는데 조금 시간이 걸린 것이라고 보여진다.. 그래도 이렇게 포스팅을 하고 하면서 나 스스로 또 한번 정리를 하기에 오늘도 이렇게 난 배워간다.. 무엇보다 문제 해결에 약간의 어드바이스를 해주신 동료 C 과장님에게 감사드린다..

아!! 그리고 나 스스로에게 짤막하게 충고를 하고자 한다.. 나의 능력 이상의 것을 탐하려고만 하지말고, 나 스스로 능력을 키우거나 그게 힘들거나 귀찮고 싫다면, 나에게 주어진 업무 혹은 공간에서 그에 맞도록 최선을 다하도록 하자.. 언제나 남의 떡이 커보이는 것이니..

명심하자.. 노력은 하되..
서두르지 말고, 시샘하지 말자..


2016년 6월 20일 월요일

[Talk] 링크드인 계정을 만들다..

어제 세미나를 다녀왔다.. 해당 세미나 내용은 내일 모레쯤해서 올릴 계획이다.. 원래는 어제 올리려고 했으나 칭구 B군과 뒷풀이로 술을 많이 마시는 바람에.. ㅋㅋ..

무튼 그건 그렇고 세미나를 다녀오고 나면 항상 먼가 시작을 하게 되는 듯한데.. 이번에는 링크드인을 시작해보려고 한다.. 이미 다들 사용을 많이 하는 서비스 이지만 항상 나는 뒤늦게 시작하는 감이 있지만 그래도 한 번 해보려고 한다.. 내 능력과는 무관하게 너무 이것저것 해보는거 아닌가 싶기도 하고..

그래서 Linkedin 사이트에 가서 바로 계정을 만들었다능.. 머 별다른 내용을 포스팅하려는건 아니고.. 그냥 만들었다는 기록이라고 해야될까.. 무엇인가 시도를 하거나 변화가 발생하면, 블로그를 시작한 이상 기록을 해두는 것이 좋다고 생각하기에.. 아래는 메인 화면이다..


보면 좀 휑하긴 한데.. 오늘은 생성해서 진짜 간단한 정보만 입력했다.. 사진이나 기타 정보는 집에가서 해야 될 듯 하고, 이미지에 보면 빨강색 박스가 바로 주소다.. 위에 링크를 걸어두긴 했지만, 그래도 한 번 더 강조를.. ㅋㅋㅋ..

수요일쯤해서 세미나 포스팅 하면서 이력서도 함께 추가 수정을 하도록 해야겠다묭..


2016년 6월 17일 금요일

[Talk] 아이락스 키보드 새로 구매..

급작스럽게 계획에 없던 포스팅을 하게 되었다.. 예전부터 키보드를 바꾸고 싶었는데 결혼을 하다보니 아무래도 내 마음대로 바꾸기가 쉽지가 않았다..

그런데 이번에 연말소득공제 금액이 조금 쏠쏠하게 들어오게 되어서 와이프한테 얘기를 하니 바꿔도 된다고.. ㅋㅋㅋ..


그래서 그전부터 좀 봐오던 i-rocks K10M 으로 바꾸게 되었다.. 원래는 FILCO 흑축을 썼는데 이번거는 청축이다..

첫번째 사진은 LED 를 최대한 밝게 했을 때이다.. 집이기 때문에 그렇게까지 밝게 할 필요는 없다고 본다..



두 번째 사진은 LED 를 최소로 밝게 했을 때이다.. 집에서는 PC 방처럼 약간 어두운 분위기가 아니다보니 제일 적당하다고 생각한다..


세 번째 사진은 맨 오른쪽에 있는 숫자패드만 불이 안들어오도록 한 사진이다.. 어차피 숫자패드는 많이 안쓰기 때문에 이렇게 끄고서 쓰려고 한다..


네 번째 사진은 과연 저렇게 쓸까 싶긴한데.. 게임을 위해서 특정 키들만 불이 들어오는 기능이다..


음 대략적인 기능은 위와 같다.. 근데 지금 이렇게 포스팅을 하면서 키보드를 계속 사용중인데 FILCO 랑은 확실하게 느낌이 틀리긴하다.. 축이 틀린것도 있지만 기본적인 사양차이도 있다고 생각한다.. 각각의 브랜드들만의 특성이라고 해야되나.. 무튼 머 그러하다.. ㅎㅎㅎ..

내가 처음 기계식 키보드에 입문[2008년 쯤???]했을 때부터 FILCO 를 사용하다가 처음으로 다른 브랜드로 넘어온거긴 한데.. 나름 재밌고 좋은듯하다.. ㅋㅋㅋㅋ..

가격도 10만원 이하이기 때문에 저렴하고 키감도 혹시나 했던 걱정은 사라지게 만들어준다.. 무엇보다 소리가 상당하지 않을까 했는데 걱정했던 것보단 소리도 적당한편이어서 여러모로 잘 산듯하다..

고장나지 않고 오래 잘 쓸 수 있기를 빌어본다..
키보드 사준 와이프.. 쌩유!!! 

2016년 6월 16일 목요일

[JAVA] 14장 객체 관계 매핑 (ORM) 데이터 접근 #2..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

이 문서는 개인적인 목적이나 배포하기 위해서 복사할 수 있다. 출력물이든 디지털 문서든 각 복사본에 어떤 비용도 청구할 수 없고 모든 복사본에는 이 카피라이트 문구가 있어야 한다.

14.4 JDO
스프링은 데이터 접근 전략으로 하이버네이트 지원과 같은 방식으로 표준 JDO 2.0과 2.0 API를 지원한다. 이 통합 클래스들은 org.springframework.orm.jdo 패키지에 있다.

14.4.1 PersistenceManagerFactory 설정
스프링은 스프링 어플리케이션 컨텍스트내에서 로컬 JDO PersistenceManagerFactory를 정의할 수 있도록 LocalPersistenceManagerFactoryBean 클래스를 제공한다.


1
2
3
4
5
6
7
Xml

<beans>
  <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
    <property name="configLocation" value="classpath:kodo.properties"/>
  </bean>
</beans>

아니면 PersistenceManagerFactory 구현클래스를 직접 인스턴스화해서 PersistenceManagerFactory를 설정할 수 있다. JDO PersistenceManagerFactory 구현 클래스는 JDBC DataSource 구현클래스처럼 스프링을 사용하는 설정에 자연스럽게 어울리는 JavaBeans 패턴을 따른다. 이 설정방식은 일반적으로 스프링이 정의하고 connectionFactory 프로퍼티로 전달되는 JDBC DataSource를 지원한다. 예를 들어 다음은 오픈소스 JDO 구현체인 DataNucleus(이전의 JPOX)(http://www.datanucleus.org/)에 대한 PersistenceManagerFactory 구현체의 XML 설정이다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Xml

<beans>

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
  </bean>

  <bean id="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close">
    <property name="connectionFactory" ref="dataSource"/>
    <property name="nontransactionalRead" value="true"/>
  </bean>
</beans>

Java EE 어플리케이션 서버의 JNDI 환경에서 JDO PersistenceManagerFactory를 설정할 수도 있다. 이는 일반적으로 특정 JDO 구현체가 제공하는 JCA 커넥터로 이루어진다. PersistenceManagerFactory 등을 획득하고 노출하는데 스프링의 표준 JndiObjectFactoryBean / <jee:jndi-lookup>를 사용할 수 있다. 하지만 EJB 컨텍스트 외부에서는 JNDI에 PersistenceManagerFactory를 가지고 있어서 생기는 실제적인 장점은 전혀 없다. 합리적인 이유가 있을 때만 이러한 설정을 사용해라. 이 논쟁에 대한 내용은 Section 14.3.6, “컨테이너가 관리하는 리소스와 로컬에 정의한 리소스 비교”를 참고해라. 여기서 나오는 논의는 JDO에도 적용된다.

14.4.2 평범한 JDO API에 기반한 DAO 구현하기
DAO도 스프링에 대한 어떤 의존성을 갖지 않고 주입한 PersistenceManagerFactory로 평범한 JDO API를 직접 사용해서 작성할 수 있다. 다음은 이에 대한 DAO 구현체의 예제이다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Java

public class ProductDaoImpl implements ProductDao {

  private PersistenceManagerFactory persistenceManagerFactory;

  public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
    this.persistenceManagerFactory = pmf;
  }

  public Collection loadProductsByCategory(String category) {
    PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
    try {
      Query query = pm.newQuery(Product.class, "category = pCategory");
      query.declareParameters("String pCategory"); 
      return query.execute(category);
    }
    finally {
      pm.close();
    }
  }
}

위의 DAO가 의존성 주입패턴을 따르기 때문에 스프링의 JdoTemplate로 코드를 작성한 것처럼 스프링 컨테이너와 궁합이 잘 맞는다.

1
2
3
4
5
6
7
Xml

<beans>
  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmf"/>
  </bean>
</beans>

팩토리에서 항상 새로운 PersistenceManager를 얻는다는 것이 이러한 DAO와 관련된 주요 문제점이다. 스프링이 관리하는 트랜잭션이 적용된 PersistenceManager에 접근하려면 대상 PersistenceManagerFactory 앞에 TransactionAwarePersistenceManagerFactoryProxy를 정의하고 이 프록시에 대한 참조를 다음 예제처럼 DAO에 전달해라.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Xml

<beans>
  <bean id="myPmfProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory" ref="myPmf"/>
  </bean>

  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmfProxy"/>
  </bean>
</beans>

데이터 접근 코드는 호출한 PersistenceManagerFactory.getPersistenceManager() 메서드에서 (존재한다면) 트랜잭션이 적용된 PersistenceManager를 얻을 것이다. 이 메서드 호출이 프록시를 통해서 이뤄져서 팩토리에서 새로운 PersistenceManager 얻기 전에 현재 사용중인 트랜잭션이 적용된 PersistenceManager를 먼저 확인한다. 트랜잭션이 적용된 PersistenceManager에서는 PersistenceManager의 모든 close() 호출을 무시한다.

데이터 접근코드가 항상 활성화된 트랜잭션내에서(또는 최소한 활성화된 트랜잭션 동기화내에서) PersistenceManager.close() 호출을 생략해도 안전하므로 DAO 구현체에서 가지고 있어야 하는 전체 finally 블럭이 간결해진다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Java

public class ProductDaoImpl implements ProductDao {

  private PersistenceManagerFactory persistenceManagerFactory;

  public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
    this.persistenceManagerFactory = pmf;
  }

  public Collection loadProductsByCategory(String category) {
    PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
    Query query = pm.newQuery(Product.class, "category = pCategory");
    query.declareParameters("String pCategory"); 
    return query.execute(category);
  }
}

활성화된 트랜잭션에 기반한 DAO에서는 활성화된 트랜잭션이 TransactionAwarePersistenceManagerFactoryProxy의 allowCreate 플래그를 끄도록 하는 것을 권장한다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Xml

<beans>
  <bean id="myPmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory" ref="myPmf"/>
    <property name="allowCreate" value="false"/>
  </bean>

  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmfProxy"/>
  </bean>
</beans>

이 DAO 방식의 가장 큰 장점은 JDO API에만 의존한다는 것이다. 어떤 스프링 클래스도 임포트할 필요가 없다. 물론 이는 비침투적인 방법이고 JDO 개발자들도 자연스럽게 느낄 것이다.

하지만 DAO는 평범한 JDOException(언체크드 예외이므로 선언하거나 잡지 않아야 한다.)를 던지므로 JDO 자체의 예외 구조에 의존하기를 원하지 않는한 호출자들은 예외를 치명적인 오류(fatal)로만 다뤄야한다. 호출자가 구현전략에 묶이지 않고는 낙관적인 작금(locking) 실패같은 특정 원인을 잡는 것은 불가능하다. 이 트래이드오프는 어플리케이션이 상당히 JDO 기반이거나 특별한 예외처리가 필요없다면 수긍할만할 것이다.

요약하자면 평범한 JDO API에 기반해서 DAO를 작성할 수 있고 이 DAO는 여전히 스프링이 관리하는 트랜잭션에 참여할 수 있다. 이미 JDO에 익숙하다면 이 전략이 맘에 들 것이다. 하지만 평범한 JDOException를 던지는 DAO에서는 스프링의 DataAccessException로 명시적인 변환을 해야한다.(원한다면)

14.4.3 트랜잭션 관리

Note
아직 읽어보지 않았다면 Section 11.5, “선언적인 트랜잭션 관리”를 읽어보기를 강력히 권장한다. 스프링의 선언적인 트랜잭션 지원의 자세한 내용을 알 수 있을 것이다.

트랜잭션내에서 서비스 작업을 실행하려고 스프링의 일반적인 선언적 트랜잭션 기능을 사용할 수 있다. 예를 들면 다음과 같다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Xml

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

  <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    <property name="persistenceManagerFactory" ref="myPmf"/>
  </bean>

  <bean id="myProductService" class="product.ProductServiceImpl">
    <property name="productDao" ref="myProductDao"/>
  </bean>

  <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
      <tx:method name="increasePrice*" propagation="REQUIRED"/>
      <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
      <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
  </tx:advice>

  <aop:config>
    <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
  </aop:config>
</beans>

JDO 가 퍼시스턴트 객체를 수정하려면 활성화된 트랜잭션이 필요하다. 하이버네이트와는 다르게 JDO에서는 트랜잭션이 아닌 플러시(flush) 개념은 존재하지 않는다. 이 때문에 선택한 JDO 구현체를 특정 환경에 대해 설정해야 한다. 특히 활성화된 JTA 트랜잭션 자체를 탐지하려고 JTA 동기화를 명시적으로 설정해야 한다. 이는 스프링의 JdoTransactionManager가 수행하듯이 로컬 트랜잭션에서는 필수사항이 아니지만 스프링의 JtaTransactionManager가 주도하든지 EJB CMT와 평범한 JTA가 주도하든지 간에 JTA 트랜잭션에 참여하려면 필요하다.

JdoTransactionManager는 같은 JDBC DataSource에 접근하는 JDBC 접근 코드에 JDO 트랜잭션을 노출할 수 있다. 그래서 등록된 JdoDialect가 의존하는 JDBC Connection의 획득을 지원한다. 이는 기본적으로 JDBC에 기반한 JDO 2.0 구현체에 해당하는 경우이다.

14.4.4 JdoDialect
고급 기능으로 JdoTemplate와 JdoTransactionManager 둘 다 jdoDialect 빈 프로퍼티에 전달할 수 있는 커스텀 JdoDialect를 지원한다. 이 시나리오에서는 DAO가 PersistenceManagerFactory 참조를 받지 않고 대신 전체 JdoTemplate 인스턴스(예를 들어 JdoDaoSupport의 jdoTemplate 프로퍼티에 전달된다.)를 얻는다. JdoDialect 구현체를 사용하는 경우 일반적으로 벤더에 특화된 방법으로 스프링이 지원하는 고급 기능을 사용할 수 있다.

  • 커스텀 격리수준이나 트랜잭션 타임아웃같은 특쟁 트랜잭션의 의미를 적용한다
  • JDBC에 기반한 DAO에 노출하기 위한 트랜잭션이 적용된 JDBC Connection의 획득
  • 스프링이 관리하는 트랜잭션 타임아웃에서 자동으로 계산한 쿼리 타임아웃의 적용
  • 트랜잭션상의 변경사항이 JDBC에 기반한 데이터 접근코드에 보이도록 PersistenceManager의 플러싱 시도(eagerly flushing)
  • 스프링 DataAccessExceptions로 JDOExceptions의 고급 변환
이에 대한 작업과 스프링의 JDO 지원내에서 사용하는 방법에 대한 자세한 내용은 JdoDialect Javadoc를 참고해라.

14.5 JPA
org.springframework.orm.jpa 패키지에 있는 스프링 JPA는 하이버네이트나 JDO를 통합한 것과 유사한 방법으로 추가적인 기능을 제공하는 의존 구현체와 함께 Java Persistence API를 지원한다.

14.5.1 스프링 환경에서 JPA 설정에 대한 세가지 옵션
스프링 JPA 지원은 엔티티 매니저를 얻으려고 어플리케이션이 사용할 JPA EntityManagerFactory를 설정하는 세가지 방법은 제공한다.

14.5.1.1 LocalEntityManagerFactoryBean

Note
독립적인 어플리케이션이나 통합 테스트처럼 간단한 배포 환경에서만 이 방법을 사용한다.

LocalEntityManagerFactoryBean 는 데이터 접근을 할 때 JPA만 사용하는 어플리케이션의 간단한 배포 환경에 적합한 EntityManagerFactory를 생성한다. 팩토리 빈은 JPA PersistenceProvider 자동탐지 메카니즘(JPA의 Java SE 부트스트래핑(bootstrapping)에 따르면)을 사용하고 대부분의 경우에는 퍼시스턴스 유닛 이름만 지정하면 된다.


1
2
3
4
5
6
7
Xml

<beans>
  <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="myPersistenceUnit"/>
  </bean>
</beans>

이 JPA 배포 형식은 가장 간단하고 가장 제한적이다. 이미 존재하는 JDBC DataSource 빈 정의를 참조할 수 없고 기존에 존재하는 전역 트랜잭션을 지원하지 않는다. 게다가 퍼시스턴스 클래스의 위빙(바이트코드 변환)은 프로바이더의 특화되어 있고 때로는 구동할 때 특정 JVM 에이전트를 지정해야 한다. 이 방법은 JPA 스펙의 설계상 독립적인 어플리케이션과 테스트 환경에만 알맞다.

14.5.1.2 JNDI에서 EntityManagerFactory 획득하기

Note
Java EE 5 서버에 배포할 때 이 방법을 사용해라. 서버의 기본 프로바이더가 아닌 다른 프로바이더를 위해 사용하는 서버에 커스텀 JPA 프로바이더를 배포하는 방법은 서버의 문서를 확인해 봐라.

JNDI에서 EntityManagerFactory를 획득하려면(예를 들면 Java EE 5 환경에서) XML 설정만 변경하면 된다.


1
2
3
4
5
Xml

<beans>
  <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>

이 동작은 표준 자바 EE 5 부트스트래핑을 가정한다. 자바 EE 서버는 자바 EE 배포 디스크립터(예를 들면 web.xml)에서 퍼시스턴스 유닛(실제로는 어플리케이션 jar의 META-INF/persistence.xml 파일들)과 persistence-unit-ref 엔트리를 자동으로 탐지하고 이러한 퍼시스턴스 유닛들의 컨텍스트 위치에 이름을 짓는 환경을 정의한다.

이러한 시나리오에서 퍼시스턴트 클래스의 위빙(바이트코드 변환)을 포함한 전체 퍼시스턴스 유닛 배포는 Java EE 서버에 달려있다. JDBC DataSource는 META-INF/persistence.xml 파일의 JNDI 위치로 정의한다. EntityManager 트랜잭션은 서버의 JTA 하위시스템과 통합된다. 스프링은 획득한 EntityManagerFactory를 그냥 사용하고 EntityManagerFactory를 의존성 주입으로 어플리케이션 객체들에 전달하고 퍼시스턴스 유닛을 위해 트랜잭션을 관리한다. (보통 JtaTransactionManager를 통해서)

같은 어플리케이션에서 어려 퍼시스턴스 유닛을 사용한다면 JNDI로 획득한 퍼시스턴스 유닛들의 빈 이름은 예를 들어 @PersistenceUnit와 @PersistenceContext 어노테이션에서 어플리케이션이 참조하기 위해 사용하는 퍼시스턴스 유닛 이름과 일치해야 한다.

14.5.1.3 LocalContainerEntityManagerFactoryBean

Note
스프링에 기반하는 어플리케이션 환경에서 전체 JPA 기능을 사용하려면 이 방법을 사용해라. 이 방법은 복잡한 퍼시스턴스가 필요한 독립적인 어플리케이션과 통합 테스트뿐만 아니라 톰캣같은 웹 컨테이너에서도 사용할 수 있다.

LocalContainerEntityManagerFactoryBean 으로 EntityManagerFactory 설정을 완전히 제어할 수 있고 세밀한 커스터마이징이 필요한 환경에 알맞다. LocalContainerEntityManagerFactoryBean는 persistence.xml 파일, 제공된 dataSourceLookup 전략, 지정한 loadTimeWeaver에 기반한 PersistenceUnitInfo 인스턴스를 생성한다. 그러므로 JNDI 외부에서 커스텀 데이터소스로 작업하는 것이 가능하고 위빙 접근을 제어할 수 있다. 다음 예제는 LocalContainerEntityManagerFactoryBean의 대표적인 빈 정의를 보여준다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Xml

<beans>
  <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="someDataSource"/>
    <property name="loadTimeWeaver">
      <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
    </property>
  </bean>
</beans>

다음 예제는 대표적인 persistence.xml 파일이다.

1
2
3
4
5
6
7
8
Xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
  <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
    <mapping-file>META-INF/orm.xml</mapping-file>
    <exclude-unlisted-classes/>
  </persistence-unit>
</persistence>


Note
exclude-unlisted-classes 요소는 <exclude-unlisted-classes/> 숏컷을 제공하려고 어노테이션이 붙은 엔티티 클래스에 대한 스캐닝을 하지 않는다는 것을 항상 나타낸다. JPA 명세서에서 이 숏컷을 제안하고 있지만 안타깝게도 이 숏컷의 false를 의미하는 JPA XSD와 충돌한다. 따라서 <exclude-unlisted-classes> false < /exclude-unlisted-classes/>는 지원하지 않는다. 엔테티 클래스에 대한 스캐닝이 이뤄지길 원한다면 exclude-unlisted-classes 요소를 그냥 생략해라.

LocalContainerEntityManagerFactoryBean 의 사용하는 것이 어플리케이션내에서 유연한 로컬 설정을 가능하게 하는 가장 강력한 JPA 설정 방법이다. 존재하는 JDBC JDBC DataSource로의 연결을 지원하고 로컬 트랜잭션과 전역 트랜잭션 등을 지원한다. 하지만 런타임 환경에서 퍼시스턴스 프로바이더가 바이트코드 변환을 필요로한다면 위빙이 가능한 클래스 로더를 사용할 수 있어야 하는 조건같은 요구사항도 강제한다.

이 방법은 Java EE 5 서버에 내장된 JPA 기능과 충돌할 것이다. 완전한 Java EE 5 환경에서는 JNDI에서 EntityManagerFactory를 얻는 것을 고려해 봐라. 아니면 예를 들어 META-INF/my-persistence.xml같은 LocalContainerEntityManagerFactoryBean에 커스텀 persistenceXmlLocation를 지정하고 어플리케이션 jar 파일들에 해당 이름을 가진 디스크립터만 포함해라. Java EE 5 서버가 기본 META-INF/persistence.xml 파일들만 찾기 때문에 커스텀 퍼시스턴스 유닛들은 무시해서 스프링이 주도하는 JPA 설정과의 충돌을 피한다.(예를 들어 이는 Resin 3.1에 적용된다.)

LoadTimeWeaver 인터페이스는 스프링이 제공하는 클래스로 웹 컨테이너 환경인지 어플리케이션 서버 환경인지에 따른 방법으로 JPA ClassTransformer 인스턴스를 플러그인할 수 있도록 한다. 자바 5 에이전트로 ClassTransformers를 후킹(hooking)을 하는 것은 보통 효율적이지 않다. 에이전트는 전체 가상머신에서 동작하고 로딩된 클래스를 모두 검사하는데 이는 프로덕션 서버 환경에서는 보통 원치 않는 것이다.

스프링은 다양한 환경에 대한 다수의 LoadTimeWeaver 구현체를 제공해서 VM에 대해서가 아니라 클래스 로더별로만 ClassTransformer 인스턴스를 적용할 수 있도록 한다.

LoadTimeWeaver 구현체와 설정(제너릭이나 여러 플랫폼(톰캣, 웹로직, OC4J, 글래스피시, 레신, JBoss등)에 커스터마이징하는 방법)에 대한 자세한 내용은 Section 8.8.4.5, “스프링 설정”의 AOP 부분을 참고해라.

로드타임 위빙은 언제 필요한가?

모 든 JPA 프로바이더가 JVM 에이전트를 필요로 하는 것은 아니다. 하이버네이트가 그 중 하나이다. 프로바이더나 에이전트를 필요로 하지 않거나 에이전트를 대신할 다른 것(커스텀 컴파일러나 ant 태스크를 통해 빌드시에 강화(enhancements)하는 등의)이 있다면 로드타임 위버를 사용하지 말아야 한다.

앞의 섹션에서 설명했듯이 context:load-time-weaver 설정요소를 사용해서 컨텍스트 범위의 LoadTimeWeaver를 설정할 수 있다. (이는 스프링 2.5부터 사용할 수 있다.) 모든 JPA LocalContainerEntityManagerFactoryBeans는 자동적으로 이러한 전역 위버(weaver)를 선택한다. 이 방법이 로드타임 위버를 설정할 때 선호하는 방법으로 플랫폼(웹로직, OC4J, 글래스피시, 톰캣, 레신, JBoss, VM 에이전트)의 자동 탐지와 위버를 인식한 모든 빈에 위버의 자동전파(propagation)를 제공한다.


1
2
3
4
5
6
Xml

<context:load-time-weaver/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  ...
</bean>

하지만 필요하다면 loadTimeWeaver 프로퍼티로 전용 위버를 수동으로 지정할 수 있다.

1
2
3
4
5
6
7
Xml

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
  </property>
</bean>

어떤 방법으로 LTW를 설정하는지에 관계없이 이 기법을 사용해서 인스트루멘테이션(instrumentation)에 기반한 JPA 어플리케이션을 에이전트가 필요없이 대상 플랫폼(예: 톰캣)에서 실행할 수 있다. 이는 JPA 변환자(transformer)가 클래스로더 수준에만 적용되무로 각각 격리되기 때문에 호스팅하는 어플리케이션이 여러 JPA 구현체에 의존하고 있는 경우 특히 중요하다.

14.5.1.4 여러 퍼시스턴스 유닛 다루기
예 를 들어 클래스패스에 다양한 JARS가 저장되어 있는 여러 퍼시스턴스 유닛 위치에 의존하는 어플리케이션에서 스프링은 PersistenceUnitManager가 중앙 레파지토리처럼 동작하고 상당한 비용이 들 수 있는 퍼시스턴스 유닛 탐색과정을 피하게 한다. 기본 구현체는 파싱하고 나중에 퍼시스턴스 유닛이름으로 획득하는 여러가지 위치를 지정할 수 있게 한다. (기본적으로 클래스패스는 META-INF/persistence.xml 파일을 검색한다.)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Xml

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
  <property name="persistenceXmlLocations">
    <list>
     <value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
     <value>classpath:/my/package/**/custom-persistence.xml</value>
     <value>classpath*:META-INF/persistence.xml</value>
    </list>
  </property>
  <property name="dataSources">
   <map>
    <entry key="localDataSource" value-ref="local-db"/>
    <entry key="remoteDataSource" value-ref="remote-db"/>
   </map>
  </property>
  <!-- 데이터소스를 지정하지 않으면 이것을 사용한다 -->
  <property name="defaultDataSource" ref="remoteDataSource"/>
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceUnitManager" ref="pum"/>
  <property name="persistenceUnitName" value="myCustomUnit"/>
</bean>

기본 구현체는 PersistenceUnitInfo 인스턴스를 JPA 프로바이더에 제공하기 전에 커스터마이징할 수 있게 한다. 이는 모든 호스팅된 유닛에 영향을 주는 프로퍼티들을 사용해서 선언적으로 하거나 퍼시스턴스 유닛을 선택할 수 있는 PersistenceUnitPostProcessor로 프로그래밍적으로 할 수 있다. PersistenceUnitManager를 지정하지 않았다면 새로 생성해서 LocalContainerEntityManagerFactoryBean가 내부적으로 사용한다.

14.5.2 평범한 JPA에 기반한 DAO 구현하기

Note
EntityManagerFactory 인스턴스는 스레드 세이프하지만 EntityManager는 그렇지 않다. 주입한 JPA EntityManager는 JPA 명세서에 정의된 대로 어플리케이션의 JNDI 환경에서 가져온 EntityManager처럼 동작한다. 모든 호출을 (존재한다면)현재의 트랜잭션이 적용된 EntityManager로 위임한다. 존재하지 않는다면 작업마다 EntityManager를 새로 생성해서 폴백(fall back)을 수행해서 사실상 스레드 세이프하게 만든다.

스프링에 대한 의존성은 전혀 두지 않고 주입된 EntityManagerFactory나 EntityManager를 사용해서 평범한 JPA로 코드를 작성할 수 있다. PersistenceAnnotationBeanPostProcessor가 활성화되어 있다면 스프링은 필드 수준과 메서드 수준에서 @PersistenceUnit과 @PersistenceContext 어노테이션을 둘 다 이해할 수 있다. @PersistenceUnit 어노테이션을 사용하는 평범한 JPA DAO 구현체는 다음과 같을 것이다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Java

public class ProductDaoImpl implements ProductDao {

  private EntityManagerFactory emf;

  @PersistenceUnit
  public void setEntityManagerFactory(EntityManagerFactory emf) {
    this.emf = emf;
  }

  public Collection loadProductsByCategory(String category) {
    EntityManager em = this.emf.createEntityManager();
    try {
      Query query = em.createQuery("from Product as p where p.category = ?1");
      query.setParameter(1, category);
      return query.getResultList();
    }
    finally {
      if (em != null) {
        em.close();
      }
    }
  }
}

위의 DAO는 스프링에 대한 의존성이 없으면서도 여전히 스프링 어플리케이션 컨텍스트에 잘 어울린다. 더욱이 DAO는 기본 EntityManagerFactory의 주입을 필요로하는 어노테이션의 장점을 취한다.

1
2
3
4
5
6
7
8
Xml

<beans>
  <!-- JPA 어노테이션의  후처리자(bean post-processor) -->
  <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

  <bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>

명시적으로 PersistenceAnnotationBeanPostProcessor 정의하는 대신에 어플리케이션 컨텍스트 설정에 스프링 context:annotation-config XML 요소를 사용하는 것을 고려해 봐라. 이렇게 하면 CommonAnnotationBeanPostProcessor 등을 포함한 어노테이션기반의 설정에 대한 스프링의 모든 표준 후처리자(post-processor)를 자동으로 등록한다.

1
2
3
4
5
6
7
8
Xml

<beans>
  <!-- 모든 표준 설정 어노테이션의 후처리자 -->
  <context:annotation-config/>

  <bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>

이러한 DAO의 가장 큰 문제점은 팩토리로 항상 새로운 EntityManager를 생성한다는 것이다. 팩토리 대신에 주입해야하는 트랜잭션이 적용된 EntityManager를(실제 트랜잭션이 적용된 EntityManager에 대한 공유되고 스레드 세이프한 프록시이기 때문에 "공유된(shared) EntityManager"라고도 부른다) 요청해서 이 문제를 피할 수 있다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Java

public class ProductDaoImpl implements ProductDao {

  @PersistenceContext
  private EntityManager em;

  public Collection loadProductsByCategory(String category) {
    Query query = em.createQuery("from Product as p where p.category = :category");
    query.setParameter("category", category);
    return query.getResultList(); 
  }
}

@PersistenceContext 어노테이션은 기본값이 PersistenceContextType.TRANSACTION인 선택적인 속성값 type을 가진다. 이 기본값은 공유된 EntityManager 프록시를 받는데 필요하다. 다른 값인 PersistenceContextType.EXTENDED는 완전히 다른 것이다. 이는 소위 확장된 EntityManager가 되어 스레드세이프하지 않으므로 스프링이 관리하는 싱글톤 빈처럼 동시에 접근하게 되는 컴포넌트에서는 사용하지 말아야 한다. 확장된 EntityManager는 상태를 가진 컴포넌트에서만 사용하도록 만들어졌다. 예를 들면 현재 트랜잭션에 묶인 것이 아니라 어플리케이션에 완전히 묶인 EntityManager의 생명주기를 가진 세션에 존재하는 상태를 가진 컴포넌트들이다.

주 입된 EntityManager는 스프링이 관리(진행중인 트랜잭션을 인식하는)한다. 새로운 DAO 구현체가 EntityManagerFactory 대신 EntityManager의 메서드 수준 주입을 사용할때 조차도 어노테이션의 사용때문에 어플리케이션 컨텍스트 XML을 변경할 필요는 없다는 점이 중요하다.

이 DAO 방식의 가장 큰 장점은 Java 퍼시스턴스 API에만 의존한다는 것이다. 어떤 스프링 클래스도 임포트할 필요가 없다. 게다가 JPA 어노테이션을 이해하기 때문에 스프링 컨테이너가 자동으로 주입을 적용한다. 이는 비침투적이고 JPA 개발자들이 더 자연스럽게 느낄 것이다.

메서드 수준의 주입과 필드수준의 주입
의존성 주입(@PersistenceUnit과 @PersistenceContext같은)을 나타내는 어노테이션들은 클래스 내부의 필드나 메서드에도 적용할 수 있으므로 메서드 수준(method-level)의 주입과 필드수준(field-level)의 주입이라고 부른다. 필드수준의 어노테이션들은 간결하고 사용하운 반면 메서드 수준의 어노테이션들은 주입된 의존성에 추가적인 처리를 할 수 있게 한다. 두 가지 모두에서 멤버 가시성(public, protected, private)은 중요치 않다.

클래스수준의 어노테이션들은 어떤가?

Java EE 5 플랫폼에서 클래스 수준의 어노테이션들은 의존성 선언에 사용하고 리소스 주입에는 사용하지 않는다.

14.5.3 트랜잭션 관리

Note
스프링의 선언적인 트랜잭션 지원의 자세한 내용을 알고싶다면 (아직 읽어보지 않았다면) Section 11.5, “선언적인 트랜잭션 관리”를 읽어보기를 강력히 권한다.

트랜잭션 내에서 서비스작업을 실행하려면 스프링의 공통 선언적인 트랜잭션 기능을 사용할 수 있다. 예를 들면 다음과 같다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Xml

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

  <bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf"/>
  </bean>

  <bean id="myProductService" class="product.ProductServiceImpl">
    <property name="productDao" ref="myProductDao"/>
  </bean>
  
  <aop:config>
    <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
  </aop:config>

  <tx:advice id="txAdvice" transaction-manager="myTxManager">
    <tx:attributes>
      <tx:method name="increasePrice*" propagation="REQUIRED"/>
      <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
      <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
  </tx:advice>
</beans>

스프링 JPA는 같은 JDBC DataSource에 접근하는 JDBC 접근코드에 JPA 트랜잭션을 노출하려고 설정된 JpaTransactionManager를 허용해서 의존하는 JDBC Connection의 획득을 지원하는 등록된 JpaDialect를 제공한다. 스프링은 Toplink, Hibernate, OpenJPA JPA의 방언을 제공한다. JpaDialect 메카니즘에 대한 자세한 내용은 다음 섹션에서 살펴볼 것이다.

14.5.4 JpaDialect
JpaTemplate 의 고급 기능처럼 JpaTransactionManager와 AbstractEntityManagerFactoryBean의 하위클래스들은 jpaDialect 빈 프로퍼티에 전달되는 커스텀 JpaDialect를 지원한다. 이러한 시나리오에서 DAO는 EntityManagerFactory의 참조를 받는 것이 아니라 전체 JpaTemplate 인스턴스를(예를 들어 JpaDaoSupport의 jpaTemplate 프로퍼티에 전달 된다.) 받는다. JpaDialect 구현체는 일반적으로는 벤더에 특화된 방법으로 스프링이 지원하는 몇몇 고급 기능들을 활성화할 수 있다.

  • 커스텀 격리수준이나 트랜잭션 타임아웃같은 특정 트랜잭션 의미를 적용한다.
  • JDBC에 기반한 DAO에 노출하기 위한 트랜잭션이 적용된 JDBC Connection의 획득
    PersistenceExceptions를 스프링의 DataAccessExceptions로의 변환
특수한 트랜잭션 의미와 예외의 고급변환에 특히 가치가 있다. 사용한 기본 구현체 (DefaultJpaDialect)는 어떤 특수한 기능도 제공하지 않는다. 위의 기능이 필요하다면 적절한 방언(dialect)을 지정해야 한다.

JpaDialect의 작업과 JpaDialect Javadoc가 스프링의 JPA 지원내에서 어떻게 사용되는지 알고 싶다면 JpaDialect Javadoc을 참고해라.

14.6 iBATIS SQL 맵
스프링 프레임워크의 iBATIS 지원은 스프링의 JDBC 지원과 아주 비슷하다. JDBC와 다른 ORM 기술에서 같은 템플릿 방식의 프로그래밍을 지원한다. iBATIS 지원은 스프링의 예외 계층과 동작하고 스프링의 IoC 기능을 사용할 수 있게 한다.

스프링의 표준 시설(facilities)로 트랜잭션 관리할 수 있다. JDBC Connection외에 특별한 트랜잭션 리소스가 없기 때문에 iBATIS를 위한 특수한 트랜잭션 전략은 필요치 않다. 따라서 스프링의 표준 JDBC DataSourceTransactionManager나 JtaTransactionManager로도 완전히 충분하다.

Note
스프링은 iBATIS 2.x를 지원한다. iBATIS 1.x 지원 클래스들은 더이상 제공하지 않는다.

14.6.1 SqlMapClient 설정하기
iBATIS SQL Map을 사용한다는 것은 스테이트먼트와 리절트맵을 포하함 SqlMap 설정 파일을 생성하는 것을 포함한다. SqlMapClientFactoryBean를 사용해서 스프링이 이러한 것들을 로딩하는 것을 담당한다. 예를 들어 다음의 Account 클래스를 사용할 것이다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Java

public class Account {

  private String name;
  private String email; 

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getEmail() {
    return this.email;
  }

  public void setEmail(String email) {
    this.email = email;
  }
}

이 Account 클래스를 iBATIS 2.x에 매핑하려면 다음의 SQL 맵 Account.xml를 생성해야 한다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Xml

<sqlMap namespace="Account">

  <resultMap id="result" class="examples.Account">
    <result property="name" column="NAME" columnIndex="1"/>
    <result property="email" column="EMAIL" columnIndex="2"/>
  </resultMap>

  <select id="getAccountByEmail" resultMap="result">
    select ACCOUNT.NAME, ACCOUNT.EMAIL
    from ACCOUNT
    where ACCOUNT.EMAIL = #value#
  </select>

  <insert id="insertAccount">
    insert into ACCOUNT (NAME, EMAIL) values (#name#, #email#)
  </insert>
</sqlMap>

iBATIS 2에 대한 설정파일은 다음과 같을 것이다.

1
2
3
4
5
Xml

<sqlMapConfig>
  <sqlMap resource="example/Account.xml"/>
</sqlMapConfig>

iBATIS가 클래스패스에서 리소스를 로딩하기 때문에 Account.xml 파일을 클래스패스에 두어야 한다는 것을 잊지 말아라.

스프링 컨테이너에서 SqlMapClientFactoryBean를 사용할 수 있다. iBATIS SQL Map 2.x에서 JDBC DataSource는 지연 로딩을 활성화하는 SqlMapClientFactoryBean에서 보통 지정한다. 다음은 이러한 빈 정의에 필요할 설정이다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Xml

<beans>

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
  </bean>

  <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    <property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
    <property name="dataSource" ref="dataSource"/>
  </bean>
</beans>

14.6.2 SqlMapClientTemplate와 SqlMapClientDaoSupport 사용하기
SqlMapClientDaoSupport 클래스는 SqlMapDaoSupport와 유사한 지원 클래스를 제공한다. DAO를 구현할 때 이 클래스를 확장한다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Java

public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {

  public Account getAccount(String email) throws DataAccessException {
    return (Account) getSqlMapClientTemplate().queryForObject("getAccountByEmail", email);
  }

  public void insertAccount(Account account) throws DataAccessException {
    getSqlMapClientTemplate().update("insertAccount", account);
  }
}

DAO 에서 쿼리를 실행하는 데 어플리케이션 컨텍스트의 SqlMapAccountDao를 설정하고 SqlMapAccountDao를 SqlMapClient 인스턴스와 연결한 후에 미리 설정된 SqlMapClientTemplate를 사용한다.

1
2
3
4
5
6
7
Xml

<beans>
  <bean id="accountDao" class="example.SqlMapAccountDao">
    <property name="sqlMapClient" ref="sqlMapClient"/>
  </bean>
</beans>

생성자 아규먼트로 SqlMapClient를 전달해서 SqlMapTemplate 인스턴스를 수동으로 만들수도 있다. SqlMapClientDaoSupport 기반 클래스가 개발자들을 위해서 SqlMapClientTemplate 인서턴스를 미리 초기화한다.

SqlMapClientTemplate는 인자로 커스텀 SqlMapClientCallback 구현체를 받아들이는 일반적인 execute 메서드를 제공한다. 예를 들어 배치작업에 이를 사용할 수 있다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Java

public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {

  public void insertAccount(Account account) throws DataAccessException {
    getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
      public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
        executor.startBatch();
        executor.update("insertAccount", account);
        executor.update("insertAddress", account.getAddress());
        executor.executeBatch();
      }
    });
  }
}

일반적으로 네이티브 SqlMapExecutor가 제공하는 작업의 어떤 조합이라도 이러한 콜백에서 사용할 수 있다. 던져진 어떤 SQLException이라도 스프링의 일반적인 DataAccessException 계층으로 자동으로 변환된다.

14.6.3 평범한 iBATIS API에 기반한 DAO 구현하기
어떤 스프링 의존성도 없이 주입된 SqlMapClient를 직접 사용해서 DAO를 평범한 iBATIS API로 작성할 수도 있다. 다음 예제는 이에 대응되는 DAO 구현체를 보여준다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Java

public class SqlMapAccountDao implements AccountDao {
        
  private SqlMapClient sqlMapClient;
  
  public void setSqlMapClient(SqlMapClient sqlMapClient) {
    this.sqlMapClient = sqlMapClient;
  }

  public Account getAccount(String email) {
    try {
      return (Account) this.sqlMapClient.queryForObject("getAccountByEmail", email);
    }
    catch (SQLException ex) {
      throw new MyDaoException(ex);
    }
  }

  public void insertAccount(Account account) throws DataAccessException {
    try {
      this.sqlMapClient.update("insertAccount", account);
    }
    catch (SQLException ex) {
      throw new MyDaoException(ex);
    }
  }
}

이 시나리오에서 관행적인 방법으로 iBATIS API가 던진 SQLException를 처리해야 한다. 보통은 SQLException을 어플리케이션에 특화된 DAO 예외로 감싸서 처리한다. 평범한 iBATIS에 기반한 DAO가 의존성 주입패턴을 따르고 있기 때문에 어플리케이션 컨텍스트에서의 연결은 SqlMapClientDaoSupport 예제에서의 연결처럼 보인다.

1
2
3
4
5
6
7
Xml

<beans>
  <bean id="accountDao" class="example.SqlMapAccountDao">
    <property name="sqlMapClient" ref="sqlMapClient"/>
  </bean>
</beans>