[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...

2017년 1월 23일 월요일

[Talk] 조회수 30,000 돌파..


지난 금요일 조회 수가 꽤 올라오고 있어서 드디어 3만을 채우는건가 했는데 퇴근전까지 딱히 채워지질 않고 있었다.. 요새는 더욱이 조리원에서 거진 생활을 하다보니 집에서는 더더욱 컴퓨터를 못하고 있는 실정이다..

그리하여 오늘 출근하자마자 조회수부터 확인..!!! 왜냐공..?? 궁금하기도 하지만 업무가 들어오기전에 후딱 올려두려고.. ㅎㅎ.. 우선 아래 이미지부터 보자..










글 검색을 해보니 2만 조회를 넘어선 것이 8월 24일이었다.. 그로부터 딱 5개월정도 걸린듯하다.. 음.. 길다면 길고, 짧다면 짧은 시간인데.. 시간이 흘러 흘러 3만건을 조회한 것도 뿌듯하지만 그 시간동안 손에서 놓지 않고 꾸준히 해왔다는 것에도 뿌듯하다.. 물론 포스팅 수는 좀 줄긴 했지만 말이지..

근데 항상 이런 글을 적을 때마다 항상 부끄러운 부분이 있다.. 나 스스로 공부를 해서 적은 글보다는 절대적으로 포스팅을 갖고 온 것이 많기에.. 요즘에는 더욱 그런거 같기도 하고 말이지.. 흠냥..

그래도 이 허접한 블로그에 많이들 오셔서 조회도 해주시고 하는 인터넷 사용자분들에게 항상 감사드립니다.. 4만건이라는 조회수가.. 언제 채워질지는 모르겠지만 계속 꾸준할 수 있도록 노력해보자.. ㅎㅎㅎ..

올해는 햄의 글 언넝 마무리하고 내 글도 좀 올리자.. ㅠㅜ


2017년 1월 20일 금요일

[JS] JSHint의 옵션 정리..


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

JSHint는 자바스크립트 코드 검사도구이다. 컴파일언어가 아니다 보니 오류를 줄이거나 스타일 가이드를 위해서 이런 도구를 보통 사용하는데 이런 작업을 보통 Linting이라고 한다. 과거에는 더글라스 크록포드가 만든 JSLint를 대부분 쓰고 있었지만 JSLint가 현실에 맞지 않게 너무 엄격해서 JSHint가 등장하고 다른 Linting도구들이 많이 있지만, 일반적으로 JSHint를 가장 많이 쓰는 걸로 보인다.

자바스크립트를 사용할 때 거의 JSHint로 코드검사를 하고 있지만, 막상 필요할 때 그때그때 찾아서 해 버릇해서 딱 정해진 옵션을 가지고 있지도 않았고 잘 모르는 옵션이나 사용하는 옵션이더라도 어떤 내용을 검사해주는지 헷갈리는 경우가 많았다. 이는 이전의 JSHint의 문서화가 그렇게 좋지 못했던 이유도 있었는데 지금은 문서화도 어느 정도 되어 있고 매번 쓰다 보니 한번 정리해야 할 필요가 있다고 생각되어 옵션들을 정리해봤다. 간단히 어떤 옵션인지 내가 알아볼 수 있는 수준으로만 정리했으니 자세한 내용은 JSHint 문서를 참고하면 되고 좀 더 자세한 예제코드는 JSHint의 테스트코드에서 볼 수 있다.

금지(Enforcing) 옵션

아래의 옵션을 true나 특정 값으로 설정하면 JSHint가 해당 내용을 검사해서 더 많은 오류를 알려준다. (옵션을 지정하지 않으면 false로 설정한 것과 같다.)
  • bitwise: ^(XOR), | 같은 bit연산자를 금지한다.
  • camelcase: 변수를 카멜케이스(혹은 UPPER_CASE)로 강제한다(이름은 카멜케이스이지만 var testvar Test모두 가능하다.)
  • curly: if 문이나 while 문 등 중괄호({})를 생략해도 되는 곳에서 중괄호를 강제한다.
  • eqeqeq: 비교문에서 == != 대신 === !== 를 사용하도록 강제한다.
  • es3: 구형브라우저를 위해서 es3 명세를 사용한 경우에 필요하다.
  • forin: for-in 루프를 사용할 때 반드시 필터링을 사용하도록 강제한다. for (var key in obj) 식의 루프에서 프로토타입 체인을 사용한 키를 다 순회하므로 일반적으로 if (obj.hasOwnProperty(key)) {} 같은 조건문을 두는데 이러한 필터링이 없을 경우(꼭 hasOwnProperty여야 하는 건 아니다.) 오류가 나오도록 한다. (루프문안에 다른 실행문이 없으면 무시한다.)
  • freeze: Array, Date, String 같은 네이티브 객체의 프로토타입을 덮어쓸 수 없도록 막는다. Array.prototype.count = function() { }; 와 같이 사용하는 경우 오류 메시지가 나온다.
  • immed: var a = function() {}(); 와 같이 함수를 바로 실행하는 경우 함수를 괄호로 감싸도록 강제한다. 이는 가독성을 높이기 위함이다.
  • indent: 들여쓰기 크기를 정하고 숫자로 지정한다.
  • latedef: 변수를 사용하는 하는 부분 뒤에 정의하는 것을 금지한다. 자바스크립트는 hoisting 때문에 같은 스코프에서 나중에 선언된 변수를 앞에서 사용할 수 있는데 이 부분을 차단한다는 의미이다.
  • newcap: new로 생성자 함수를 사용할 때 대분자로 시작하도록 강제한다. new animal(); 대신 new Animal(); 와 같이 사용해야 한다.
  • noarg: 최적화가 어려워 폐기될 예정인 arguments.caller arguments.callee 의 사용을 막는다.
  • noempty: for (var i=0;i < 10;i++) { } 와 같이 for문 등에서 빈 블록을 금지한다.
  • nonew: new Animal(); 같은 생성자함수의 실행결과를 다른 변수 등에 할당하지 않고는 사용할 수 없게 한다.
  • plusplus: ++, -- 같은 단항연산자를 금지한다.
  • quotmark: 문자열 등에 사용하는 따옴표의 스타일을 강제한다. true 로 지정하면 쌍따옴표, 홑따옴표를 모두 쓸 수 있지만 섞어서 사용할 경우 오류가 나고 single 은 홑따옴표 double 는 쌍따옴표를 강제한다.
  • undef: 선언되지 않은 변수를 사용하면 오류가 발생한다.
  • unused: 변수를 선언하고 사용하지 않으면 오류가 발생한다.
  • strict: 함수에 ECMAScript 5의 strict mode를 강제한다. 이 옵션은 함수범위에만 강제하고 전역 strict mode는 허용하지 않는다.
  • trailing: 라인 끝에 불필요한 공백문자가 들어가면 오류가 발생한다.
  • maxparams: 값을 숫자로 지정하고 함수에서 파라미터의 최대 개수를 지정한다.
  • maxdepth: 제어문의 최대 중첩개수를 지정한다.
  • maxstatements: 한 함수내의 사용할 수 있는 최대 스테이트먼트 개수를 지정한다.
  • maxcomplexity: 코드의 사이클매틱 복잡도(cyclomatic complexity)를 지정한다.
  • maxlen: 한 라인의 최대 길이를 지정한다.

완화(Relaxing) 옵션

아래 옵션을 true 로 설정하면 더 적은 오류를 보여준다.
  • asi: 세미콜론이 빠졌을 때 발생하는 오류를 보여주지 않는다.
  • boss: if (a = 1) 처럼 비교문이 와야 할 곳에 할당문이 올 때 발생하는 오류를 보여주지 않는다.
  • debug: debugger; 문을 코드에 사용했을 때 발생하는 오류를 보여주지 않는다.
  • eqnull: == null 비교에 대한 오류를 보여주지 않는다.
  • esnext: ECMAScript 6 문법을 사용을 허용한다.
  • evil: eval 을 사용했을 때 발생하는 오류를 보여주지 않는다.
  • expr: 함수 호출이나 할당문이 아닌 표현식에 대한 오류를 보여주지 않는다. 주로 테스트에서 true.should.be.ok; 같은 표현식을 사용할 때 필요하다.
  • funcscope: if (true) { var a = 1; } 처럼 제어문 내에서 변수를 정의하는 경우 발생하는 오류를 보여주지 않는다. 자바스크립트는 펑션스코프를 사용하므로 동작에는 이상이 없지만, 오류를 발생할 여지가 있으므로 이 방법을 권장하지 않는다.
  • globalstrict: ECMAScript 5의 strict mode를 전역으로 사용하는 것을 허용한다.
  • iterator: __iterator__ 프로퍼티 사용에 대한 오류를 보여주지 않는다.
  • lastsemic: 한 줄짜리 블록에서 마지막 세미콜론이 빠진 경우에만 오류를 보여주고 블록 내부 등에서 세미콜론을 사용하지 않은 경우에는 오류를 보여주지 않는다.
  • laxbreak: 코드에서 안전하지 않은 줄 바꿈에 대한 오류를 보여주지 않는다. 이 오류는 콤마를 앞에 쓰는 형식에 대한 오류도 보여주지 않는데 이 경우에는 laxcomma를 사용해야 한다.
  • laxcomma: 객체 리터럴등에서 콤마를 앞에(마지막이 아니라) 쓰는 형식을 허용한다.
  • loopfunc: 루프 안에서 함수를 정의하는 경우 발생하는 오류를 보여주지 않는다.
  • moz: 모질라의 자바스크립트 확장 문법(JavaScript 1.7)을 사용하도록 허용한다.
  • multistr: \를 사용해서 문자열을 여러 라인에 걸쳐서 사용하는 경우 발생하는 오류를 보여주지 않는다.
  • notypeof: typeof 의 값을 비교할 때 typeof 의 값이 아닌 값과 비교하는 경우 발생하는 오류를 보여주지 않는다.
  • proto: __proto__ 프로퍼티 사용에 대한 오류를 보여주지 않는다.
  • scripturl: <a href="javascript:"> 처럼 스크립트를 타켓으로 한 URL(javascript:)에 대한 오류를 보여주지 않는다.
  • smarttabs: 탭과 스페이스를 섞어서 사용하는 경우 발생하는 오류를 보여주지 않는다.
  • shadow: 이미 선언된 변수를 재선언해서 발생하는 variable shadowing에 대한 오류를 보여주지 않는다.
  • sub: obj['key'] 대신 .을 사용하는 표기법을 권장하는 오류를 보여주지 않는다.
  • supernew: new function () {} new Object; 처럼 잘못 작성했을 가능성이 있는 생성자에 대한 오류를 보여주지 않는다.
  • validthis: strict 모드로 동작할 때 생성자가 아닌 함수에서 this를 사용하는 것에 대한 오류를 보여주지 않는다.

환경

아래 옵션을 JSHint가 전역 변수들을 미리 정의하도록 한다.
  • browser: 최신 브라우저들의 document, navigator 같은 전역 변수를 정의한다. 이 옵션은 console, alert 은 노출하지 않는다.
  • couch: CouchDB의 전역변수를 정의한다.
  • devel: console, alert 등 개발용으로 사용하는 전역 변수/객체를 정의한다.
  • dojo: Dojo의 전역변수를 정의한다.
  • jquery: jQuery의 전역변수를 정의한다.
  • mootools: MooTools의 전역변수를 정의한다.
  • node: Node.js환경에 맞도록 브라우저 환경에만 어울리는 오류는 무시하고 Node.js에 맞는 전역변수를 정의한다.
  • nonstandard: escapeunescape처럼 표준은 아니지만, 범용적으로 쓰이는 전역변수를 정의한다.
  • phantom: PhantomJS에서 동작하는 환경에 맞는 전역변수를 정의한다.
  • prototypejs: Prototype의 전역변수를 정의한다.
  • rhino: Rhino 환경에 맞는 전역변수를 정의한다.
  • worker: Web Worker 환경에 맞는 전역변수를 정의한다.
  • wsh: Windows ScriptHost 환경에 맞는 전역변수를 정의한다.
  • yui: YUI의 전역변수를 정의한다.

레거시 옵션

아래 옵션들은 폐기되어서 앞으로는 제거될 예정이다. 사용하지 마라.
  • nomen: 변수의 앞이나 뒤에 언더스코어(_)를 사용한 경우 오류가 발생한다.
  • onevar: 함수 안에 var 선언을 하나만 해야 한다.
  • passfail: 이 옵션을 사용하면 첫 오류나 경고에서 멈춘다.
  • white: JSHint가 더글라스 크록포드(Douglas Crockford)의 코딩 스타일가이드에 따라 코드를 검사하도록 한다.

My Comment..
음.. 노상 JS 를 쓰면서도 실질적으로 이런 코드 검사를 해주는 도구가 있는줄은 몰랐다.. 끽해야 F12 를 통한 브라우저 자체제공 도구를 사용하는정도가 다였는데 말이지..

역시 햄 블로그를 찬찬히 보다보면 새로운 것들을 많이 알게 되는 것 같다.. 나 스스로도 정리하고 새로운것을 알아보고 해야되는데.. 아흠.. 그것까진 솔직히 잘 안된다.. ㅎㅎㅎ..

[UFC] UFC 마감뉴스..


출처 : SPOTV NEWS























[Book] 심플은 정답이 아니다..

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

심플은 정답이 아니다 - 6점
도널드 노먼 지음
이지현 외 옮김
교보문고

인지과학의 대부인 도널드 노먼 교수의 책으로 난 UX에도 관심있고 디자인에도 관심(관심만..)은 있지만 UI나 UX를 설계하는 업무가 주업은 아니기 때문에 이쪽에 대한 사전지식이 깊지 않은 가운데 읽었기 때문에 읽고 받아들이는 수준도 그리 높지는 않았다.(이쪽도 점점 관심을 더 깊게 가져야 해서...) 디자인(웹에 대한 얘기도 나오지만 전체적으로는 모든 분야를 다루고 있다.)에서 단순함을 추구하는 경향가운데 단순함과 복잡함을 어떻게 봐야하는지를 자세히 설명하고 있다. 웹사이트들에 대한 얘기도 좀 나오긴 하지만 전체적으로는 길이나 건물, 길거리등 다양한 사례를 들면서 설명하고 있어서 이해하기가 어렵지는 않고 설명이 좋아서인지 너무 당연하게 느껴질 정도이다.(평소에는 이렇게 생각하기 어렵겠지만.) 이 책을 읽으면서 왠지 Martin Odersky의 Simple or Complicated?이라는 글이 생각났다.

우리가 사용하는 제품들이 복잡하므로 "단순하게 만들어라"라는 해결책이 그럴듯해 보이지만 실제 단순한 제품에 대해서 사람들은 "핵심" 기능이 없다고 불평한다는 것이다. 여기서 사람들이 생각하는 단순함이란 좋아하는 모든 기능이 들어있으면서 버튼 하나로 조작할 수 있는 단순함을 의미하는데 이는 불가능하다고 보는 것이 맞다다. 사람들이 향샹된 기량과 쉬운 사용을 원한다고 이를 더 많은 기능, 단순한 디자인으로 생각해서는 안되고 사람들이 정말 원하는 것은 이해하기 쉬운 제품이다. 그래서 인간 중심 디자인의 핵심은 복잡한 도구를 최적화하고 이해가 쉽고 즐거운 제품으로 바꾸어 복잡함을 길들이는 것이다.

사람들은 단순함을 원하지만 많은 멋진 기능을 포기하고 싶어하지도 않는다. 그래서 너무 단순하면 금세 지루해지고 너무 복잡하면 혼란스러우므로 결국 사람들은 중간 수준의 적절한 복잡함을 원하게 된다. 단순함은 복잡함의 반대가 아니다. 복잡함은 세상의 모습이고, 단순함은 마음의 상태다. 그래서 기술을 길들이는 것은 물리적인 문제가 아니라 심리적인 문제이다.

아무리 똑똑하고 의도가 좋더라도 엔지니어와 프로그래머는 기계의 관점에서 바라볼 수밖에 없고 평범한 사용자들이 아니다. 엔지니어들이 기계에 더 높은 지능을 주려고 노력하고 있지만 지금 상황에서 신경써야 할 것은 지능이 아니라 매너이고 이 책임은 디자이너에게 있다. 그래서 당황스런 사용자 행동에 대해서 짜증을 내기 보다는 이런 반응을 유도한 자신의 사회성을 반성해야 한다. 인간중심 디자인과 사회적 디자인에는 그 사물을 이용하는 사람이 진정으로 필요로 하고 원하는 것을 고려해 그들에게 도움을 줘야 한다는 철학이 깔려 있다. 한때는 "디자인"이 외관을 가리키던 적이 있었지만 지금은 좋은 상호작용이 좋은 디자인의 중요한 요소중 하나가 되었다. 그래서 내가 가진 디자인 원칙 중 하나는 오류 메시지를 없애서 오류가 아니라 도움이 필요한 상황으로 간주하고 스스로 설명할 수 있게 하는 것이다.

복잡함을 단순하게 만드는 가장 좋은 방법은 핵심 문제에 대한 개념을 새로 세우는 것이다. 디자인적 사고란 가장 먼저 진짜 문제가 무엇인지를 규정하는 것이다. 나는 이를 두고 "클라이언트가 해결해 달라고 하는 문제는 절대로 해결하지 마라"고 바꾸어 말한다. 클라이언트는 증상에만 반응하기 때문이다. 모든 과정에서 가장 어려운 일이기도 하면서 디자이너가 가장 먼저 해야 할 일은 정말로 해결되어야 하는 문제가 무엇인지를 찾는 것이다.

2017년 1월 19일 목요일

[Talk] 드디어 만나다.. 쥬니어 탄생..


약 3일동안 휴가를 보내고 왔다.. 하지만 이 휴가는 온전히 나를 위한 것은 아니었다..

기다리고 기다리던 리보를 만났다.. 일전에 2세에 대한 얘기를 살짝 언급한 적이 있었다.. 무튼.. 리보가 누구냐구..?? 나의 2세.. 쥬니어다.. 10여개월이란 시간이 언제 지나지..?? 라고 생각했는데 지나고보니 엄청 빨리 스쳐간듯하다..

처음 출산이기도 하지만 유도분만을 해야되기 때문에 자연분만 못하면 어떻게하나 걱정을 많이 했다.. 자연분만이 안되면 자연스럽게 수술을 선택 해야되겠지만 여자 스스로에게도 자연분만을 하는 것이 회복하는 것도 그렇고 여러면에서 좋기에 기왕이면 자연분만을 하기를 바랬는데 조금 고생은 했지만 자연분만을 하게 되었다.. 길.. 고생해숑.. >_<//

그렇게 우여곡절 끝에 만나게 된 우리 리보.. 출산 소식을 듣고 탯줄을 자르러 들어갔는데 그게 참.. 신기하긴 했지만 감동이라던지 울음이라던지 그런 것 보다는 멍~~~~~~ 했었다.. 그리고 이어지는 선생님의 "아빠 여기 탯줄 가운데 잘라주세요.." 라는 말씀을 듣고서 그제서야 정신 차리고서 잘랐다..

탯줄 자르자마자 난 바로 간호사분들과 나가서 애기의 건강상태.. 즉, 발가락, 손가락이 다 있는지.. 귀는 정상인지.. 잘 우는지.. 호흡은 정상인지 등등 을 확인하고서 신생아실로 같이 갔다.. 거기서 또 유의사항을 듣고서야 난 와이프 곁으로 갔다..

지금은 조리원에 있는 와이프와 리보.. 마냥 신기하다.. 신기하면서도 나름 또 걱정이 많이 들게 된다.. 애기에 대해서 조심스럽다보니 조금의 변화도 걱정이되고, 건강하게 잘 자랐으면 하는 마음에 불안함도 함께 오는 듯 하다.. 무엇보다 리보가 20살이 될즘에는 내나이는.. 헉..;; 앞으로 돈을 어떻게 그때까지 벌어야 된담.. 무엇을 하는게 좋을까.. 흠..;;

난 솔직히 내가 엄청난 재능이 있는 것은 아니기에 리보에게 무엇을 바라기보단 건강하게만 잘 자랐으면 좋겠다.. 내가 아빠라는 위치가 되었다니.. 아직도 여전히 실감이 오질 않는다.. 그래도 열심히 또 살아봐야지..

우리 리보.. 앞으로 잘해보자규..!!!

2017년 1월 10일 화요일

[JAVA] multipart는 HTTP POST로만 전송해야 한다..

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

작업을 하다가 multipart/form-data 로 PUT 전송을 할 일이 생겼다. 예를 들어 일반적인 회원가입 폼을 생각해 보면 회원가입시에는 /signup 에 POST로 폼 전송을 하지만 회원 가입 후 회원정보를 갱신한다고 생각하면 /user/{id} 에 PUT 전송을 하는게 요즘은 일반적이다. 완전히 REST를 다 따르진 않다고 하더라도 /user/edit?userId=1 과 같이 사용할 수도 있지만 요즘은 RESTful하게 작성하는 것이 어느 정도 보편화되었고 리소스중심으로 URI를 가져가면 여러 모로 더 깔끔해 지는 장점도 있다.

어쨋든 이러한 회원 가입 시나리오에서 회원정보에 이미지같은 파일이 있기 때문에 폼 전송을 multipart/form-data 로 하면서 PUT으로 하게 된 것이다. 뭘 개발하냐에 따라 다르겠지만 요즘은 input[type='file'] 보다는 파일을 업로드하는 컴포넌트를 따로 써서 폼전송과 별도로 업로드 하는 게 더 일반적이기 때문에 multipart/form-data 자체를 사용한지가 좀 오래되었다. 스프링 웹MVC를 사용하는 환경이었는데 브라우저에서 폼 전송을 하다보니 바로 PUT 전송을 하는 것이 아니라 메서드 오버라이드를 이용해서 POST전송을 하면서 <input type="hidden" name="_method" value="PUT"> 을 이용해서 PUT으로 처리되도록 사용하고 있었는데 스프링 웹MVC가 이를 PUT으로 인식하지 않고 계속 POST로만 인식하고 있었다. 스프링은 이를 HiddenHttpMethodFilter가 처리하는데 이 처리가 제대로 되지 않았다.(물론 multipart/form-data 가 아니면 정상적으로 동작한다.)

추적해 본 결과 CommonsMultipartResolver Apache Commons FileUpload사용하는데 ServletFileUpload의 isMultipartContent 소스를 보면 다음과 같이 POST로 하드코딩이 되어 있다.


1
2
3
4
5
6
7
8
Java

public static final boolean isMultipartContent(HttpServletRequest request) {
  if (!POST_METHOD.equalsIgnoreCase(request.getMethod())) {
    return false;
  }
  return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
}

일단 multipart/form-data 로 넘어왔으므로 HiddenHttpMethodFilter 가 쿼라파라미터를 제대로 판단하지 못했고 멀티파트는 아예 POST만 받도록 처리하게 되어 있었다. 도움을 받아서 이를 우회할 수 있도록 일단 처리는 했지만 POST로 하드 코딩되어 잇는 이유가 궁금했다. 듣보잡 라이브러리도 아니고 아파치 커먼즈 라이브러리에서 POST만 받도록 처리한데는 이유가 있을것 같아서 원인을 찾기 시작했다.

검색으로는 잘 나오지 않았기 때문에(대부분은 "_method 인풋을 히든으로 만드세요"라는 답변이거나 좀 더 찾으면 PUT을 인식할 수 있게 리졸버를 작성하라는 내용이 전부였다.) FileUpload 라이브러리의 이슈를 찾아가니 isMultipartContent가 PUT을 지원하지 않는다라는 이슈가 있었다.
Roy T. Fielding added a comment - 07/Mar/13 06:25
PUT means the sent representation is the replacement value for the target resource. A server could certainly support that functionality using any container format, it wouldn't be "normal" to use a MIME multipart, nor is it expected to be supported by the file upload functionality defined for browsers in RFC1867.
If you want to PUT a package, I suggest defining a resource that can be represented by an efficient packaging format (like ZIP) and then using PUT on that resource to have the side-effect of updating the values of its subsidiary resources.
대충 번역하자면
PUT은 대상 리소스의 값을 교체한다는 의미이다. 서버는 어떤 컨테이너 포맷이라도 사용해서 이 기능을 반드시 구현해야 하는데 여기서 포맷은 보통 multipart MIME을 사용하지 않고 RFC 1867에 따라 브라우저도 파일 업로드 기능으로 지원하지 않는다.
PUT으로 패키지를 올리기 원한다면 패키지 포맷(zip같은)을 나타내는 리소스를 정의하고 해당 리소스의 값을 갱신하는 리소스에 PUT을 사용해야 한다.
이 글이 달리고 내용이 정리되어 해당 이슈는 닫혔는데 여기서 댓글을 단 Roy T. Fielding은 HTTP 스펙을 작성한 사람중의 하나이면서 아파치 HTTP 서버를 만든 사람이기도 하고 REST를 최초로 만든 그 로이 필딩이다! 이견없이 한번에 이해가 됐다. "아~ PUT으로 multipart를 보내면 안되는 거구나." 그러니까 PUT은 특정 리소스를 갱신하는 역할을 하는데 multipart로 보내면 한번에 여러 리소스를 처리하므로 이미지 같은 경우를 PUT으로 처리하려면 이미지등에 대한 리소스 URI에 별도의 PUT 요청을 보내서 갱신하고 일반적인 폼은 따로 처리하라는 의미이다. 스펙에 빠삭하지 못해서 정확치는 않지만 이 경우에는 한 URI로 PUT을 보내서 여러 리소스(회원 정보 + 이미지)를 한꺼번에 처리하려고 했으므로 PUT이 적합치 않다는 의미로 보인다.

UI를 당장 파일업로드별로 따로 처리할 수 없다보니(요즘은 다 이미지 같은건 따로 처리하는데 이게 꼭 Rich한 UI를 가지기 위한 것만은 아님을 알 수 있었다.) POST로 처리해버렸다.

My Comment..
쓸일이 아주 많지는 않지만 무엇보다 대부분 그냥 있던 것을 생각없이 쓸 때가 많았다.. 그냥 되던 것을 붙여서 그것이 동작하도록 하고는 나중에 살펴봐야지..?? 하곤 누구나..?? 그렇듯이 그냥 지나치고 잊어버리기 때문이다..

물론 과거보다는 그래도 나름 정리하려는 습관을 갖으려고는 하지만 마음처럼 안되는게 현실이기도 하다.. 햄 덕분에 조금 더 깊이..?? 정확하게..?? 이해를 하게 된듯하다..

올해도 느낀다.. 사람은 항상 고민을 하고, 발전을 하려고 하고, 본인이 한 것들에 대해서 정리하고 기록하는 습관을 갖어야 된다는 것을 말이지..

But.. 뜻처럼 안되.. ㅠㅜ 흙..;;;;;

[Book] 코딩 호러의 이펙티브 프로그래밍..

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

제프 앳우드(Jeff Atwood)Coding Horror라는 유명 블로그를 운영하는 블로거이자 프로그래머로 우리같은 개발자들에게는 이제 너무 소중해진 스택오버플로우를 만든 사람 중에 하나이기도 하다. 보통 스택오버플로우하면 조엘 스폴스키가 사람들에게 더 잘 알려져있는데 제프 앳우드가 같이 만들었다.(만든 과정을 자세히 알지는 못하지만 이 책을 읽고 나면 실제 코딩은 제프 앳우드가 다 한듯하다.)

책 제목이 이펙티브 프로그래밍이라서 이펙티브 자바같은 성능좋은 프로그래밍 방법을 알려주는 책으로 생각할 수도 있는데 이 책은 그런 내용의 책은 아니다. 이 책의 원제는 Effective Programming: More Than Writing Code인데 책을 읽고 난 느낌은 부재인 More Than Writing Code 이 더 크다고 생각하는데 프로그래밍이라는 직업 자체에 대한 이야기들이 담겨있고 제프 앳우드가 자신의 블로그에 쓴 글을 모아서 책으로 엮은 것이다.

목차를 보면 대충은 무슨 내용일지 알 수 있지만 프로그래밍 혹은 개발자와 관련된 다양한 얘기가 모여있는 책이다. 프로그래밍에서 신경써야 하는 부분외에도 채용방법, 면접에 대한 생각들, 협업에 대한 얘기, 심지어 의자는 어떻게 고르고 일하는 곳의 조명은 어떻게 해야 하는가에 대한 얘기까지 나온다. 제프 앳우드가 블로그에 글을 오래 썼기 때문에 다양한 주제에 대한 많은 생각을 알 수 있고 번역도 괜찮아서 에세이를 읽듯이 재미나게 읽을 수 있다. 한 챕터에 몇페이지 되지 않고 내용이 계속 이어지는 것이 아니라서 읽기 쉬운 책이다. 뒷부분으로 가면서 서비스를 만드는 부분에 대한 얘기나 스택오버플로우를 만드는 것과 관련된 내용들이 나오는데 나는 이부분이 가장 재미있었다. 아무래도 스택오버플로우라는 사이트가 현재 가지는 위상은 물론이고 이러한 서비스를 만든 사람이 자신의 생각, 의도, 경험을 얘기해준다는 것은 아주 가치있기 때문에 도움될 내용도 많았고 몰랐던 스택오버플로우 얘기도 들을 수 있어서 좋다.

다음은 책을 읽으면서 인상적이었는 부분들...
진짜 프로그래머는 모든 시간을 코딩으로부터 나오는 가치를 창출하는데 보내는 사람이라고 생각한다. ...중략... 프로그래머가 되는 것은 돈과 관련 있는 것이 아니다. 프로그래밍은 어디까지나 열정에 대한 것이다.
다른 무엇보다 중요한 것은 바로 의사소통 능력이다. ...중략... 위대한 프로그래머는 다른 사람을 설득함으로써 영향력을 확대한다.
우리가 스택오버플로우에 참여하는 이유는 다음과 같다.
  • 우리는 프로그래밍을 사랑한다.
  • 우리는 다른 프로그래머들에게 길잡이 역할을 해주는 빵조각을 떨어뜨려서 그들이 우리가 저질렀던 것과 같은 우둔한 실수를 반복하지 않도록 만들고자 한다.
  • 동료를 가르치는 것은 어떤 일을 완전히 습득하기 위한 지름길이다.
  • 우리의 관심이 어느 쪽으로 향하든 그것을 따라갈 수 있다.
  • 작은 노력을 기울여서 커뮤니티를 집단적인 방식으로 더 나은 곳으로 만들고자 한다.
세상에는 이미 스택오버플로우 엔진을 복제한 사이트가 여럿 있다. 나는 그런 사이트들이 더욱 번성하길 바란다. 복제할 만한 가치가 있는 대상을 만들었다는 사실이 자랑스럽기 때문이다.
겸손한 프로그래머가 되는 방법의 핵심은 어떤 상황에 처하더라도 결국 모든 잘못의 뿌리는 자기가 작성한 코드라는 사실을 인정하는 것이다. 그것은 언제나 당신의 잘못이다. ...중략... 소프트웨어 개발자로서의 당신은 자기 자신의 가장 큰 적이다. 이 사실을 일찍 깨달을수록 더 휼륭한 프로그래머가 될 수 있다.
내가 보기에 아이디어는 실행되지 않는 한 아무 가치도 없다. 아이디어는 단지 증폭기 같은 것에 불과하다. 수백 만 달러의 가치가 있는 것은 실행이다.
커뮤니티 피드백의 90%는 쓰레기다 나머지 10%는 대단히 훌륭한 것들이다! 나는 당신이 그 10%에 도달하기 위해 100개 정도의 글을 읽을 수 있는 참을성을 가지고 있기만 하다면 모든 사람들을 위해 사이트를 더 나은 곳을 만들수 있는 황금과도 같은 글을 열 개 정도 발견할 것이라고 장담 할 수 있다.


2017년 1월 2일 월요일

[UFC] UFC 207 론다 로우지.. 이제 그만 떠나길 빈다..

지난 토요일 작년 마지막 이벤트인 UFC 207 이 있었다.. UFC 측의 마지막 이벤트이기도 하지만 이 경기가 특히나 관심이 있었던 이유는 세가지였는데.. 첫째는 김동현 출전 경기였고, 두 번째는 도미닉 크루즈 vs 코디 가브란츠 타이틀전, 마지막으로 핵심 이유였던 론다 로우지의 복귀전이자 타이틀 전 경기였다..

우선 김동현 선수의 승리를 축하한다.. 어려운 경기였지만 상황에 맞게 잘 대처했고, 침착했다고 생각한다.. 다만 경기 스타일은 좀 바꾸는게 좋다고 본다.. 그리고 도미닉 크루즈를 좋아하는 편이어서 응원했지만 코디 가브란트가 승리를 했는데 가브란트의 경기를 보면서 팬심이 생겼다.. 아주 흥미로운 선수고 앞으로 정말 기대 된다..

정말 중요한 경기는 바로 이 부분인데.. 아만다 누네즈 vs 론다 로우지 타이틀 전이다.. 나 뿐 아니라 대부분의 격투기 팬이라면 약 1년여만에 복귀를 하게 되는 로우지의 경기이기 때문에 더더욱 기대를 했을 것이고, 지켜봤을 것이다..

기본적인 경기전 내 생각은 로우지의 패배를 생각했다.. 과거 홀리 홈에게 패한 부분도 있지만, 로우지는 타격이 베이스가 아닌 선수다.. 올림픽에도 출전을 한 유도가이며, 본인의 캠프에 대한 변화도 없이 단순히 타격에 대한 감각이 훈련과 스파링만 통해서 변화될것이라고 보진 않았다.. 물론 흡수력이 빨라서 금새 바뀌는 선수도 분명 있다..

하지만 평생을 유도가로 살아온 로우지가 맞아본 적도 거의 는 로우지가 홀리 홈에게 진 후 1년 내내 타격 연습을 한 것도 아니고 영화도 찍고 기타 엔터적인 활동을 한 로우지가 누네즈를 이길 것이라고 생각은 안했다.. 다만, 영향력이 있었던 선수고 UFC 내에 여성 체급을 만들게끔 한 장본인이기에 그래도 기본 이상을 해주길, 버텨주길 바랬다..

위와 같은 기대를 하면서 경기를 보기 시작했는데 아뿔싸..;;; 1라운드 약 48초 만에 굴욕적인 패배를 당했다.. 48초라는 숫자도 중요하지만 로우지는 아무것도 한 것이 없었다.. 본인 입으로 그토록 연습했다던 타격..?? 전혀 없었다.. 타격 연습을 했다면 나와야 될 커버링..?? 속수무책으로 뚤렸다.. 그렇다면 유도가이니 클린치라도 하던지 머라도 되었어야 하는데 인간 샌드백이었다.. 저렇게 무기력하게 질 수 있는 것일까..?? 라는 생각을 들게 만든 한판이었다..


로우지는 경기가 끝난 후 "가장 찬란한 순간뿐만 아니라 가장 힘겨운 순간에도 나를 기다려준 팬들에게 고맙다는 말을 전하고 싶다. 여러분의 사랑과 성원이 내게 얼마나 큰 의미인지는 말로 표현하기 어렵다"고 그녀는 "나는 단지 싸우기 위해서가 아니라 승리하기 위해 돌아왔다"며, "하지만 때로는 모든 것을 쏟아 붓고 준비한 것들이 계획했던 대로 돌아가지 않을 때도 있다"고 설명했다.. 마지막으로 "지나온 길을 돌아보고 미래를 생각할 시간이 조금 필요하다. 나를 믿고 이해준 모든 분에게 감사하다"고 말했다..

난 저 인터뷰를 보면서 생각을 했고, 경기전에도 생각을 했지만 로우지는 은퇴를 하고 물러나는 것이 맞다고 본다.. 혹시라도 UFC 관련된 일을 하고 싶다면, 과거 영광을 토대로 한 홍보대사 정도가 적당하다고 생각한다.. 그리고 만일 더 싸우고 싶다면, 캠프를 바꾸길 바란다.. 지금의 캠프는 더 이상 의미가 없다고 생각하기 때문이다..

[Talk] Started in 2017 & Terminated in 2016..

어느 덧 2016년이 다 지나갔다.. 나의 첫 회고록이라면 회고록이라고 할 수 있겠다.. 이런 글을 쓰게 될거라곤 생각 못했는데 말이지.. ㅎㅎ..

올해 초 면접에 의한 정신적인 충격을 받은 이후 아웃사이더 햄의 블로그를 베이스로 삼고 블로그를 시작하게 되었는데.. 솔직히 반신반의 했다.. 이렇게 오래 할 수 있을까라는 의문이 가장 큰 이유이기도 했다..

그런데 벌써 꽤나 많은 시간이 지나고, 2017년을 맞이하게 되었다.. 원래는 지난해의 마지막날 혹은 새해의 첫날 쓸까 했는데 나의 특성상 회사에서만 거의 컴퓨터를 하고 블로그를 보는 편이고, 집에서는 가정사[?]를 돌보는 편이라 그렇게 하지 못하고서 2일인 오늘 쓰게 되었다..

꼭 쓰려고 한다면 집에서도 할 수야 있겠지만.. 나 스스로의 규칙을 좀 깨뜨리려고 하는 생각이 일부분 있어서기도 하다.. 꼭 다람쥐 같자나.. ㅎㅎㅎ..

작년 한해는 몇 가지 변화가 있었기도 했고, 꾸준히 하고자 했던 것을 꾸준히 잘 수행하기도 했다.. 하지만, 항상 느끼는거지만 좀 커다란 변화가 없다는 것은 아쉽긴하다.. 아웃사이더 햄처럼 먼가 큰 변화를 주고, 새로운 시도를 많이 해볼까라는 생각도 들긴 하지만 사람의 성향을 무시할 수도 없는 듯 하다..

가정사
가장 큰 변화라면 가정사를 꼽을 수 있을 듯 하다.. 더 큰 변화가 있을 수 있겠지만 나에게는 우선 가장 핵심이되고, 큰 부분인데.. 드디어 나의 2세를 임신을 하게 되었고, 그 아이가 태명이 리보인데.. 리보가 올해 태어나게 된다.. 1월 중에 볼 수 있을 듯하다.. 어떻게 생겼을지 어떻게 리보와 지내게 될지 한편으로는 불안함과 걱정스러움 등의 감정도 있지만 리보를 만날 생각에 기대감이 더 큰 것은 사실이다..

블로그
내 생활패턴에 있어서 블로그를 시작하게 된 것은 참 좋은 계기였다고 본다.. 물론 나의 관심사가 IT 라던지 기술부분에 한정된것은 아니다보니 블로그 내용들이 엄청나진 않지만 또한 나의 글보단 아웃사이더 햄의 글이라던지 기타적인 요소부분이 꽤 많지만 조금이라도 관심을 갖고 꾸준히 노력하는 부분을 높이 사고 싶어진다.. 나 자신이기에 좀 후하다.. ㅎㅎ..

취미생활
내 오랜 취미중 하나는 운동이다.. 헬스.. 몸짱이 되기위함보단 나의 건강 자체를 위해서 하는 것인데 솔직히 헬스장 가는것 자체게 상당히 귀찮지만 지속적으로 가기위해서 마음을 다 잡고 노력을 하고 있다.. 그리고 온라인 게임을 접은지가 상당히 오래되었는데 올해부터 시작한 피파온라인3 를 꾸준히 하고 있다.. 꾸준히는 하지만 실력이 늘지 않는 것은 함정인듯하다..

업무
업무 자체가 크게 변한 것은 없다.. 한 곳에서 머물면서 SM 을 하다보니 아무래도 좀 루즈한 것도 있긴하다.. 하지만 여타 다른 곳에 이직을 해서 치열하게 살기에는 지금의 생활을 통해서 가정이라던지 내 개인생활 등 얻는 것이 너무 많기에 지금의 생활 자체에는 만족한다.. 다만 나 스스로 노력을 좀 더 해야 될 것이다..

공부
난 IT 업종에 종사하는 근무자 치곤 공부를 별로 안하는 스타일이다.. 근데 이게 참 문제란 말이지.. 그런 이유 때문에 작년에 세미나도 참석하고 그런 것인데 아무래도 개인 생활 및 가정사로 인해서 무작정 다 참여가 쉽지만은 않았다.. 올해에는 평일에 있거나 한 세미나가 존재한다면 최대한 참석에 노력을 기울여봐야겠다..

나의 첫 회고록인데 쓰고보니 먼가 엄청 많은 듯 하지만 알맹이는 크게 없는 것 같다.. 나 스스로에게 있어서 엄청나게 몇 걸음 나아가지는 못하더라도 최소한 현재의 나보다는 조금이라도 반발자국이라도 한해를 돌아봤을 때 "아.. 이런 시도를 해봤구나.." 라는 생각이 들게끔 올해도 열심히 생활을 했으면 좋겠다..

Happy New Year..