[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년 4월 21일 목요일

[EP]웹 보안 취약성 관한 교육..

나른한 오후에 보안 교육을 받았다.. 1차, 2차 교육이 있었는데 오늘이 2차고, 1차는 어제였다.. 어제는 개인휴가였기 때문에 오늘 듣게 되었다..

어찌보면, 해당 회사에서 근무하면서 거의 매년 또는 전/후반기에 교육을 듣게 된다.. 특별한 케이스가 아니면, 교육의 내용이 엄청 바뀌지는 않는 듯 하다..

하지만, 내가 블로그를 시작한게 올해부터였기 때문에 처음으로 포스팅을 해본다.. 만약, 추후 교육을 또 받았는데 바뀐것이 많다면, 추가 포스팅을 해보도록 하겠다.. 지금 기준에서는 거창한 포스팅은 아니기 때문에 세부적인 내용은 개발자 스스로 조금 더 검색을 해서 확인을 해야된다.. 이 글은 이런게 있다 정도의 개념이라고 보면 된다.. 무엇보다 해당 회사도 그렇지만, 약 30여개의 보안항목 중에 실질적으로 중요도를 높여서 확인하는 것은 9개 정도이다.. 가장 큰 이유는 각 회사마다 업무에 따른 중요도의 기준이 틀리 듯 이곳의 중요도 기준이 그러하다..

상주하고 있는 인력이 교육을 해주셨는데 마음이 급하셨는지 회사 소개 및 본인 소개는 없었다.. 타이틀 소개와 목차 소개 후 바로 본론으로 고고.. 그렇다면 교육에서 언급한 9가지 항목에 대해서 간단한 소개와 대응 방안을 보도록 하자..

다시 말하지만, 이건 간단한 소개정도이고 실질적인 적용은 자신이 다니는 회사에 맞게 검색을 더 해야되며, 소스를 더 찾아봐야 된다.. 요즘 웹 개발에 있어서 이정도를 주로 보안 취약성으로 많이 본다?? 정도가 딱 알맞다..

1. SQL 인젝션
  • 기본정의 : SQL 내에 있는 파라미터를 조작해서 쿼리처럼 실행이 되도록 해서 DB 제어를 한다.
  • 해결방법 : preparedStatement 를 사용해서 변수 바인딩을 하거나 특수문자 필터링 처리를 한다.

2. XSS [크로스 사이트 스크립트]
  • 기본정의 : 웹 사이트 내에서 임의의 스크립트를 실행한다.
  • 해결방법 : replaceAll 등을 통해서 필터링 처리를 하거나 꼭 사용해야 하는 특수문자라면 필터링 처리를 했다가 데이터를 받는 부분에서 다시 복원하는 방식으로 사용한다.

3. 파일 업로드
  • 기본정의 : 시스템 컨트롤이 가능한 파일을 업로드 하는경우를 뜻한다.
  • 해결방법 : 허용된 확장자만 업로드가 되도록 코딩을 하거나 추축불가능한 파일명 및 경로사용 내지는 서버사이드 구현을 통해 사전 위험도를 관리한다.

4. 파일 다운로드
  • 기본정의 : 지정된 파일외에 서버내 파일을 다운로드해서 임의로 사용하는 것을 뜻한다.
  • 해결방법 : 사용하는 모듈을 Index 화해서 사용하거나 요청하는 user 의 권한을 확인 후 처리하도록 한다.

5. 불충분한 인가
  • 기본정의 : 접근 권한에 대한 체크로직이 없어서 접근하게 되는 경우를 뜻한다.
  • 해결방법 : userID 및 권한 등을 추가적으로 검증하는 로직을 추가한다.

6. 쿠키변조
  • 기본정의 : 쿠키 값 변조를 통해서 접근 및 권한상승을 임의로 한다.
  • 해결방법 : 서버 측 session 을 사용해서 값을 전달한다. 

7. 디렉터리 인덱싱
  • 기본정의 : 불필요 파일로 인해서 web 구조를 파악하게 하는 것이다.
  • 해결방법 : 각 server 측 특성에 맞도록 인덱싱 기능을 제거해서 관리하도록 한다. 무엇보다 불필요 파일에 대해서 관리를 철저히 하도록 한다.

8. 프로세스 검증누락
  • 기본정의 : 기존 프로세스  흐름을 우회해서 처리가 가능하도록 한다.
  • 해결방법 : server side 검증 로직을 추가하거나 기존 단계에 대한 검증여부를 재차 확인한다. javascript 보다는 server 에서 처리를 하는쪽을 권장한다.

9. 정보누출
  • 기본정의 : 주요 정보 노출로 인한 2차 공격이 가능해진다.
  • 해결방법 : server 설정을 변경하거나 jsp, javascript, json 등의 처리를 할 때 표시되는 정보를 삭제하거나 마스킹 처리를 하도록 한다.

9가지 항목은 위와 같다.. 그런데 해당 교육을 받으면서 아쉬움이 좀 있었다면, 실제 업무에서 사용하고 있는 소스의 일부분을 발췌해서 대응 방안을 보여줬으면 어떨까 싶다..

물론 같이 일하는 개발자들이 각자의 소스에 맞게끔 수정해서 적용하고 사용하고 있긴 하지만 예시가 너무 틀에박힌 샘플성이 아니었으면 하는 마음이었다.. 그럼 조금이나마 집중도가 올라가지 않았을까..??..

또한, 교육이 끝난 후 개인적으로 질문을 한 것이 있었다.. 근데 머가 떨린다고 그렇게 어버버 했는지 모르겠다.. 이놈의 울렁증.. ㅡ;;ㅡ 무튼.. 질문의 요는 "취약성에 대해서 유틸화 해서 각 인스턴스마다 각자 사용하고 있는데 그 유틸 파일에 대한 최신화를 업체에서 해주거나 검증이 가능한가..??" 였다..

위와 같은 질문을 한 배경을 간단히 얘기하자면 과거에 XSS 취약성 문제로 기본적으로 되어있던 유틸 파일을 통해서 수정을 했었다.. 그런데 나중에 추가 보안 요청을 해온 이유중에 하나가 요즘에는 어떠어떠한 부분도 필터링에 포함이 되어야 하는데 그 부분이 누락되었다는 것이다.. 그래서 질문을 한 것이다.. 혹시나 하면서..

솔직히 기대를 안하고 한 질문이긴 한데 어떤 대답이 나올지 짐작이 되기 때문이었다.. 그런데 역시나 답은 이러했다.. "현 상황을 알고는 있으며, 최신화를 통한 공통화를 시킬까 했지만 현 상황으로는 안된다" 라고 말이다..

답변을 해주신 분에게 감정이 있거나 혹은 서운하거나 그러진 않았다.. 다만 해당 회사 뿐 아니라 모든 회사들이 보안이 어쩌고 21세기가 어쩌고 미래를 어쩌고 IT 선진화 등등 보기 좋은 말은 그렇게들 하면서도 정작 내부적으로 작은 프로세스 혹은 유틸 등 무엇인가를 바꾸기엔 대중에게 내놓는 슬로건과는 거리가 있다는게 아쉬울 뿐이었다..

그 간격이 조금이라도 빠른 시일내에 좁혀지길 바랄 뿐이다..

[Book] 구글러가 전하는 IT 취업 가이드..

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

구글러가 전하는 IT 취업 가이드 - 8점
게일 맥도웰 지음
강은진 옮김
인사이트

이 책은 The Google Resume: How to Prepare for a Career and Land a Job at Apple, Microsoft, Google, or any Top Tech Company의 번역서입니다. 제목에 Google이라는 타이틀이 딱 붙어있지만 부재에도 붙어있듯이 구글 취업가이드 같은건 아니고 내용도 딱히 구글 입사에 특화되어 있는 것은 아닙니다.  제목에서 알 수 있듯이 이는 취업가이드이고 꼭 개발자에만 한정된 것은 아니고 IT 업계에 대한 포괄적인 취업가이드를 제시해주고 있습니다. 물론 저자가 개발자 출신이라 개발자에 대한 얘기가 다수있기는 합니다. 이 책의 저자는 구글, 애플, MS를 다닌 후 Careercup을 창업한 게일 맥도웰인데 취업에 대한 다양한 식견을 가지고 있어서 도움이 많이 됩니다.

이 책은 취업에 대한 전체적인 내용을 다루고 있습니다. 취업을 준비할 때 어떤 것을 고민해야하는 지부터 해서 이력서작성을 할 때 어떤 부분을 고려해야 하는지, 면접은 어떻게 해야하는지를 자세히 설명하고 취업이 결정난 후 거절하게 되면 어떻게 해야하는지와 실제 일하면서 장래를 위해서 어떤 고민을 하면서 일해야 하는지를 설명해 주고 있습니다. 각 장에는 실제 저자에게 질문이 들어온 구체적인 사례에 대한 답변들도 나와있습니다. 어찌보면 상당히 뻔한 내용을 설명한다고 느껴질 수도 있지만 구체적으로 왜 그런 답변이 좋고 어떤 마음가짐으로 고민해야 하는지를 설명해 주면서 예시답변도 보여주기 때문에 취업을 준비하는 사람들이라면 상당히 도움이 될 듯 합니다.

다만 번역서이기 때문에 일부는 국내에서는 적용되지 않습니다.
예를 들어 국내에는 전화면접같은 것이 존재하지 않습니다. 혹 어딘가 있을지도 모르지만 땅이 넓은 세계 도처에 있는 구직자때문에 해외에는 전화면접이 존재하지만 국내에서는 한번도 본 적이 없습니다. [요 근래 보니 naver 에서는 전화면접을 시행하더란..] 또한 이 책에서는 강력히 추천하지만 이력서를 쓸 때 커버레터라는 것을 따로 작성하는 것도 본 적이 없습니다. 그 외에도 여기서는 이력서를 한페이지 혹은 두페이지로 줄이라고 하지만 회사 취향에 따라 다르겠지만 국내에서는 이정도로 적은 양을 적지는 않습니다. 그렇기 때문에 구체적인 절차에 대해서 너무 연연하는 것은 좋지 않아보입니다. 경력직이라면 책을 읽으면서 국내에 적용되는 것과 아닌 것을 구별할 수 있겠지만 신입이라면 어느게 맞는 말인지 헷갈릴 수도 있겠습니다. 그런 판단을 하기 어렵다면 구체적 형식보다는 마음가짐이나 자세쪽에 더 초점을 맞춰서 보시는 게 좋을듯 합니다.

읽으면서 내용이 참 좋다고 느껴졌습니다. 일단 번역이 꽤 좋습니다. 이 책에는 예시로 모범 이력서 예시나 답변 예시등이 나와있는데 이런 부분은 단순히 내용 전달뿐만 아니라 문장의 자연스러움이나 세련됨도 필요하기 때문에 번역투로 번역되었다면 책의 가치가 상당히 떨어졌을 것입니다. 제가 사람을 뽑고그러는 레벨은 아니라서 얼마나 좋은 글인지는 판단하기 어렵지만 문장이 어색하게 느껴지지는 않습니다. 취업이란 건 신입때뿐만 아니라 일을하면서 지속적으로 필요하고 여기서 말하는 내용은 사실 취업때뿐만 아니라 일을 하는 도중에도 참고할 만한 내용들이 있기 때문에 이런 쪽에 능력이 좋지 않다면 참고할만 합니다.


My Comment..
음.. 햄이 좀 바쁘게 쓴 글인가 싶다.. 항상 햄의 Book Story 를 보면, 읽지 않아도 이게 어떤 책이고, 무엇을 논하고, 무엇을 배울 수 있다라는 감이 단번에 왔는데.. 이번에는 좀 아닌듯하다.. 물론, 어느 정도 책의 성격은 파악이 되지만, 과거 햄이 올렸던 책 후기에 비해서 조금 빠진다는 것이다.. 딴지는 아니공 그냥 내 생각.. ㅋㅋ

[EP]"TDD 실천법과 도구 2년 뒤" 모임 후기..

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

지난 6월 27일에 있었던 모임이니 2주도 지났지만 휴가도 갔다오고 하다 보니 이제야 정리합니다.(너무 지나서 귀차니즘에 건너뛸까도 생각했습니다만...)

이 책은 너구리님이 2년 전에 쓰신 테스트 주도 개발 : 고품질 쾌속개발을 위한 TDD 실천법과 도구가 출간할 때 베타리더 등으로 참여했던 사람들을 대상으로 너구리님이 책을 쓰고 2년이 지나면서 달라진 생각, 지금의 생각 등을 공유하기 위해서 만든 자리였습니다. 사실 어떤 시나리오가 있는 세미나가 아니라 너구리님이 자신의 생각을 공유하면서 자유롭게 토론을 하는 분위기였기에 정리하기가 쉽지 않지만 대충 임의로 정리해 봅니다. 여러 사람들이 얘기를 나누어서 누가 말씀하셨는지는 다 기억하기 어려워서 생략합니다.

잘 안된다...
책을 쓰고 2년이 지나면서 배운 점은 TDD가 잘 안된다는 점이라고 하셨습니다. 다른 사람을 설득하려고 했지만 결과적으로 잘되지 않았고 이게 원래 안되는게 아닐까라는 생각이 들었습니다. 과거 CBD(Component-Based Development)가 실패했던 이유에 대해서 많은 얘기가 오갔었는데 그 당시에 CBD가 필요한 상황이 없었거나 받쳐줄 기술이 제대로 갖추어지지 않았으며 장사꾼(?)들이 개입하면서 왜곡되기 시작했고 CBD로 무엇을 하는가에는 관심이 없고 무엇을 얻는가에 너무 집중되어 있었다는 얘기가 있었습니다.(전 CBD는 잘 몰라서....) 어떤 인식이 공유안된 상태에서 새로운 것을 도입하는 것은 상당히 힘들다는 것에 대부분 공감하는 것 같았습니다.

너구리님은 약간 회의적인 시각으로 보셨지만 반대 의견들도 있었습니다. TDD가 실패라면 반대로 성공은 무엇인가를 정의하는 것은 어렵고 OOP도 성공했다고 말하기에는 많은 반론이 있을 것입니다. 이런 면에서 재능이 포터블한가?에 대해서 생각해 볼 수 있는데 시도는 많이 하지만 대부분 잘 되지 않고 이동하는 순간 효과가 확 떨어지는 결과가 대부분입니다. 그럼에도 믿음이 의지력을 만든다고 생각하기 때문에 된다고 믿으면 실제로 되고 안된다고 믿으면 실제로 안될 수 있습니다.

왜 안되는가?
기술이 받쳐주지 못해서 못하는 경우는 거의 없고 실제로도 하는 사람들은 다 TDD를 하고 있습니다. 하지만 시도와 중요도를 기준으로 했을 때 자꾸 뒤로 밀리는 경향이 있습니다. 외견상의 현상만 봤을 때는 문제가 무엇인지를 알지 못하거나 개발자들이 변화를 계속해서 시도하지 않는 문제가 있고 밥 아저씨처럼 "참 쉽죠~"해서 신기했지만 감동도 잠깐이고 어렵고 커버리지 압박등으로 재미도 없는 것 같다는 얘기도 있었습니다.

어떻게 하면 잘 할 수 있는가?
이건 어찌 보면 어떻게 하면 개발을 잘 할수 있는가의 문제입니다. 한가지 방법은 TDD를 잘하는 사람을 관찰하는 것입니다. 너구리님은 일단 TDD를 한다고 했습니다.(책의 저자이기도 하니...) 협력업체 직원같은 경우는 그냥 원래 그렇게 하는거라고 하면 대부분 잘 따라온다고 합니다. 오히려 위험한 사람이 우리 팀에서 가장 잘하는 개발자입니다. [이 부분에 대해서 상당히 공감을 한다.. 나도 현재 협력직? 계약직? 입장인데 어차피 새로운 업무를 맡거나 정규직이 이렇게 해주시고, 어떤 패턴으로 해주세요 라고 요청을 하면, 그 업체에 맞게끔 해주는게 맞기 때문에 조금은 불편하거나 생소하더라도 오히려 기존 세력?? 보다 더 쉽게 받아들이는건 맞는 듯 하다..] 이런 개발자는 보통 코드가 어려운 데다가 테스터블하지 않은 코드도 뛰어난 능력으로 테스트코드를 만들어버리기도 하기 때문에 이런 개발자의 TDD를 보고 배우는 건 위험합니다.

2년동안 보니 다음과 같은 조건의 사람들이 TDD를 잘 합니다.

  • TDD의 경험이 있는 사람(장점을 기억하고 있는 사람)
  • Divide and Conquer를 잘하는 개발자
  • 협동작업을 잘하는 개발자
TDD를 잘 하려면 설계를 먼저하고 given / when / then 템플릿(이건 정말 최고!)이 정말 많은 도움이 됩니다. 그리고 TDD를 연습시키려면 다음과 같은 과정으로 진행하는게 좋아보입니다.
  1. 계획하기
  2. 확인할 방법 생각해보기
  3. 실행하기
  4. 기능 요구사항이 명학한지 확인하기
  5. 머리속으로 단계를 그려보기
  6. 종이에 적어보기
  7. 단계별로 확인할 방법을 생각해 보기
  8. 코딩 시작
코딩을 하면서 "지금 작성하는 코드에서 테스트를 작성할 수 있는 가장 간단한 것은 무엇인가?"라는 질문을 계속 던져야 합니다.

책을 쓸 때와는 달라진 생각들
많은 개발자가 Mock에 흥미를 가지지만 대부분의 경우 Mock으로 불필요한 코드들이 생기게 된다.
짝 프로그래밍은 TDD에도 많은 도움이 된다. 짝 프로그래밍에 대해서도(이것도 엄청나게 큰 하나의 주제이므로) 많은 얘기가 오갔는데 짝 프로그래밍에는 소셜 스킬이 중요하다는 얘기가 나왔습니다. 물론 이는 짝이 같은 가치관을 가지고 있지 않으면 짝 프로그래밍이 무척 어렵다는 얘기부터 시작된 것이지만 가치관이 다른 경우 소셜스킬로 해결할 수 있다는 얘기로 이어졌습니다.(이 얘기가 더 맞는듯 합니다.) 대부분 짝 프로그래밍을 가르칠 때 소셜 스킬을 가르치지 않기 때문에 문제가 발생하는데 중요한 사건들은 화면이 아니라 두 사람 사이에서 발생합니다. 그래서 김창준님은 짝 프로그래밍을 조언할 때 화면이 아니라 짝 프로그래밍을 하는 두 사람을 촬영해서 가져오기를 요구한다고 했습니다. 그래서 프로그래밍이 아닌 두 사람간의 문제가 생긴다는 것을 미리 알려주지 않으면 짝 프로그래밍을 하면서 당황하기 때문에 어떤 상황이 생길 수 있고 어떻게 해결해야 하는지 얘기해 주어야 한다고 했습니다.

그리고 이런 얘기를 하는 가운데 김창준님이 don't는 약한 표현이기 때문에 don't를 얘기할 때는 do를 함께 얘기하는게 좋다고 하셨는데 이부분이 꽤 인상적이 었습니다. ~~를 하지 마라만으로 부족하고 대신 ~를 해라까지 나아가는게 좋다는 것이지요. 그리고 대부분은 문제를 감지할 수 있는 방법을 알려주는 것 좋은데 if()로 상황을 주어도 그 조건을 대부분을 감지해 내지 못한다는 얘기셨습니다. 그래서 구체적으로 문제를 감지할 수 있는 방법까지 알려주는게 좋다는 얘기였습니다. [이 부분도 공감이 되는 글귀다.. 햄이 표현하고자 하는 혹은 김창준 님이란 분이 말씀하시는게 내 생각과 의미가 통하는지는 모르겠으나.. 어떤 부분에 대한 문제를 지적 혹은 알려만 주는 것보다는 왜 그렇게 되었는지 혹은 이 부분으로 인해서 어떻게 되고, 해결법에는 어떠한 좋은 것이 있다고 알려주거나 힌트를 주는게 좋다고 생각한다.. 사람들이 가장 큰 실수를 하는 것이 설명을 할 때 자신이 알기 때문에 상대도 알것이라고 생각하고 생략을 하는 것이 많다.. 또한, 본인은 문제점을 간파했기 때문에 당연히 이 사람이 어떻게 조치를 하겠지.. 라고 생각을 할 수 있지만, 상대방이 그것을 알았다면 애초에 지적을 받지 않았을 것이다.. 조금만 더 상대를 배려?? 또는 풀어서 설명해주는 습관이 모두에게 중요하다고 생각이 든다..]


Image by cobalt123 via Flickr

내 생각....
일단 저는 TDD가 실패(?)했다고 생각하지 않는 쪽입니다. 실제로 TDD를 해보면 재미있기도 하지만 때때로 무척 귀찮을 때도 상당히 존재하는데 실제 프로덕션레벨로 나가면 또 상황이 달라지는 것 같습니다. 실배포전에 수정한 내용의 오류르 테스트케이스로 발견했을 때(물론 이는 TDD가 아니라 나중에 유닛테스트를 만들어도 같지만 그냥 뭉뚱구려 얘기합니다.) 테스트케이스를 작성한 보람을 느끼게 됩니다.

또 한편 이게 오픈소스나 공개소스로 넘어가면 얘기가 또 완전히 달라지게 됩니다. TDD는 좀 귀찮기도 하다는 생각을 한다고 하더라도 어떤 오픈소스를 가져다 쓸 생각을 하면 테스트코드가 얼마나 잘 작성되어있는가가 주요한 판단 기준이 되며 소스를 오픈소스로 제공한다고 생각하면 제 코드의 신뢰성을 증명하는데 테스트케이스 만한 것은 없습니다. 실제로 오픈소스 프로젝트들을 보면 대부분 테스트케이스를 작성하고 있으면 코드를 수정해서 제출하더라도 테스트코드를 같이 제출해야 하는 경우가 대부분입니다. 이런 면에서 TDD는 꽤 많이 자리 잡았다고 생각합니다.

암튼 마지막 정리하면서 의견을 낼 때 아직 너무 어려워서 더 쉬워져야한다. 라는 얘기가 있었습니다. 이 말이 제 머릿속에 오래 머물렀었는데 어려운 게 사실이고 그런식으로 생각해 보진 않았기 때문입니다. 많은 프렉티스가 공유되고 정보가 많아지면서 이전보다 쉬워지긴 했지만 여전히 어려운 것은 사실입니다. 하지만 더 쉬워져야 한다에는 공감하지만 쉬워질 수 있는가?에 대해서는 회의적입니다. 다른 얘기를 하면 건강을 유지하려면 음식을 조절해야 하고 운동을 규칙적으로 하고 잠을 충분히 자야합니다. 물론 그렇게 하는 사람도 있지만 직장생활을 하면서 음식조절을 하고 규칙적으로 매일 운동해서 건강하고 좋은 몸은 유지하는 것은 쉽지 않은 일입니다.(그래서 대부분 배가 나오죠.) 그럼에도 건강해 질 수 있는 지름길 같은 것은 존재하지 않고... 운동안하고 먹고싶은거 다 먹으면서 건강하고 날씬한 몸을 유지할 수 있는 방법도 없습니다. 많은 사람이 운동을 규칙적으로 못한다고 잘못된 방법이라고 생각하지도 않습니다. 비슷한 이치가 아닐까요? 좋은 소프트웨어를 만드는 것은 원래 어려운 일이고 여기에 은총알이나 지름길 같은 건 없습니다. 더 많이 생각하고 더 많이 해보고 하는 거지요.(머 그런의미로 이날의 논의가 이뤄졌다고 생각하진 않지만요.)

머 요즘은 그냥 할 수 있는 범위 내에서는 TDD를 해보려고 노력하면서 기술적인 부분에만 관심을 가지고 근본적인 내용에 대해서 고민해 적은 별로 없었습니다. 그냥 노력해야 할 것으로만 생각했을 뿐이지요. 간만에 TDD에 대해서 그 의미에 대해서 많은 생각을 해보고 의견을 들어볼 수 있는 좋은 모임이었습니다. 그리고 너구리님의 엄청난 인맥으로 이날에는 한자리에 모이기 힘든 대단하신 개발자들이 많이 모였는데 끝나고 생각해 보니 단체사진이라도 하나 찍을걸 그랬다는 아쉬움이 남더군요. ㅎ


My Comment..
이 글은 내가 TDD 를 해본적도 없고 햄의 블로그를 통해서 알게 된 것이기에 갖고 올까 고민을 하였다.. 머 언제나 그렇듯이 나에게 있어서 좀 애매한 글들은 고민을 하게 되고 읽어본 후 결정을 한다.. 그래서 역시나 이 글도 읽어보고, 내가 TDD 를 한 것은 아니지만, 나름 공감가거나 내가 하고 싶은 말도 떠오르게 되서 갖고 왔다.. 언어의 영역은 틀리지만, 어느정도 공통성이 있는 것처럼 최초의 주제는 내가 모르는 것일지라도 결국 IT 내에서 일어나는 일들이거나 프로세스이기에 공감가는 부분이 있는 듯 하다..

[Book] 시간을 요리하는 뽀모도로 테크닉..

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

시간을 요리하는 뽀모도로 테크닉 - 8점
스타판 뇌테부르 지음
신승환 옮김
인사이트

이 책은 제목처럼 뽀모도로 테크닉에 대한 책입니다. 뽀모도로 테크닉은 처음 얘기를 들었을 때 이름이 참 특이하다는 생각을 했었는데 작년에 이 책이 나온 뒤에 제 주위에서 뽀모도로를 적용해서 효과를 보는 사람들이나 시도를 해보는 사람을 많이 보게 되서 관심은 약간 있었지만 이제야 읽게 되었습니다.

자기관리를 하는 방법론이 많이 존재하고 있습니다. 스티븐 코비의 성공하는 사람들의 7가지 습관에 나온 방법이라던가 GTD(Getting things done)등이 있습니다. 저 같은 경우에는 GTD의 변형(?)을 사용하고 있다고 할 수 있는데 뽀모도로는 이러한 방법론과는 약간 다른 접근방법을 가지고 있습니다. 간단히 말하면 다른 접근법이 자신이 할일을 어떻게 잊지않고 체계적으로 관리할 수 있는가에 집중하고 있다면 뽀모도로는 실행에 상당히 초첨을 맞추고 있습니다. 그래서 다른 할일 관리 방법과 섞어서 사용할 수도 있습니다.

뽀모도로 테크닉의 규칙은 상당히 간단한데 25분을 1 뽀모도로로 해서 한번에 한가지 일만을 합니다. 1 뽀모도로가 끝나면 5분을 쉬고 다시 뽀모도로를 합니다. 뽀모도로를 할 때는 타이머를 두어서 뽀모도로를 시작할 때는 항상 타이머를 돌리고 타이머가 돌때는 보통 소리가 나는 등의 효과가 있습니다. 이는 마치 파블로프의 개처럼 조건 반사효과를 주어 타이머를 돌리거나 소리에 반응해서 집중하게 합니다.  간단한 규칙은 이것이 전부이고 그 외에 쉬는 시간마다 다음 뽀모도로의 할 일을 다시 판단하고 방해받는 경우에는 따로 표시하면서 진행하고 다 끝나면 회고를 합니다.

이 책은 이 뽀모도로를 설명하고 있습니다. 책이라고는 하지만 글이 많지 않아서 금방 볼 수 있고 꽤 재미있게 볼 수 있습니다. 이 책에서는 뽀모도로가 필요한 이유와 뽀모도로로 인해서 어떤 효과를 가져올 수 있는지 설명하고 있는데 상당히 설득력이 있고 간단한 규칙을 통한 효과이기 때문에 더 효과가 있어 보입니다. 실행할 때 다양한 대처에 대해서 설명해 주기 때문에 집중을 잘 못하거나 할일관리를 잘 못한다면 이 책을 한 번 읽어보면 좋을 듯 합니다.

앞에서 얘기했듯이 GTD로 할일을 관리하고 있는데 사실 아주 잘 된다고 할 수는 없습니다. 항상 그렇듯이 할일의 우선순위를 정한다는 것이 쉬운일은 아니고 하다보니 시간이 지날수록 할일은 쌓이고 제대로 관리가 되지 않습니다. GTD도 실행에 꽤 초점이 맞추어져 있다고 생각했었지만 뽀모도로에 비한다면 실행에 대한 초점은 훨씬 못하다고 생각하기에 뽀모도로를 잘 활용한다면 효과를 볼 수 있으리라 생각합니다. 물론 이런 류의 실천법은 개개인의 차이가 있기 때문에 연습하고 적용해보아야 실질적인 효과를 알 수 있고 여러가지 시도를 해본 뒤에 뽀모도로를 평가하는 것이 아닌 책을 읽고 평가하는 차원에서 뽀모도로를 얘기하기는 빠른 감도 있습니다. 하지만 책을 읽어보고 나니 주위 사람들이 말하던대로 괜찮아보이고 뽀모도로를 읽으면서 내내 애자일같은 실용적이고 효과적인 것 같아 충분히 시도해볼 가치가 있어 보입니다.



[Book] Play Framework Cookbook 한국어판..

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

Play Framework Cookbook 한국어판 - 6점
알렉산더 릴젠 지음
박재성 옮김
에이콘출판

자바의 경량 프레임워크 중 하나인 Play Framework의 쿡북입니다. 플레이 프레임워크를 처음 만져봤던 것은 2009년이었었는데 그 뒤에 많이 만져보지는 못했지만 상당히 매력적인 프레임워크로 알아야 할 엄청난 기술스택과 초기 셋팅에 대한 비용이 많이 드는 대부분의 자바프레임웍에 비해서 자바의 레일즈프레임워크 같은 느낌이 드는 프레임워크입니다. 간단한 페이지는 정말 순식간에 만들 수 있고 별다른 설정없이도 변경한 자바코드가 핫스왑으로되기 때문에 상당히 개발을 즐기면서 코딩을 할 수 있습니다.

이 책은 플레이 프레임워크의 1.x대 중 최신인 1.2.4를 기준으로 작성되어 있습니다. 현재는 2.0.1이 나와있기는 하지만 2.x부터는 설계부터 새로 했고 Scala에 상당히 친화적으로 기술 스택이 달라지면서 1.x때와는 많이 느낌이 다른 것으로 알고 있습니다.(2.x는 아직 못 써봤습니다.) 그래서 2.x가 나오기는 했지만 아직 1.x를 그대로 쓰고 있는 곳도 많기에 아직 이 책이 다루는 내용은 유효하다고 할 수 있습니다.

제목에 나와있듯이 이 책은 쿡북입니다. 그래서 난이도의 차이는 있지만 실무에서 사용할 법한 여러가지 상황별로 예제를 들어가면서 설명하고 있습니다. 다시 말해 플레이 프레임워크의 입문서가 아니라 최소한 플레임워크는 사용해 보았고 어느정도 사용하고 있는 개발자들이 더 다양하게 사용해 볼 수 있도록 하는데 타겟팅이 되어 있습니다. 아직 국내에는 플레이프레임워크가 많이 보급되지 않았고 그런 가운데 플레이 프레임워크의 책이 나온 것은 환영할 만하지만 입문서없이 쿡북이 먼저 나온데는 약간 아쉬움이 있습니다.(물론 그래서 역서에는 첫 장에 플레이 프레임워크의 설치부분을 할당했고 가이드 문서만 보면 웹사이트정도 올리는 것은 금방할 정도로 진입장벽인 낮은 프레임워크라고 생각합니다.)

각 부분은 여러 가지 실무에서 활용할 만한 사례별로 나누어져 있고 요구사항에 대한 약간의 설명 후에 구현한 예제 코드를 보여주고 예제에 대한 설명이 나오고 이서서 해당 상황에 대해서 참고할 만한 정보를 알려주는 방식으로 모든 설명이 이어집니다. 예제에 대한 설명이 아주 자세한 정도까지는 아니라고 느껴지지만 완전 입문서를 타게팅하는 것은 아니기 때문에 코드와 같이 보면서 이해할 만한 수준이라고 생각합니다. 그리고 상당수의 예제는 테스트코드를 먼저 작성하고 예제를 작성하고 있기 때문에 실무에서 테스트코드를 작성하는 것을 참고하는데도 도움이 될 듯 합니다.

저는 플레이 프레임워크의 기능을 좀 파악한다는 생각으로 죽~ 보기는 했지만 쿡북이므로 플레이 프레임워크로 개발을 하면서 유사한 상황의 사례에 대해서 참고하면서 본다면 꽤 도움이 될 만합니다. 총 400여 페이지로 분량이 좀 되기 때문에 기본적인 부분부터 컨트롤러, 모듈에 까지 꽤 광범위하게 다루고 있습니다.



[JAVA]5장 리소스 #2..

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

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

5.6 의존성으로써의 Resources
빈 자체가 어떤 동적인 과정을 통해 리소스 경로를 결정하고 제공할 것이라면 빈에 리소스를 로드하는데 ResourceLoader 인터페이스를 사용하는 것이 합리적일 것이다. 사용자의 역할(role)에 의존하는 특정 리소스가 있는 어떤 템플릿을 로딩하는 예제를 생각해 보자. 리소스가 정적이라면 ResourceLoader 인터페이스의 사용을 완전히 제거하고 빈이 필요한 Resource 프로퍼티를 그냥 노출해서 주입되도록 하는 것이 합리적이다.

이러한 프로퍼티 주입을 대수롭지 않게 만드는 것은 모든 어플리케이션 컨텍스트가 String 경로를 Resource 객체로 변환할 수 있는 특별한 자바빈 PropertyEditor를 등록하고 사용하는 것이다. 그래서 myBean에 Resource 타입의 템플릿 프로퍼티가 있다면 다음처럼 해당 리소스에 대한 간단한 문자열로 설정할 수 있다.


1
2
3
4
5
Xml

<bean id="myBean" class="...">
  <property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>

이 리소스 경로는 접두사가 없으므로 어플리케이션 컨텍스트 자체가 ResourceLoader로 사용되기 때문에 리소스는 컨텍스트의 정확한 타입에 의존하는 (적절한) ClassPathResource, FileSystemResource, ServletContextResource를 통해서 로드될 수 있다.

특정 Resource 타입을 사용하도록 강제해야 한다면 접두사를 사용할 수 있다. 다음 두 예제는 어떻게 ClassPathResource와 UrlResource를(후자는 파일시스템의 파일에 접근하는데 사용한다.) 강제할 수 있는지 보여준다.


1
2
3
4
5
6
7
Xml

<property name="template" value="classpath:some/resource/path/myTemplate.txt">

Xml

<property name="template" value="file:/some/resource/path/myTemplate.txt"/>

5.7 어플리케이션 컨텍스트와 Resource 경로
5.7.1 어플리케이션 컨텍스트 생성
(특정 어플리케이션 컨텍스트 타입에 대한) 어플리케이션 컨텍스트 생성자는 보통 컨텍스트의 정의를 구성하는 XML 파일같은 리소스의 위치 경로로 문자열이나 문자열의 배열을 받는다.

이 러한 위치 경로에 접두사가 없을 때 특정 Resource 타입은 해당 경로에서 만들어지고 특정 어플리케이션 컨텍스트에 의존적이고 적절한 빈 정의를 로드하는데 사용한다. 예를 들어 다음처럼 ClassPathXmlApplicationContext를 생성한다면


1
2
3
Java

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

빈 정의는 ClassPathResource처럼 사용될 클래스패스에서 로드될 것이다. 하지만 FileSystemXmlApplicationContext를 생성한다면

1
2
3
Java

ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");

빈 정의는 이 경우에 현재 워킹디렉토리에서 상대적인 파일시스템 위치에서 로드될 것이다.

위치경로에 특별한 클래스패스 접두사나 표준 URL 접두사를 사용하면 정의를 로드하려고 생성한 Resource의 기본 타입을 오버라이드할 것이다. 그래서 이 FileSystemXmlApplicationContext...


1
2
3
Java

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");

... 클래스패스에서 해당 빈 정의를 실제로 로드할 것이다. 하지만 이는 여전히 FileSystemXmlApplicationContext이다. 이어서 ResourceLoader를 사용한다면 접두사가 없는 어떤 경로도 여전히 파일시스템 경로로 다룰 것이다.

5.7.1.1 ClassPathXmlApplicationContext 인스턴스 생성하기 - 단축키(shortcuts)
ClassPathXmlApplicationContext 는 편리한 인스턴스화를 할 수 있도록 다수의 생성자를 노출한다. 기본 아이디어는 하나만 XML 파일 자체의 파일명을(경로 정보없이) 담고 있는 문자열 배열을 제공하고 Class도 또한 제공한다. ClassPathXmlApplicationContext는 제공된 클래스에서 경로 정보를 얻을 것이다.

예제가 이를 명확하게 해줄 것이다. 다음과 같은 디렉토리 레이아웃을 생각해 보자.


1
2
3
4
5
6
7
C-like

com/
  foo/
    services.xml
    daos.xml
    MessengerService.class

ClassPathXmlApplicationContext 인스턴스는 다음처럼 인스턴스화될 수 있는 'services.xml'와 'daos.xml'에 정의된 빈들로 구성되어 있다.

1
2
3
Java

ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}, MessengerService.class);

다양한 생성자에 대한 자세한 내용은 ClassPathXmlApplicationContext 클래스의 Javadoc을 참고해라.

5.7.2 어플리케이션 컨텍스트 생성자 리소스 경로에 와일드카드 사용하기
어 플리케이션 컨텍스트 생성자 값의 리소스 경로들은 (위에서 본 것처럼) 타겟 리소스에 일대일로 매핑되는 간단한 경로일 수도 있지만 "classpath*:"같은 접두사나 내부적으로 Ant 스타일의 정규표현식(스프링의 PathMatcher 유틸리티의 사용과 일치하는)을 포함할 수도 있다. 후자의 두 경우는 사실상 와일드카드이다.

어플리케이션은 컴포넌트 스타일로 조립하는 것이 이 메카니즘의 한가지 용도이다. 모든 컴포넌트들을 알고 있는 위치경로로 켄텍스트 정의 조각을 배포할 수 있고 classpath*:로 접두사가 붙은 같은 경로를 사용해서 최종 어플리케이션 컨텍스트를 생성할 때 모든 컴포넌트 조각들을 자동으로 선택할 것이다.

이 와일드카드는 어플리케이션 컨텍스트 생성자(또는 PathMatcher 유틸리티 클래스 계층을 직접 사용할 때)의 리소스 경로의 사용을 지정하고 생성시에 처리한다. 이는 Resource 타입 자체는 아무것도 하는 것이 없다. 리소스가 단순히 한번에 하나의 리소스만 가르키는 것처럼 실체 Resource를 생성하는 classpath*: 접두사를 사용하는 것은 불가능하다.

5.7.2.1 Ant 스타일의 패턴
예를 들어 다음처럼 위치 경로가 Ant 스타일 패턴을 포함하고 있을 때


1
2
3
4
5
6
C-like

/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml

... 리졸버는 복잡하지만 와일드카드를 처리하려고 정의되어 있는 정차를 따른다. 리졸버는 마지막의 와일드카드가 아닌 부분의 경로로 Resource를 생성하고 그로부터 URL을 획득한다. 이 URL이 "jar:" URL이나 컨테이너가 지정한 변형(예를 들어 WebLogic의 "zip:"나 WebSphere의 "wsjar" 등)이 아니라면 java.io.File를 URL에서 획득하고 파일시스템을 탐색해서 와일드차드를 처리한다. jar URL일 경우에 리졸버는 URL에서 java.net.JarURLConnection를 얻거나 와일드카드를 처리하기 위해 수동으로 jar URL을 파싱해서 jar파일의 내용을 탐색한다.

이식성의 영향(Implications on portability)
지정된 경로가 이미 파일 URL이라면(명시적이든 암묵적이든) 기반 ResourceLoader가 파일시스템이기 때문에 와일드카드가 이식성에서도 완전히 동작한다는 것을 보장한다.

지 정한 경로가 클래스패스라면 리졸버는 Classloader.getResource() 호출을 통해서 와일드카드가 아닌 마지막 경로 부분을 반드시 획득해야 한다. 이는 단순히 경로의 한 부분(결국 파일은 아니다)이므로 사실상 정의되지 않았고(ClassLoader Javadoc에서) 이 경우에 정확한 URL의 종류가 리턴된다. 실제로 이는 항상 클래스패스 리소스를 파일시스템 위치로 처리하는 디렉토리나 jar 위치로 처리하는 jar URL을 나타내는 java.io.File이다. 여전히 이 작업에서 이식성 이슈가 있다.

와 일드카드가 아닌 마지막 부분으로 획득한 jar URL을 획득했다면 리졸버는 URL에서 java.net.JarURLConnection를 얻거나 jar의 컨텐츠를 탐색할 수 있도록 jar URL을 수동으로 파싱해서 와일드카드를 처리할 수 있어야 한다. 이는 대부분의 환경에서 동작할 것이지만 몇몇 환경에서는 실패할 것이다. jar 리소스의 와일드카드 처리는 사용하기 전에 의존환경에 대한 완전히 테스트해 볼 것을 강력히 추천한다.

5.7.2.2 classpath*: 접두사
XML 기반의 어플리케이션 컨텍스트를 생성할 때 위치 문자열은 특수한 classpath*: 접두사를 사용할 것이다.


1
2
3
4
Java

ApplicationContext ctx =
    new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

이 특수한 접두사는 주어진 이름과 일치하는 모든 클래스패스 리소스들이 획득되어야 한다는 것을 가르키고 (내부적으로는 ClassLoader.getResources(...) 호출을 통해서 이뤄진다.) 최종 어플리케이션 컨텍스트 정의의 형식으로 합쳐진다.


Classpath*: 이식성
와 일드카드 클래스패스는 의존하는 클래스로더의 getResources() 메서드에 기반한다. 최근의 어플리케이션 서버 대부분은 자신만의 클래스로더 구현체를 제공하므로 이 동작은 jar파일을 다룰 때 특히 다를 것이다. classpath*가 동작하는 지 확인하기 위한 간단한 테스트는 클래스패스의 jar 내에서 파일을 로드하도록 클래스로더를 사용하는 것이다: getClass().getClassLoader().getResources("<someFileInsideTheJar>") 이 테스트를 이름은 갖지만 다른 두가지 위치에 있는 파일로 시험해봐라. 적절하지 않은 결과가 나온 경우에 클래스로더의 동작을 조정할 수 있는 세팅과 관련해서 어플리케이션 서버의 문서를 확인해라.

"classpath*:" 접두사는 위치 경로의 다른 부분에서 PathMatcher 패턴과 조합할 수도 있다. 예를 들면 "classpath*:META-INF/*-beans.xml"처럼 사용할 수 있다. 이 경우에 처리 전략은 아주 간단하다. ClassLoader.getResources() 호출은 클래스 로더 계층에서 일치하는 모든 리소스들을 얻기 위해 마지막 와일드카드가 아닌 경로 부분을 사용하고 각 리소스를 빼와서 위에서 설명한 같은 PathMatcher 처리 전략을 와일드카드 하위경로에 사용한다.

5.7.2.3 와일드 카드와 관련된 추가적인 내용
"classpath*:"를 Ant 스타일 패턴과 조합해서 사용할 때는 실제 타겟 파일이 파일시스템에 존재하는냐와 상관없이 패턴이 시작하기 전에 최소한 하나의 루트 디렉토리가에서만 확실하게 동작할 것이다. 이 말은 "classpath*:*.xml" 같은 패턴은 jar 파일의 루트에서 파일을 획득하는 것이 아니라 확장된 디렉토리의 루트에서 획득한다는 의미이다. 이는 (검색할 잠재적인 루트를 가르키는) 전달된 빈 문자열에 대해서 파일 시스템 위치만 리턴하는 JDK의 ClassLoader.getResources() 메서드의 제한에서 비롯된 것이다.

"classpath:"를 가진 Ant 스타일 패턴의 리소스는 검색할 루트 팩키지가 여러 클래스 경로에서 있을 경우 일치하는 리소스를 찾는다는 보장을 하지 않는다. 이는 다음과 같은 리소스 때문이다.


1
2
3
C-like

com/mycompany/package1/service-context.xml

딱 한 위치에만 있을 것이지만 경로가 다음과 같은 경우

1
2
3
C-like

classpath:com/mycompany/**/service-context.xml

경로를 처리하려고 시도하면 리졸버는 getResource("com/mycompany")가 리턴한 URL을 (먼저) 없앨 것이다. 이 기반 패키지 노드가 여러 클래스로더 위치에 존재한다면 실제 최종 리소스는 최하단에 존재하지 않을 수 있다. 그러므로 이러한 경우에는 차라리 루트 패키지를 포함하는 모든 클래스 경로를 검색하도록 같은 Ant 스타일 패턴과 "classpath*:"를 사용해라.

5.7.3 FileSystemResource의 주의사항
FileSystemApplicationContext에 소속되지 않은 FileSystemResource(즉 FileSystemApplicationContext는 실제 ResourceLoader가 아니다.)는 기대한 것처럼 절대경로 대 상대경로로 다룰 것이다. 상대 경로는 현재 워킹디렉토리의 상대경로이고 절대경로는 파일시스템의 루트의 상대적인 경로이다.

하지만 하위 호환성(역사적인) 때문에 FileSystemApplicationContext가 ResourceLoader일 때는 달라진다. FileSystemApplicationContext는 간단하게 모든 붙은(attached) FileSystemResource 인스턴스가 경로가 슬래시로 시작하던지 아니던 지에 상관없이 모든 위치경로를 상대적으로 다루도록 한다. 사실 이는 다음 두 가지가 같다는 것을 의미한다.


1
2
3
4
5
6
7
8
9
Java

ApplicationContext ctx =
    new FileSystemXmlApplicationContext("conf/context.xml");

Java

ApplicationContext ctx =
    new FileSystemXmlApplicationContext("/conf/context.xml");

다음 두 가지도 같다.(한 경우는 상대경로이고 다른 경우는 절대경로인 것처럼 다른 것이 당연하다고 하더라도)

1
2
3
4
5
6
7
8
9
Java

FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");

Java

FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");

실제로 진짜 파일시스템 절대경로가 필요하다면 FileSystemResource / FileSystemXmlApplicationContext와 함께 절대경로를 사용하는 것은 삼가하는 것이 더 낫다. 그리고 그냥 file: URL 접두사를 사용해서 UrlResource의 사용을 강제해라.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Java

// 실제 컨텍스트 타입과는 상관없이 Resource 는 항상 UrlResource가 될 것이다
ctx.getResource("file:/some/resource/path/myTemplate.txt");

Java

// UrlResource로 해당 정의를 로드하는데 이 FileSystemXmlApplicationContext을 사용하도록 강제한다
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("file:/conf/context.xml");

[JAVA]5장 리소스 #1..

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

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

5. 리소스
5.1 소개
자바의 표준 java.net.URL 클래스와 다양한 URL 접두어들에 대한 표준 핸들러는 안타깝게도 저수준 리소스에 모두 접근하기에는 전혀 충분하지 않다. 예를 들면 클래스패스나 ServletContext에 상대경로에서 얻어와야 하는 리소스에 접근하려고 사용할 표준화된 URL 구현체가 없다. 전문화된 URL 접두사(http:같은 접두가에 대한 핸들러가 존재하는 것처럼)에 대한 새로운 핸들러를 등록할 수 있기 때문에 이는 보통 꽤 복잡하고 URL 인터페이스는 리소스의 존재여부를 확인하는 메서드같은 몇가지 기대하는 기능이 여전히 부족하다.

5.2 Resource 인터페이스
스프링의 Resource 인터페이스는 저수준 리소스 접근을 추상화한 더 기능이 많은 인터페이스이다.


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

public interface Resource extends InputStreamSource {
    boolean exists();
    boolean isOpen();
    URL getURL() throws IOException;
    File getFile() throws IOException;
    Resource createRelative(String relativePath) throws IOException;
    String getFilename();
    String getDescription();
}

Java

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

다음은 Resource인터페이스에서 가장 중요한 메서드들이다.


  • getInputStream(): 리소스의 위치를 찾고 오픈한 뒤 리소스를 읽기 위한 InputStream를 리턴한다. 호출할 때마다 새로운 InputStream를 리턴한다. 스트림을 닫는 것은 호출한 쪽에 책임이 있다.
  • exists(): 해당 리소스가 물리적인 형태로 실제 존재하는지 나타내는 boolean을 리턴한다.
  • isOpen(): 해당 리소스가 오픈 스트림을 가진 하나의 핸들을 나타내는 지를 가르키는 boolean을 리턴한다. 이 값이 true이면 InputStream는 여러번 읽을 수 없고 반드시 오직 한번만 읽은 뒤에 리소스 누출을 피하기 위해 닫아야 한다. InputStreamResource 예외를 가진 모든 일반적인 리소스 구현체에서는 false가 될 것이다.
  • getDescription(): 리소스로 작업할 때 오류 출력에 사용할 해당 리소스에 대한 설명을 리턴합니다. 이는 때로 정규화된 파일명이나 리소스의 실제 URL이다.
다른 메서드들은 리소스를 나타내는 실제 URL나 File 객체를 얻을 수 있게 한다.(기반을 이루는 구현체가 호환성이 있고 해당 기능을 지원한다면)

Resource 추상화는 리소스가 필요할 때 많은 메서드 시그니처에서 아규먼트 타입으로 스프링내에서 광범위하게 사용된다. 몇몇 스프링 API의 다름 메서드들은(다양한 ApplicationContext 구현체에 생성자같은) 간소화되고 간단한 형식으로 해당 컨텍스트 구현체에 적절한 Resource를 생성하는데 사용하거나 String 경로에서 특별한 접두사로 콜러(caller)가 생성하고 사용해야 하는 특정 Resource 구현체를 지정하도록 String을 받아들인다.

Resource 인터페이스는 스프링과 함께 또는 스프링에서 많이 사용되기 때문에 심지어 코드가 알지 못하는 엑세스에 접근하거나 스프링의 다른 부분에 관심이 있을 때 자신의 코드에서 단독으로 일반적인 유틸리티 클래스로써 사용하기에 실제로 아주 유용하다. 이는 코드를 스프링에 커플링하지만 URL에 대한 더 기능이 많은 대체제로 제공하는 이 작은 유틸리티 클래스 세트에만 실제로 커플링하고 같은 목적으로 사용할 다른 어떤 라이브러리에 대한 동일한 역할로 생각할 수 있다.

Resource 추상화가 기능을 교체하지 않는다는 것은 중요하다. 예를 들면 UrlResource는 URL을 감싸고 URL의 작업을 하는데 감싸진 URL를 사용한다.

5.3 내장된 Resource 구현체
스프링에서 혁신적으로 직접 제공하는 많은 수의 Resource 구현체가 있다.

5.3.1 UrlResource
UrlResource는 java.net.URL를 감싸고 일반적으로 URL로 접근할 수 있는 파일, HTTP 대상, FTP 대상 등과 같은 객체에 접근하는데 사용할 수 있다. 적절하게 표준화된 URL 접두사는 다른 타입에서 URL 타입을 가르키는데 사용는 것처럼 모든 URL은 표준화된 String로 나타낸다. 이는 파일시스템 경로에 접근하는 file:, HTTP 프로토콜로 리소스에 접근하는 http:, FTP로 리소스에 접근하는 ftp:등을 포함한다.

UrlResource는 자바 코드로 UrlResource 생성자를 사용해서 명시적으로 생성하지만 때로는 경로를 나타내는 String 아규먼트를 받아들이는 API 메서드를 호출했을 때 암묵적으로 생성될 것이다. 후자의 경우 JavaBeans PropertyEditor가 결국 어떤 타입의 Resource를 생성할 것인지를 결정할 것이다. 경로 문자열에 classpath:같은 어느정도 알려진 접두사가 있다면 해당 접두사에 적절한 Resource를 생성할 것이다. 하지만 접두사를 인식하지 못한다면 그냥 표준 URL 문자열이라고 가정하고 UrlResource을 생성할 것이다.

5.3.2 ClassPathResource
이 클래스는 클래스패스에서 얻어와야하는 리소스를 나타낸다. 이 클래스는 쓰레드 컨텍스트 클래스 로더, 주어진 클래스로더, 클래스를 로딩하려주 주어진 클래스를 모두 사용한다.

Resource 구현체는 클래스패스 리소스가 파일시스템에 존재하면 java.io.File같은 해결책을 지원하지만 jar에 존재하는 클래스패스 리소스는 지원하지 않고 파일시스템으로 확장하지도 않는다. 이를 다양한 Resource 구현체에 배치시키려면 java.net.URL같은 해결책을 항상 지원해야 한다.

ClassPathResource는 ClassPathResource 생성자를 사용해서 자바코드로 명시적으로 생성하지만 때로는 경로를 나타내는 String 아규먼트를 받아들이는 API를 호출할 때 암묵적으로 생성될 것이다. 후자의 경우 JavaBeans PropertyEditor이 문자열 경로에서 특수한 classpath: 접두사를 인식할 것이고 이 경우에 ClassPathResource를 생성할 것이다.

5.3.3 FileSystemResource
이는 java.io.File 핸들에 대한 Resource 구현체이다. 명백하게 File와 URL같은 해결책을 지원한다.

5.3.4 ServletContextResource
이는 관련된 웹 어플리케이션의 루트 경로내에서 상대 경로를 인터프리팅하는 ServletContext 리소스에 대한 Resource 구현체이다.

이는 항상 스트림 접근과 URL 접근을 지원하지만 웹 어플리케이션 아카이브가 확장되었고 리소스가 파일시스템에 물리적으로 있다면 java.io.File 접근만을 허용한다. 이처럼 파일시스템에 있거나 확장되었거나 JAR나 DB같은 다른 곳에서(생각해 볼 수 있는 곳이다.) 직접 접근했는가에 관계 없이 서블릿 컨테이너에 실제로 의존적이다.

5.3.5 InputStreamResource
주어진 InputStream에 대한 Resource 구현체이다. 이는 적용할 수 있는 특정 Resource 구현체가 없을 때만 사용할 수 있다.특히 ByteArrayResource나 파일 기잔의 어떤 Resource 구현체가 가능한 곳에서 더 선호한다.

다른 Resource 구현체와는 달리 이는 이미 오픈된 리소스에 대한 디스크립터(descriptor)이다. 그러므로 isOpen()는 true를 리턴한다. 리소스 디스크립터를 어딘가에 유지할 필요가 있거나 스트림을 여러번 읽어야 할 때는 사용하지 말아야 한다.

5.3.6 ByteArrayResource
주어진 바이트(byte) 배열에 대한 Resource 구현체이다. 이는 주어진 바이트 배열에 대한 ByteArrayInputStream를 생성한다.

일회용 InputStreamResource에 의지하지 않고 주어진 바이트 배열에서 컨텐츠를 로딩하는데 유용하다.

5.4 ResourceLoader
ResourceLoader 인터페이스는 Resource 인스턴스를 리턴(즉 로딩)할 수 있는 객체로 구현된다는 것을 의미한다.


1
2
3
4
5
Java

public interface ResourceLoader {
    Resource getResource(String location);
}

모든 어플리케이션 컨텍스트는 ResourceLoader 인터페이스를 구현하고 있으므로 Resource 인스턴스를 획득하는데 모든 어플리케이션 컨텍스트를 사용할 수 있다.

특정 어플리케이션 컨텍스트에서 getResource()를 호출하고 지정된 위치경로가 특정 접두사를 가지지 않았을 때 특정 어플리케이션 컨텍스트에 적절한 Resource 타입을 얻을 것이다. 예를 들어 ClassPathXmlApplicationContext 인스턴스에 대해 실행하는 다음의 코드가 있다고 해보자.


1
2
3
Java

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");

리턴되는 것은 ClassPathResource가 될 것이다. FileSystemXmlApplicationContext 인스턴스에 대해서 같은 메서드를 실행했다면 FileSystemResource를 얻을 것이다. WebApplicationContext에 대해서는 ServletContextResource를 얻는 등이다.

이처럼 특정 어플리케이션 컨텍스트에 적절한 방법으로 리소스를 로드할 수 있다.

반면에 classpath: 접두사를 지정함으로써 어플리케이션 컨텍스트 타입에 관계없이 ClassPathResource를 사용하도록 강제할 수도 있다.


1
2
3
Java

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");

비슷하게 표준 java.net.URL 접두사를 지정해서 UrlResource를 사용하도록 강제할 수 있다.

1
2
3
4
5
6
7
Java

Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");

Java

Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");

다음 표에 String을 Resource로 변환하는 전략을 요약했다.

Table 5.1. 리소스 문자열

접두사예제설명
classpath:classpath:com/myapp/config.xml클래스패스에서 로드한다.
file:file:/data/config.xml파일시스템에서 URL로 로드한다. [1]
http:http://myserver/logo.pngURL로 로드한다.
(none)/data/config.xml기반하는 ApplicationContext에 달려있다.
[1] 하지만 다음도 봐라. Section 5.7.3, “FileSystemResource의 주의사항”.







5.5 ResourceLoaderAware 인터페이스
ResourceLoaderAware 인터페이스는 ResourceLoader 참조와 함께 제공되기를 기대하는 객체를 식별하는 특별한 마커(marker) 인터페이스이다.


1
2
3
4
5
Java

public interface ResourceLoaderAware {
   void setResourceLoader(ResourceLoader resourceLoader);
}

클래스가 ResourceLoaderAware는 구현하고 어플리케이션 컨텍스트에 배포했을 때(스프링이 관리하는 빈처럼) 어플리케이션 컨텍스트는 클래스를 ResourceLoaderAware로 인식한다. 그 다음 어플리케이션 컨텍스트는 자신을 아규먼트로 전달하면서 setResourceLoader(ResourceLoader)를 호출할 것이다. (모든 스프링의 모든 어플리케이션 컨텍스트는 ResourceLoader 인터페이스를 구현했다는 것을 기억해라.)

물론 ApplicationContext가 ResourceLoader이기 때문에 빈은 ApplicationContextAware를 구현할 수도 있고 리소스를 로드하려고 제공된 어플리케이션 컨텍스트를 직접 사용할 수도 있다. 하지만 리소스를 로드하려는 목적이라면 전용 ResourceLoader를 사용하는 것이 더 낫다. 코드는 전체 스프링 ApplicationContext 인터페이스가 아니라 유틸리티 인터페이스로 고려될 수 있는 리소스 로딩 인터페이스에 그냥 커플링 될 것이다.

스프링 2.5에서 ResourceLoaderAware 인터페이스를 구현하는 대신에 ResourceLoader의 자동연결에 의존할 수 있다. "전통적인" constructor와 byType의 자동연결 모드는 (Section 4.4.5, “협력객체의 자동연결(Autowiring)”에서 설명했듯이) 이제 생성자 아규먼트나 setter 메서드 파라미터 각각에 대해서 ResourceLoader 타입의 의존성을 제공하는 기능이 있다. 더 유연하게 하려면 (필드와 다중 파라미터 메서드를 자동연결하는 것을 포함해서) 새로운 어노테이션 기반의 자동연결 기능의 사용을 고려해봐라. 이 경우에 ResourceLoader는 필드나 생성자 메서드에 @Autowired 어노테이션이 붙어있으면 ResourceLoader 타입을 기대하는 필드나 생성자 아규먼트, 메서드 파라미터에 자동연결 될 것이다. 더 자세한 내용은 Section 4.9.2, “@Autowired”를 봐라.


[UFC]코너 맥그리거 은퇴라니..

어제는 개인적인 일로 하루 휴가였다.. 개인 업무를 보는 중 잉여시간이 생겨서 모바일 뉴스를 보는데 내가 잘못본건가..?? 싶은 뉴스를 봤다..

코너 맥그리거가 은퇴를 한다고 한다.. 격투기를 좋아하고, 즐겨보는 사람이라면 놀라지 않을 수 없는 뉴스이기도 하고 이건 완전히 뒷통수를 쎄게 맞은 느낌이다..

말이 되는가.. 그 동안 해온 업적도 많거니와 본인의 입지를 탄탄하게 다져오던 그였다.. 내가 보기에 지금 현재 종합격투기계에서 그만한 스타도 없다.. 그런데 갑작스럽게 은퇴라니.. 원래는 어제 포스팅을 하려고 했었다.. 하지만, 요새 웹 뉴스는 종종 잘못된 뉴스가 올라오곤 하기 때문에 그 사이 또 어떤 뉴스가 어떻게 올라올지 모르기에 잠시 기다려봤다..

그리고 오늘 아침 다시 봤지만, 역시나 은퇴가 맞는 듯하다.. 지금 현재 나오는 얘기 중 가장 유력한 이유가 되는 것은 자신의 팀 동료가 지난 경기에서 뇌에 충격을 받고 경기 후 사망을 한 사건이 있었다고 한다.. 그로 인해서 마음을 못잡는 것이 아닌가 싶은 부분이다..


코너 맥그리거. 사진=UFC 아시아
코너 맥그리거. 사진=UFC 아시아

난 그렇다고 해도 잠깐의 해프닝이길 바랬다.. 왜냐면 UFC 200 을 기다리고 있었고, 그만한 재미난 유쾌한 선수가 현재는 없다고 보기 때문이다.. 항상 그의 경기는 기대를 갖게끔하고, 지켜 보게끔 하기 때문이다.. 진짜 아쉽다..

과거 조르주 생 피에르[GSP] 가 본인의 건강과 여러 심경의 변화 그리고 UFC 의 정책등에 불만을 품고서 은퇴를 선언하고 지금은 일선에서 물러난 상태이다.. 하지만, 지금 분위기를 봐선 컴백을 준비중인 듯 하다..

코너 맥그리거도 그렇게 되길 빈다.. 지금이야 정신적인 충격 때문에 잠시 떠나 있더라도 다시금 돌아와서 흥미로운 경기들을 만들어주길 바란다..

다시 돌아와!! 코너 맥그리거!!!