태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

달력

04

« 2017/04 »

  •  
  •  
  •  
  •  
  •  
  •  
  • 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
  •  
  •  
  •  
  •  
  •  
  •  

string url1 = "http://localhost/contents/?registered_date_from=2016-12-26T15%3A00%3A00.000Z&registered_date_to=2016-12-27T15%3A00%3A00.000Z&keywords=%EA%B3%84%ED%9A%8D%EC%84%9C";

string url2 = "http://localhost/contents/?registered_date_from=2016-12-26T15%3A00%3A00.000Z&registered_date_to=2016-12-27T15%3A00%3A00.000Z";


var uri1 = new Uri(url1);

var uri2 = new Uri(url2);


Console.WriteLine(uri1.PathAndQuery);

Console.WriteLine(uri2.PathAndQuery);

// uri1.PathAndQuery

--> /contents/?registered_date_from=2016-12-26T15:00:00.000Z&registered_date_to=2016-12-27T15:00:00.000Z&keywords=%EA%B3%84%ED%9A%8D%EC%84%9C

// uri2.PathAndQuery

--> /contents/?registered_date_from=2016-12-26T15%3A00%3A00.000Z&registered_date_to=2016-12-27T15%3A00%3A00.000Z


쿼리 스트링의 구성에 따라서(현상으로는 UTF-8 한글이 인코딩된 쿼리스트링이 있는지의 여부에 따라) System.Uri 가 쿼리스트링을 이상하게 처리하는 문제다.

System.Uri 는 매우 광범위하게 사용되고 있어서, UriBuilder, HttpClient 도 이 문제의 영향을 받는 것을 확인했다.

OAuth 등 URL hash 해서 서명하는 방식의 경우 바로 문제가 드러나는데, 일단 이번 경우는 query string 파싱을 직접 구현하는 것으로 대체해서 해결은 되기는 했다. 닷넷 소스를 들여다보고 싶긴 한데 지금은 시간이 없어서 보질 못하겠네.

이 문제를 발견한 프로젝트는 닷넷 4.5 를 타겟으로 개발된 프로젝트이고, 닷넷 4.5.1, 4.5.2 설치된 환경에서 이 문제가 발생하는 것을 확인했다.

LINQPad 로 확인해보면 동일 PC에서 Linqpad 4 에서는 아래의 문제가 발생하지 않고, Linqpad 5 에서는 아래의 문제가 재현된다.

registered_date_from, registered_date_to 는 두 경우 모두 동일하게 url encode 되어 있는 상태인데, uri1 번의 PathAndQuery 에 포함된 것은 url decode 되어 버린 상태이고 uri2 번의 경우 그렇지 않다.

uri1 번의 PathAndQuery 의 경우 더더욱 웃긴 건 일부는 url decode 되어 있고 일부는 아니라는 점.

신고
TAG c#
Posted by wafe

댓글을 달아 주세요

지금은 alembic 을 포터블하게 사용하기 위해서 WinPython(3.5.2.3 Zero 버전)을 사용하고 있는데, pip 를 이용해서 alembic 을 설치한 상태로 압축해서 다른 PC에 가져가면 "failed to create process" 라는 에러를 내면서 alembic 실행이 실패하는 문제가 있었다.

이 상태에서도 기본 포함된 python 인터프리터를 실행하는 데에는 문제가 없었기 때문에 pip 로 추가설치한 패키지가 문제인 것 같았다.

혹시 몰라서 내 PC에서 pip로 alembic 설치할 때의 WinPython 위치(예를들면 D:\Tools\WinPython)와 동일한 경로에다가 옮겼더니 다른 PC에서도 그제야 실행이 된다. 

역시 pip 로 추가 설치한 패키지는 설치할 때 전체 경로가 고정되어서 들어가는 부분이 있는 것 같다. 일단은 C:\WinPython 처럼 WinPYthon을 C 드라이브의 경로에 두고 alembic 을 설치한 뒤 이걸 복사해서 다른 곳에서도 사용하는 방식으로 사용하는 선에서 마무리 하는게 좋겠다.

WinPython 설치 파일 자체에 원래부터 포함되어 있던 파이썬 패키지들은 괜찮은 것 같은데, 아예 alembic 을 포함하는 커스텀 WinPython 설치 파일을 만들 수 있으면 좀 더 편리할 것 같다.

신고
Posted by wafe

댓글을 달아 주세요

C#을 스크립팅 언어로 만들어주기까지 하는 완소 툴이 LINQPad 다. 오늘 JSON 문자열을 복사해서 코드에 붙여넣는 작업을 많이 할 일이 있어서 이것저것 알아보다가... 결국 별다른 팁을 못 찾았는데, 의외로 등잔 밑에 유용한 기능이 숨어 있었다.

이런 JSON 문자열을 C# 코드에 문자열 리터럴로 넣으려면 큰따옴표를 전부 이스케이프 해주는 게 완전 귀찮은데...

{"RequestedUserId":"wafe","TermId":"2017_1","CourseId":"1004","WeekId":"01","UseDept":true}

Edit > Paste as Escaped String 기능을 사용하면 아래와 같이 그대로 코드에 사용할 수 있는 형태로 붙여넣어 준다.

"{\"RequestedUserId\":\"wafe\", \"TermId\":\"2017_1\", \"CourseId\":\"1004\", \"WeekId\":\"01\", \"UseDept\":true}"


신고
TAG c#
Posted by wafe

댓글을 달아 주세요

파이썬용 DB 마이그레이션 라이브러리인 alembic ( Outsider’s Dev Story alembic tag )을 사용해서 MySQL DB를 관리해보려는 생각으로, 일단 테스트를 해보려고 하니 WinPython Zero Version 에는 MySQL 클라이언트가 설치되어 있지 않다. 그래서 실행하면 mysqldb가 없다고 에러가 난다.

내가 사용한 것은 WinPython 3.5.2.3 64비트 Zero 버전인데, 여기 포함된 CPython 버전은 3.5대이다. 구글링해보니 파이썬 3부터는 mysqlclient를 설치하면 mysqldb 호환이 된다고 한다.

pip install mysqlclient 해서 설치하면 일단 빌드가 필요하다고 나온다 흐아. 얼마전 글에서 WinPython의 빌드 설정을 msvc로 바꿨기 때문에 Visual C++ Build Tools 설치가 필요하다는 메시지가 나온다. 나는 이미 VS 2015가 있기 때문에 VS 2015 설치에서 C++ 관련 항목을 설치해줬다.

그러고 나서 다시 인스톨을 시도하니 아래와 같은 빌드 오류가 난다.

_mysql.c(29): fatal error C1083: Cannot open include file: 'my_config.h': No such file or directory

오류 메시지보다 조금 위의 cl.exe 실행 메시지를 보니, MySQL include 경로 설정이 아래처럼 되어 있는데, 실제로 내 PC에 설치된 MySQL C Connector 와는 버전이 다른 것을 찾고 있다.

"-IC:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include"

구글링을 약간 해서 pip로 설치할 때 커스텀하게 빌드 옵션을 지정할 수 있는 것을 발견하고 아래처럼 실행했다.

> pip install mysqlclient --global-option=build_ext --global-option="-IC:\Program Files\MySQL\MySQL Connector C 6.1.3\include"

이번에는 아까와 다른 빌드 오류가 난다.

C:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\ucrt\stdio.h(1927): fatal error C1189: #error:  Macro definition of snprintf conflicts with Standard Library function declaration

으… 오랜만에 예~~전에 리눅스에 뭐 하나 설치하려면 소스 받아서 make all make install 해야 하는데, 빌드오류 하나하나 잡아가면서 몇 시간씩 걸려 설치하던 악몽이 떠오른다.

Windows 사용하면서 무슨 빌드냐! 분명 바이너리 패키지가 있을거야! 하며 구글링에 돌입, 역시 세상을 아름답게 만들어 주는 분들이 있다.

Unofficial Windows Binaries for Python Extension Packages에서 각종 패키지의 whl 파일을 받을 수 있다. (말이 unofficial 이지… 윈도 사용자에게는 거의 오피셜?!)

사용하는 CPython 버전과 32/64비트 버전에 맞게 whl 파일을 받아서 설치한다.

> pip install d:\downloads\mysqlclient-1.3.8-cp35-cp35m-win_amd64.whl

Processing d:\downloads\mysqlclient-1.3.8-cp35-cp35m-win_amd64.whl
Installing collected packages: mysqlclient
Successfully installed mysqlclient-1.3.8

설치 완료! 해피~!

신고
Posted by wafe

댓글을 달아 주세요

2016.11.17 21:28

Portable python - WinPython 분류없음2016.11.17 21:28

파이썬을 포터블하게 사용할 수 있는 방법을 찾다가 발견한 것이 WinPython 이다. (왜 전에는 몰랐지?)

WinPython 은 여러가지 패키지가 있는데, 파이썬 기반으로 유틸리티를 만들어서 간단히 복사해서 갖다놓기만 하면 실행이 가능한 형태로 쓰면서도 만들기도 편하게 하려는 것이 목표이므로, 가장 작은 Zero Version(WinPython 3.5.2.3Zero 등 끝에 Zero 가 붙은 판)을 사용하면 적당하다.

다운로드는 EXE인데, 뭘 설치해 준다기 보다는 지정한 경로에 압축만 풀어주는 정도다. 포함된 WinPython Control Panel.exe 를 사용하면 python.org 에서 배포하는 정식 인스톨러처럼 시스템에 등록도 해주는 기능이나 패키지 설치해주는 기능도 있다는데, Zero 버전(내가 쓴 것은 3.5.2.3Zero다)에서는 UI관련 패키지가 빠져있어서인지 아예 실행도 안된다. 그냥 개발 환경에서 여러 버전을 깔아서 편하게 쓰고 싶은거라면 약 200MB 짜리 풀 버전을 받는게 속 편하다.

압축 풀린 상태 그대로 있는 패키지만 가지고 사용하는 데에는 전혀 무리가 없다. 설치 폴더의 WinPython Command Prompt.exeWinPython Interpreter.exe 를 실행시키면 된다. .py 스크립트 파일을 실행시키고 싶으면 scripts 폴더의 python.bat 를 이용해서 python.exe 사용하듯이 실행시키면 필요한 환경변수들을 다 세팅해서 잘 돌아간다.

Zero 버전이므로 추가 패키지를 설치해야 되는데 pip 를 사용하면 된다고 하지만 실제로는 pip install 로 뭔가 설치해보면 cygwin builder 어쩌고 하는 곳에서 TypeError: unorderable types: NoneType() < str() 라는 오류가 나면서 설치가 안된다.

정식 해결방법인지는 잘 모르겠는데, settings\pydistutils.cfg 파일을 열어서 mingw 로 되어 있는 부분을 msvc로 변경하면 문제없이 잘 설치된다.


신고
Posted by wafe

댓글을 달아 주세요

2016.11.04 15:03

PHP와 schema-less URL 분류없음2016.11.04 15:03

schema-less 혹은 protocol relative URL 이라고 부르는 // 로 시작하는 URL을 브라우저는 잘 다루지만, 서버 측 언어/라이브러리는 잘 다루지 못하는 경우가 있다.

<?php
$url = '//www.example.com/path?googleguy=googley';

// Prior to 5.4.7 this would show the path as "//www.example.com/path"
var_dump(parse_url($url));



// 5.3.x
array(2) {
  ["path"]=>
  string(22) "//www.example.com/path"
  ["query"]=>
  string(17) "googleguy=googley"
}



// 7.0.x
array(3) {
  ["host"]=>
  string(15) "www.example.com"
  ["path"]=>
  string(5) "/path"
  ["query"]=>
  string(17) "googleguy=googley"
}


신고
TAG php
Posted by wafe

댓글을 달아 주세요

자이닉스 개발부 블로그에, 얼마 전에 자이닉스에 합류한 남정현 씨의 첫 포스트가 올라왔네요. :)


Internet Explorer 11의 Breaking Changes(자이닉스 개발부 블로그)


UserAgent 문자열에서 MSIE를 뺐다는 건, 요즈음의 웹프론트 개발 트렌드를 따르겠다는 모양으로 보이고, W3C의 표준 DOM API를 잘 따르겠다는 선언의 의미로 보입니다.


비슷한 전례로 이미 Windows 8의 메트로 모드 IE(Modern UI IE?)와 데스크톱 모드 IE를 User-Agent 문자열만으로 구분할 수 없도록 한 바가 있죠. User-Agent 문자열을 이용하여 브라우저 종류와 버전을 알아낸 후에 이건 IE용 코드고 저건 크롬용 코드라는 식으로 코드를 작성하지 말고, 관심있는 특정 기능의 사용 가능 여부에 따라서 그 기능이 사용가능할 때의 통상 코드와 사용 불가능할 때의 예외 상황 코드를 작성하라는 가이드를 제시한 바가 있습니다.


HTML5/CSS3 시대가 되면서 요 근래에는 특정 기능의 사용 가능 여부를 확인해서 로직을 분기하는 것을 권장하는 분위기입니다. 그런 분위기 속에서 특정 기능의 사용 가능 여부를 쉽게 확인할 수 있게 해주는 Modernizr 라는 라이브러리가 인기를 끌고 있죠.


MS의 결정이 일단 표준 준수 쪽으로 향하고 있고, 웹 개발 분야의 트렌드를 수용하는 방향으로 가고 있으니 기대가 됩니다.


한편으로 실제 개발 상황에서는 예를 들면 메트로 모드 IE라서 실버라이트 지원이 안되는건지, 데스크톱이긴 한데 실버라이트 플러그인 설치를 안해서 그런건지 구분하고 싶어했던 예를 떠올려볼 수 있겠네요. 상세 개발 레벨에서는 결국 User-Agent에서 Trident 라는 문자열을 검사해서 IE11을 구분해 내려는 유혹이 상당히 있지 않을까 싶긴 합니다. 아예 Gecko 엔진 같은 걸로 갈아탔으면 호환성도 높아지고 Firefox 프로젝트를 살려주는 공익적인 성격도 있어 더 높을 것 같은데 말이죠. (MS가 그런 선택을 할리가 없겠지만요)



신고
Posted by wafe

댓글을 달아 주세요

  1. 2014.10.07 19:24  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • wafe 2014.12.12 21:07 신고  댓글주소  수정/삭제

      제가 요즘 바빠서 블로그를 못챙기다보니 이렇게 오래 지나서 댓글을 달게 되네요.

      요즘 아무래도 관련 분야 내용들이 워낙 빠르게 변화하고, 외국 사례들이 바로바로 번역되어 들어와야 하는 상황이다보니 번역어를 고르고 고를만한 여유가 적어졌기 때문이지 않을까 싶습니다. 공들여 번역한 번역서들은 사실 제가 번역한 결과물보다 품질도 좋고 용어 선택도 더 좋지요. 저도 짬내서 약간의 취미 겸 공부로 하는 거다보니 짧은 시간을 들이게 되기도 하는군요.

      아직도 공공기관이나, 비슷한 성격의 기관을 대상으로 하는 제안서 등에는 일부러라도 한자어로 골라서 쓴다거나 하는 그런 분위기가 많이 남아 있긴 합니다만 일상 대화에서는 또 잘 안쓰게 되네요. ^^

ffmpeg의 avpicture_get_size() 함수를 보면 언제부터인가 첫번째 인자 타입이 enum PixelFormat pix_fmt 로 변경되었습니다. 최초로 이런 변경 사항이 적용된 커밋을 찾아서, 이 변경 사항의 영향 범위가 어느 정도인지 파악하고 싶었는데, ffmpeg 프로젝트의 git 저장소를 웹으로 보여주는 인터페이스에서는 그 지점을 찾기가 여간 힘든게 아니네요.

우선 웹 인터페이스를 통해서 0.5 릴리스 브랜치의 가장 최근 커밋(head)에서는 avpicture_get_size()의 첫번째 인자 타입이 int pix_fmt 인 것은 확인을 했고요, 0.6 릴리스 브랜치의 head 에서는 PixelFormat pix_fmt 인 것을 확인했습니다. Get FFmpeg 페이지에서 보면 0.5 릴리스 브랜치가 2009-03-02 에 cut off 되었다고 하니, 0.6 릴리스 브랜치에서 2009-03-02 이전의 커밋을 찾아보면 될 것 같습니다. 페이지를 막~ 넘겨서 60페이지 쯤 가니까 2009년 2월 커밋들이 보이네요. 아무 커밋이나 하나 골라서(c027e91a744c5875a47e5d4bb2a0ff9b112d2e0f) 확인해보니 인자 타입이 int pix_fmt 입니다. 그러면 이 커밋과 0.6 릴리스의 헤드 커밋 사이 어디쯤에선가 인자 형태가 바뀌었다고 볼 수 있겠네요. 어느 커밋에서 그런 변경이 있었는지 bisect 로 찾아보기로 했습니다.

ffmpeg 저장소를 clone 하고, 리모트의 0.6 브랜치를 체크아웃 합니다.

관심 대상인 avcodec.h 파일을 Notepad++ 이나 Sublime Text 같이 파일이 변경되었을 때 자동으로 바뀐 내용으로 새로고침해주는 편집기로 열어둡니다. 이렇게 하면 매번 파일을 새로 열어보는 번거로움을 덜 수가 있습니다.

이제 bisect 를 시작해봅시다.

git command line 을 실행해서 ffmpeg 저장소 루트 디렉토리로 갑니다. 거기서 시작 명령을 내려줍니다.

> git bisect start

그리고 0.6 브랜치의 head 는 PixelFormat pix_fmt 형태이므로, bad 라고 표시를 해 줍니다.

> git bisect bad

또한 int pix_fmt 형태인 커밋의 위치를 알고 있으므로 good 으로 표시해줍니다.

> git bisect good c027e91a744c5875a47e5d4bb2a0ff9b112d2e0f

이렇게 하면 git 은 자동으로 0.6 브랜치의 head 와  c027e91a744c5875a47e5d4bb2a0ff9b112d2e0f 커밋의 중간 지점 커밋을 체크아웃 해 줍니다. 아까 에디터에 열어둔 avcodec.h 파일을 확인해봅니다. 아직은 인자 타입이 PixelFormat 이므로 bad 로 표시합니다.

> git bisect bad

그러면 git 이 자동으로 이 커밋과 가장 처음 good 으로 표시된 지점인 c027e91a744c5875a47e5d4bb2a0ff9b112d2e0f 커밋의 중간 지점 커밋을 체크아웃 해 줍니다. 다시 에디터에서 avcodec.h 를 확인해봅니다. 역시 PixelFormat 이군요. bad 로 표시합시다.

> git bisect bad

이런 식으로 커밋 히스토리를 절반씩 나눠가면서 일종의 바이너리 서치(이진 탐색)을 해서 인자 타입이 int 일 때에는 bad 대신 good 으로 표시해주고, bisect 모드가 끝날 때까지 진행하면 인자 타입이 int 에서 PixelFormat 으로 변경된 커밋을 빠르게 찾을 수 있습니다.

파일에 "avpicture_get_size(enum PixelFormat pix_fmt" 라는 문자열이 포함되어 있는지 확인하는 스크립트를 git bisect run 을 이용하여 실행시키면 지금까지 했던 과정을 자동화할 수도 있죠.

svn 저장소를 활용하면서도 이런 일을 해주는 스크립트들이 상당히 만들어져 있긴 합니다. 하지만 아무래도 svn 은 특정 커밋(리비전)간의 전환을 하려면 네트워크로 파일 전송을 해야 하니 상대적으로 매우 느리죠. git 에는 bisect 기능이 내장되어 있어 잘 알려져 있기도 하고, svn 보다는 git이나 mercurial 같이 커밋간의 전환이 아주 빠른 DVCS 들에서 빛을 보는 기능이라고 할 수 있겠습니다. svn 에서 bisect 할 일이 있으면 git-svn 같은 도구를 이용해서 svn 저장소를 git 저장소로 마이그레이션 한 후에 git bisect 기능을 사용하는게 더 효율적일 거라는 조언도 있네요.

신고
TAG git
Posted by wafe

댓글을 달아 주세요

일하다보면 동영상을 다룰 일이 자주 있습니다. 동영상 관련해서는 유지보수 이슈가 꽤 많은 편이거든요. 인코더가 많다보니 동영상의 세부적인 정보? 내용? 들이 아주 제각각인 경우가 꽤 있죠. 프레임 단위로 뭔가 분석해보고 싶을 때에는 ffprobe 를 사용해야겠지만, 거기까지 가면 이미 지옥문을 열었다고 볼 수 있고요... ^^; 보통은 코덱이나 비트레이트, 어떤 스트림이 포함되어 있는지를 우선 확인하는 게 순서인데 그럴 때 MediaInfo 라는 오픈소스 도구를 사용하면 도움이 많이 됩니다.

설치하고 나면 탐색기에서 동영상 파일을 오른쪽 클릭하여 컨텍스트 메뉴에서 바로 실행할 수 있어서 편리합니다.

여러가지 View 를 제공하는데 저는 아래 이미지처럼 TreeView 형태로 사용하는 편입니다.


신고
Posted by wafe

댓글을 달아 주세요

2013.05.06 19:00

PHP: The Right Way 한국어판 분류없음2013.05.06 19:00

PHP: The Right Way를 주변 사람들에게 보여주고 싶다는 생각이 들었는데 아직 한국어판이 없기에 직접 번역해보았습니다.

혹 무슨 말인지 모르겠다거나 잘못된 부분이 있으면 말씀해주세요. 피드백 환영합니다.



신고
TAG php
Posted by wafe

댓글을 달아 주세요

  1. 귀뫄뉘 2013.07.15 17:25 신고  댓글주소  수정/삭제  댓글쓰기

    잘 봤습니다~ 큰 도움이 되었어요 ^^

  2. 윤진우 2013.09.26 11:19 신고  댓글주소  수정/삭제  댓글쓰기

    우연히 검색하다 http://wafe.github.io/php-the-right-way/ 사이트를 알게되었는데
    번역에 링크 타고 넘어오다 남깁니다
    잘 읽고 많이 배웠습니다 감사합니다.
    오래오래 유지 해주세요^^