[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년 2월 18일 목요일

[JS]잘못된 Javascript의 사용에 대해서..

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


제목이 좀 거창하기는 한데(ㅡ..ㅡ) 을 아예 이해를 못한채 개발된 코드를 좀 보게 된다. 개발이라는 것이 순수 자기 머릿속에 있는 것만 가지고 처음부터 끝까지 개발하는 사람이 어디 있겠는가... 요즘 같으면 개발능력이 검색 능력이라고 농담할 정도로 소스가 인터넷에 널려있고 그걸 갔다가 잘 조합하다보면 그럭저럭 돌아간다. 또한 사수나 이전에 구축되어 있는 사이트들도 있고.... 근데 여기서 돌아가는 동작을 이해하지 못하면 결국 잘못된 소스가 나올 경우가 많다.

실용주의 프로그래머에 보면 "디버깅을 하지 못하는 것은 원래 어떻게 돌아갔는지 몰랐기 때문이다." 라는 말이 있다. 철저히 공감한다.






최근에 본 소스에 대해서 얘기를 해보려고 한다. 머 그녀석이 작성한 소스는 아니었지만 이런 내용을 보면 프로젝트의 일원으로써 기분나쁠수도 있지만 머 잘못된 것은 잘못된거다. 약간 상황상 초기단계에도 그 프로젝트의 소스를 좀 보았었는데 초반에도 많이 잘못된 부분이 있었는데 내가 관여할 상황이 아니기 때문에 그냥 나뒀다. 몇달만에 다시 보았을때는 괜찮은 사이트의 모습을 갖추고 있었지만 내부는 영 부실했다. 로그인 체크가 이런식으로 되어 있었다.

JavaScript

if (isLogin) {
    // 로그인되었을 때의 동작
} else {
    // 로그인 안되었을때의 동작   
 }


동작은 중요하지 않으므로 그냥 한글로 처리했다. 아이디/패스워드를 입력하면 서블릿을 호출해서 결과값을 xml로 가져와서 파싱한다. 그리고 결과값을 isLogin에 넣어서 로그인 여부를 보여준다. 아마 작성자는 로그인을 하지 않았을때 권한이 없는 메뉴에 대해서 페이지가 넘어갔다가 오는 것도 낭비라고 생각한것 같다. Ajax로 할때 많이 하듯이 로그인 처리도 현재 페이지에서 바로 처리했고 권한이 없는 메뉴에 대해서 isLogin이라는 자바스크립트 변수로 접근하지 못하게 막고 있다.


이건 완전히 잘못됐다. 이건 브라우저 주소창에 다음과 같은 한줄만 입력하면 isLogin의 값을 접속자 맘대로 바꿔버릴 수 있다.

javascript:isLogin=true;void 0;

정확히는 모르겠지만 내가 보기엔 이건 해킹도 아니고 XSS(크로스 사이트스크립팅)도 아니다. 그냥 잘못만든거다. 보안 문제는 서버쪽에서 체크해야지 클라이언트단이 자바스크립트에서 하겠다는 생각은 잘못 된것이다.(물론 자바스크립트에서도 신경써야하는 보안문제가 있지만...) 자바스크립트는 유저 편의성과 HTML강화를 위해서 제공하는 것이지 자바스크립트로 모든 걸 다 할 수는 없다. Ajax를 쓰다보면 자바스크립트에서 처리해야 하는 부분도 있지만 이부분은 UI를 위한 부분이지 검증을 위한 부분이 아니기 때문에 검정을 Javascript에 의존하지 말고 당연히 서버쪽에서도 재확인 해주어야 한다.




여기서 또하나를 보자

JavaScript

<script type="text/javascript">
var usrId = "<% session.getAttribute("userId") %>";

if (userid != null) {
      로그인에 대한 동작
} else {
      <% session.remove("userId"); %>
      <% session.remove("memberType"); %>
}
</script>


위 코드가 로그인하고 메뉴에 들어간 페이지에 들어있던 자바스크립트 코드이다. 무엇이 잘못된지 알겠는가.... 해당부분만 잘라온 라서 약간 헷갈릴수도 있지만 이건 JSP와 자바스크립트의 동작을 전혀 이해하지 못한 것이다. 그냥 보면 뭘 하고 싶었는지 까지는 이해할 수 있다. 세션에 값이 있으면 로그인하고 세션에 값이 없으면 로그인에 문제가 있었다고 생각하고 세션을 초기화 해주겠다는 것이다. 결론적으로 이 코드는 돌아가지 않는다.

아주 단순한 원리인데 인터넷에서 사람들이 질문하는 것을 봐도 이걸 이해하지 못하는 사람들을 꽤 많이 볼 수 있다.


웹이라는 것은 서버가 있다. 서버에는 웹서버가 있고 WAS(컨테이너포함)라고 얘기하는 웹어플리케이션서버가 있다. 설정나름이지만 이렇게 존재하는 이유는 서버에서 컴파일등의 동작이 필요없는 html, javscript파일, css, 이미지등을 사용자가 요청이 오면 그냥 돌려준다. 그렇지 않고 jsp등 서버의 해석이 필요한 페이지는 WAS가 페이지를 해석해서 나온 결과값을 원래의 html파일에 넣어서 사용자에게 돌려준다. 그러면 사용자의 웹브라우저(IE, Firefox 등등)가 해당 페이지를 받아서 렌더링을 한다. 여기서 웹브라우저가 html을 렌더링해서 보여주고 javascript를 해석해서 해당 동작을 수행한다.


이게 간단히 요약한 동작방식이다. 위에서 보듯이 jsp코드와 자바스크립트는 그 수행시점과 장소가 완전히 다르다. 그 순서로 보면 저위의 코드는 if문의 참여부의 상관없이 무조건 session.remove()가 동작한다. WAS는 jsp의 <% %>안에 있는 스크립틀릿 코드만 수행하지 그 외의 부분은 전혀 신경쓰지 않기 때문에....

그렇기 때문에 저 사이트는 첫페이지에서 세션을 심고는 두번째 페이지에서 무조건 세션을 날려버린다. 이런 동작방식을 이해하고 있어야 개발할 때 헷갈리지 않고 많이 나오는 질문중에 하나인 자바스크립트의 변수에 있는 값을 jsp의 변수에 넣으려고 하는 것이 불가능한지를 이해할 수 있다. (물론 js와 jsp간에 서로 값을 주고 받을 수 있는 프레임워크는 존재하지만 여기선 그 얘기가 아니므로....)



항상 어디서나 기본적인 개념이 중요하다는 생각......
 

[JS]자바스크립트 예약어(Reserved Word)..

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

자바스크립트 예약어들(ECMAScript v3)
break
case
catch
continue
default
delete
do
else
false
finally
for
function
if
in
instanceof
new
null
return
switch
this
throw
true
try
typeof
var
void
while
with


현재 사용되고 있지는 않지만 ECMA v3에서 확장을 위해 예약되어 있는 단어들

abstract
boolean
byte
char
class
const
debugger
double
enum
export
extends
final
float
goto
implements
import
int
interface
long
native
packge
private
protected
public
short
static
super
synchronized
throws
transient
volatile



as, is, namespace, use는 현재 예약되어 있지는 않지만 ECMAScript v4에서 사용될 계획이 있으므로 조심조심

My Comment..
얼핏보면, 꼭 java 같다능.. 저 중에 몇개나 써봤을꼬..
대충 보면 break, if, else, while, var 등등.. 누구나 봤을만한건 써봤거나..
혹은 나도 봤다는 기억만 하고 뚜렷하지 않는게 있구나..
그래도 생각보단 많이 써본 듯.. 문제는 기억을 다 못하는게.. 냥흠..

근데 내가 기억력이 없는건지.. 왜 쓰고서 기억을 잘 못하지..
그래서 항상 나중에 또 쓰려면, 전체가 기억이 나는게 아니고, 일부분 기억이 나는..
키워드 갖고서 검색해서 쓰거나.. 같은 프로젝트면.. 이클립스에서 검색해서..
사용하게 된다.. 덕분에 ctrl + h 겁니 눌러됬다.. ㅋㅋ..
이게 웃을일만은 아닌데.. 흙.. ㅠㅜ

[JSP]response.sendRedirect()에 대해서..

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

JSP로 페이지 작업을 하면서 페이지를 이동하기 위해서 자연스레 response.sendRedirect()를 사용했다. 나름 자바스크립트의 location.href()로 이동하는 것 보다는 나을꺼라는 생각으로 근데 오히려 문제가 많았다. 처음엔 꽤 해맸는데 이런저런 자료를 찾다가 response.sendRedirect()에 대해서 좀 알게 되었다.

response.sendRedirect()는 생긴거는 아주 직관적으로 생겼다.(물론 오해지만...) resonse를 리다이렉트 시켜버린다는 건데 실제 동작은 그렇게 직관적이지 않다. 직관적이지 않다고 말한 이유는 자바스크립트의 location.href()가 해당 코드를 만나는 순간 페이지를 이동하는 반면에 response.sendRedirect()를 실행될때 페이지를 이동하는 것이 아니라 페이지의 Header정보의 HTTP 상태코드(Status code)를 301로 바꾸어서 보내준다. 헤더를 바꾼다는 의미는 response.sendRedirect()이하의 모든 코드를 다 실행한다는 얘기다.

Java

<body>
<% response.sendRedirect("target.jsp"); %>
<% System.out.println("test"); %>
</body>


jsp라는 것을 전제하에 스크립틀릿으로 작성했고 기본적인 html태그는 생략했다. 이 소스를 실행하면 콘솔에 "test"가 찍힐까 안찍힐까... 동작원리를 몰랐을때는 안찍힌다고 생각했는데 이건 찍힌다. response.sendRedirect() 아래의 코드는 실행이 안된다고 생각하기 쉽지만 response.sendRedirect()는 위에 말한대로 헤더의 상태코드만 바꿔주는 역할을 하기 때문에 이하 페이지의 모든 소스가 다 실행된다.즉 아래쪽 코드를 실행하는데 에러가 있다면 response.sendRedirect()이 되지 않고 에러메시지만 나타난다. response.sendRedirect()이하코드를 실행하기 싫다면 if-eles문을 이용해서 아예 다른쪽 코드는 실행자체가 되지 않도록 해야한다.

Java


<body>

<% 
    if (회원이 아니면) {
        response.sendRedirect("target.jsp"); 
    } else {
        // 회원일 땐의 동작 코드
    }
%>

</body>


의미 전달이 중요하지 코드는 중요하지 않기 때문에 if-else구문은 그냥 한글로 처리해버렸다. ^^;;; 어쨌든 저런식으로 else문의 반대쪽 코드를 다 넣어야 한다. 에러가 안나더라도 아래쪽에 시간을 많이 소비하는 소스가 있다면 필요도 없는 소스에 리소스를 낭비하게 되는 겪이다.






그럼 헤더의 상태코드를 받는다는 것은 무엇인가. W3C의 HTTP/1.1 Status Code Definitions을 보면 상태코드에 대해서 자세히 나와있다. 대략적으로 몇가지 적으면

200 OK
301 Moved Permanently
403 Forbidden
404 Non Found
500 Internal Sever Error


등이 있다. 익숙한 코드들이 많이 보인다. 브라우저가 서버측에 페이지를 요청에서 받은 정보의 헤더정보의 상태코드를 봐서 200이면 정상이므로 페이지가 보여지고 403, 404, 500코드이면 에러메시지를 보여준다. 여기서 response.sendRedirect()는 이 상태코드를 301로 바꿔서 보내주고 브라우저는 상태코드가 301이 오면 같이 받은 URL로 다시 요청을 보내는 것이다. 당연히 브라우저는 클라이언트쪽이기 때문에 서버쪽에서는 모든 코드가 다 실행되는 것이다.


이런 response.sendRedirect()의 동작원리 때문에 발생한 문제가 또 있다. include를 사용했을 때의 문제인데 include에는 2가지 방식이 있다. 정적인 방식과 동적인 방식이 있는데

<jsp:include page="incl.jsp" flush="false" />

와 같이 작성하면 동적인 방식이고 페이지가 요청될때마다 인클루드하는 파일을 새로 읽어온다.

<%@ include file="incl.jsp" %>

위와같이 작성하면 정적으로 인클루드를 컴파일단계에서 해당소스를 인클루드를 하는 파일의 소스에 집어넣는다. (수행속도는 당연히 정적인 방식이 빠르다.)



여기서 동적인 방식으로 인클루드 했을 때 incl.jsp파일에서 response.sendRedirect()를 사용해도 작동을 하지 않는다. 처음에는 혼란스러웠지만 동작원리를 알고나면 그다지 혼란스럽지 않다. 100%확신까진 아니지만 response.sendRedirect()는 incl.jsp의 Header의 상태코드를 변경했고 이 변경된 코드가 브라우져에 전달된것이 아닌 인클루드 해온 파일에 전달되었고 그 파일의 상태코드는 301이 아니기 때문에 리다이렉션 자체가 수행되지 않는다. 당연히 정적인 방식으로 인클루드 했을때문 문제없이 수행된다. (물론 위에 말한대로 그 이하 소스도 다 수행된다.)

My Comment..
BC 에서는 다 XML 내지는 서버 자체에 설정을 해서 처리하긴 하는데..
머 그것도 어디까지나 말로만 그렇다는거지..
해당 문제로 인해서 보안에 걸릴 때가 많단 말이지..

근데 옛날에는 저런것 자체를 몰랐는뎅.. 왜 해야되는지도 몰랐고..
BC 내부적으로 돌아가는 것을 다 확인은 안하고.. 단순히 카더라만 생각했는데..

내가 공부 및 확인 해야 될 목록에 적어두고서 확인해서 포스팅 해봐야겠당..
형 글을 옮기다보니.. 목록이 점점 늘어간다.. 후아..
언제 다 한다묭.. ㅎㅎ..

[DEV]이클립스(Eclipse)에서 웹서비스 클라이언트 만들기..

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

여기서 웹서비스는 웹으로 하는 서비스를 얘기하는게 아니고 기술이름인 웹서비스를 말하는 것이다. 내가 웹서비스라는 말을 처음 들은 것은 올 2월정도였던 것 같다. 그뒤로는 심심찮게 들리고 있지만.... 이런게 있는지도 몰랐었다. ㅡ..ㅡ  그때 당시 회의에 들어가서 웹서비스를 나는 웹으로 하는 서비스라고 당연히 생각하고 있었기 때문에 회의내용을 도저히 이해 못하고 있었고 나와서 웹서비스가 기술중 하나의 이름이라는 것을 알게 되었다. (그당시에는 보편적인 이름이 아니었는지 몰라도 네이밍 센스 한번.. ㅡ..ㅡ 이건 현대에서 자동차 새로 만들었는데 모델명이 자동차라고 지은거랑 똑같잖아.. ㅡ..ㅡ)

어쨌든 웹서비스란게 있다. 쉽게 말하면 이기종간의 통신을 위한 것이다. SOAP, WSDL, UDDI등을 이용해서 자바사에서 C#으로 만들어진 서비스에 요청을 보내도 응답을 받을 수 있다. 그 이념과 목표는 대단했지만 너무 복잡한 스펙덕분에 빛을 발휘 못하고 요즘은 그나마 지원하는 툴들이 많아져서 괜찮아진것 같지만 REST의 등장으로 인하여 아주 큰 주목을 받지 못하고 있는 듯 하다. 검색해 보면 웹서비스에 대한 많은 글들을 볼수가 있고 크게 뜨진 못했지만 웹서비스는 끝났다라고 말할수는 없는듯 하다. REST가 뜨면서 같이 다시 주목받고 있는 듯한 느낌도.... 한글 위키피디아는 간략한 내용밖에 없고 좀 자세한 걸 보려면 역시 영문 위키피디아의 내용을 보아야 한다.(오른쪽 그림이 웹서비스 아키텍쳐)

물론 나도 웹서비스를 거의 이해하고 있지 못하다. 올초 관련 사업이(하진 않았지만) 있어서 책을 좀 보았는데 스펙에 대한(XML) 설명만 너무 길게 있어서 이해하기가 쉽지 않았다.(나의 내공으로는...) 대충 머하는 것인지만 알고 있지 그래서 어쩌라고? 정도의 수준이다.. ㅡ..ㅡ




어쨌든 그래도 웹서비스라는게 있다라는 걸 안것 만으로도 일단 도움이 되었다고 할 수는 있는데 최근에 웹서비스 클라이언트를 만들어야 되는 상황이 왔다. 쉽게 말하면 우리 시스템은 자바기반인데 다른 시스템의 닷넷기반에서 만들어준 웹서비스를 우리쪽에서 호출해서 값만 받아오면 끝나는 문제. 상황은 아주 명확하고 WSDL도 받았는데 위에 말한대로 그래서 어쩌라고? ㅡ..ㅡ 어떻게 호출하는 지를 몰랐다. 여기저기 찾아다녔지만 이렇다할 정보를 찾을수 없었고 클라이언트 구현하자고 책펴놓고 웹서비스 자체를 다 공부하기에는 시간이 모자랐다.


물어볼 사람도 없고 답답한 와중에 kenu님의 포스팅을 발견했다. 깜깜하던 가운데 발견한 한줄기 빛이...
이클립스로 쉽게 웹서비스 시작하기
이클립스로 웹서비스 개발 쉽게하기 part2



일단 익히기 위해서 따라해본 다음에 강좌에서는 자바로 기능을 만들어서 서버/클라이언트를 모두 만들었지만 난 만들어진 서버의 WSDL이 있는 상황이었기 때문에 이것저것 만져가면서 클라이언트 부분만 구현을 했다. 자세한 내용은 kenu님의 포스팅을 참고하고 내가 확인해본 바로는 3.2 WTP나 3.3 Europa나 둘다 웹서비스를 만드는 기능이 있었다. 당연히 3.4 Ganymede에도 있을꺼라 생각하고 그 이하버전에 대해서는 확인안해봐서 정확히 모르겠다.

사용자 삽입 이미지

일단 New Project를 만든다. 웹으로 할것이므로 당연히 "Dynamic Web Project"로 생성한다. 이름은 적당히 주고...

사용자 삽입 이미지

만들어진 프로젝트에서 오른쪽 마우스를 눌어서 New - Other를 실행한다.

사용자 삽입 이미지

Other로 들어가면 너무 많이 나오기 때문에 상단 filter란을 통해서 Web Service를 찾는다. 여기서는 클라이언트만 만들 것이므로 "Web Service Client"를 실행한다.

사용자 삽입 이미지

client레벨을 Test까지 올려준다.(정확한 차이는 잘 모르겠다.) 캡쳐에는 안나왔지만 Monitor the Web Service를 체크하면 웹서비스를 이클립스에서 모니터할 수 있다. 상당 Service definition에 wsdl의 위치를 넣어주어야 한다. Browse를 눌러서

사용자 삽입 이미지
WSDL의 위치를 넣으면 아래쪽에 선택한 WSDL에 대한 정보(?)가 나타난다. 내가 실제 사용했던 것은 펼치고 열어볼수 있었는데 사업에 쓴 WSDL을 공개할 순 없어서 공개된 구글 WSDL을 썼더니 Read Only로만 나타난다. WSDL의 차이로 인한 형상인듯 하다. 어쨌든 가운데 칸에 WSDL에 대한 것이 나와야 한다. 잘못된 WSDL일 경우에는 나오지 않는다.


이게 끝이다. Finish를 눌러주면 스스로 WSDL을 분석해서 소스를 뱉어준다.(WSDL에 따라 생성되는 시간은 좀 다른것 같다.)

사용자 삽입 이미지

위의 프로젝트가 Web Service 자동생성으로 만들어진 코드이다. TestClient.jsp를 실행하면

사용자 삽입 이미지

위와같은 화면이 나오고 웹서비스 프로바이더에서 제공하는 함수를 클릭해서 테스트해볼 수 있는 페이지가 제공된다. 관련함수들 중에서 Proxy라는 이름이 붙은(여기서는 GoogleSearchPortProxy.java)파일에 제공된 함수들이 정의되어 있다. 실제적으로 사용할때도 이것만 사용하면 된다.



method.jsp에서 각 함수별로 파라미터로 분류 숫자를 넘겨주고 input에서 case문으로 각 함수별로 필요한 필드값을 보여준다. 그리고 Result에서 동일하게 case문을 이용해서 실제 함수를 실행한다. 결국 함수 사용법을 참고하려면 Result만 보면 된다.(input쪽도 필요하면 같이 참고하고...)

Java

<jsp:useBean id="sampleGoogleSearchPortProxyid" scope="session" class="GoogleSearch.GoogleSearchPortProxy" />
<%
    if (request.getParameter("endpoint") != null && request.getParameter("endpoint").length() > 0)
        sampleGoogleSearchPortProxyid.setEndpoint(request.getParameter("endpoint"));
%>


다양하게 안해봐서 항상 같은지는 모르겠지만 보통 위와 같은 코드는 기본적으로 들어간다. 물론 WSDL마다 이름은 달라지겠지 GoogleSearchPortProxy의 Bean을 생성하고 엔드포인트(정확한 의미는 모르겠다.)를 생성한다. 이정도가 기초작업인것 같다. 그 다음부터는 그냥 Bean의 객체를 사용해서 자바에서 메서드 사용하듯이 GoogleSearchPortProxy를 호출하고 파라미터를 넘겨주면 된다.

위의 예시해서 한 GoogleSearch에서는 이런 형태가 없었지만 내가 만진 WSDL에서는 다음과 같은 형태가 있었다. 메서드 동작은 중요하지 않으니 정의형 형태만 보자

public void getInfo(java.lang.String strID, javax.xml.rpc.holders.IntHolder getInfoResult, javax.xml.rpc.holders.StringHolder strInfo)

WSDL을 가지고 이클립스에서 자동생성을 했더니 저런식으로 만들어 주었다. 여기서 API정의를 보면 실제 내가 넘기는 파라미터는 strID뿐이고 getInfoResult와 strInfo는 내가 메서드 호출 결과로 받아야 할 리턴값들이었다. 생전 처음보는 타입들이었기 때문에 고생을 좀 했는데 Holder라는 타입의 변수를 미리 정의해 놓고 메서드 호출할 때 파라미터로 넘겨주면 메서드 호출후 해당 변수에 결과값이 할당된다.(결과값이 여러개인 API정의를 보고 신기했는데.. 이것 말고 다른 방법이 있는지 모르겠지만 일단 이클립스에서는 이렇게 생성을 해 주었다.)

Java

javax.xml.rpc.holders.IntHolder infoResult= new javax.xml.rpc.holders.IntHolder(-1);
javax.xml.rpc.holders.StringHolder info= new javax.xml.rpc.holders.StringHolder("");

Proxyid.getInfo(id, infoResult, info);

System.out.println("result : " + infoResult.value);
System.out.println("info: " + info.value);


결과값을 가져올 때는 value속성을 이용해서 가져온다. 이렇게만 하면 웹서비스 클라이언트를 이용할 수 있다. XML로 된 WSDL문서만 가지고 이렇게 자동화 할 수 있다는 점은 참 신기하긴 하다.





전체에 구동에 대해서 이해하지 못한채로 구현에만 초점을 맞추는 것은 내가 추구하는 방식은 아니지만 항상 그렇게만 할수는 없는 노릇이니까(특히 이번처럼 파악해야 할 것의 덩치가 무지 큰 경우에는....) 다음에 또 접할 기회가 생기면 더 잘 이해할 수 있겠지....

[JAVA]TOMCAT 5.5에서 GET방식으로 한글파라미터 사용하기..

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

JEUS를 사용하다가 톰캣으로 넘어왔더니 GET방식으로 한글 파라미터를 넘기는 것이 되지 않았다. POST전송이야 알아서 되니까 괜찮고 GET방식으로 파라티터를 넘길 때 URL Encoding과정을 거쳐야 된다. 영문,숫자는 괜찮지만 특수기호나 한글이 들어가게 될 경우 주소창에 표시되는데 문제가 있기 때문에 URL Encoding해서 보내준다.

주소창에 %BF%D5%B1%E2%C3%E1 같은 형태로 쓰여진 것을 본적이 있을텐데 이것이 인코딩을 해준 것이다. 당연히 받을때는 디코딩을 해주고... 그냥 파라미터는 엔코딩한다고 생각하는게 차라리 맘편하다.

String encode(String s,String enc) 의 형태를 띄고 있다. 첫번째 파라미터는 엔코딩할 스트링이고 두번째 파라미터는 캐릭터 엔코딩 타입이다. URLEncoder.encode("블로그","utf-8") 와 같은 형태로 사용한다. URLEncoder는 java.net에 정의되어 있다.

근데 잘 돌아가던 것이 WAS를 변경해서 톰캣 5.5로 넘어왔더니 별 짓을 다해도 한글 GET파라미터가 도저히 먹지를 않았다.

톰캣설치폴더\conf\server.xml 파일에서 90~100라인정도에 보면 다음과 같은 내용이 있다.

Xml

<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
<Connector port="8090" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />

<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector className="org.apache.catalina.connector.http.HttpConnector"
           port="8443" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" disableUploadTimeout="true"
           acceptCount="100" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"  >


서버 설정에 따라서 세부 내용은 약간 다를 수는 있다. 이곳에 URIEndode부분을 추가해 준다.



Xml


<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
<Connector port="8090" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="utf-8" />

<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector className="org.apache.catalina.connector.http.HttpConnector"
           port="8443" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" disableUploadTimeout="true"
           acceptCount="100" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS" URIEncoding="utf-8" >



이렇게 설정해 주고 톰캣을 restart시키면 한글 GET파라미터가 먹는다. 원칙상으로는 디코딩을 해주어야 하지만 <% request.setCharacterEncoding("utf-8"); %>를 상단에 선언했을 경우 자동으로 처리해 주기 때문에 굳이 디코딩까지는 안해주어도 상관없다.

이 부분에 대해서는 권남님의 포스팅에 잘 정리되어 있으니 자세한 내용은 그곳에서 참고...

[DEV]Silverlight 1.0 을 Javascript로 다뤄보기..

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

요즘 한꺼번에 이것 저것 보느라고 좀 어렵긴 한데 실버라이트는 주워만 듣다가 처음 배우니까 전체 개념을 잡기가 쉽지 않았다. 이것저것 배우고 있기는 한데 전체 그림을 아직 못그리고 있으니까 헷갈리기도 하고 맞는건지 아닌건지 잘 모르겠고 포스팅을 하려면 좀 정리가 되어야 하는데 정리가 되지 않는 상황이다.

그래서 포스팅을 미루고 있긴 했는데 또 그러니까 배운것도 정리가 안되서 계속 다음수업나올때 마다 헷갈려서 배운거라도 좀 정리해서 내껄로 만들어야 겠다. 2차적으로 정보공유에 목적을 두고 내가 알게 된 지식은 공유한다는 원칙을 가지고 있지만 1차적인 블로그의 목적은 내가 배운걸 더 잘 기억하고 나중에 쉽게 찾아볼 수 있게 해서 삽질을 줄인다는데 그 목적이 있으니.... (잘못된 정보 전달을 하게 될까봐 좀 신경쓰이긴 하지만 그런 부분은 다른 고수분들이 지적해 주실꺼라고 생각하고.. ㅎㅎ)


잡설이 길었으니 이제 자바스크립트로 핸들링을 해보자. 앞의 포스팅에서 얘기했듯이 1.0에서는 실버라이트를 자바스크립트로 핸들링한다. 이전 포스팅에 있던  XAML을 가져와보자.

Xml

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="silverlightOnLoad" >
    <Ellipse Height="100" Width="100" Stroke="Black" StrokeThickness="10" Fill="SlateBlue" x:Name="ellipse1" />
</Canvas>


Canvas태그에 Loaded라는 속상을 추가했다. 이 속성을 추가하면 실버라이트가 로드된 후에 자바스크립트에서 Loaded속성에 지정한 이름의 함수를 찾아서 호출한다. 당연히 자바스크립트에 silverlightOnLoad라는 이름의 함수가 정의되어 있어야 한다. 기본적인 초기화(?)는 XAML파일에서 하지만 그외에 실버라이트가 로드된 다음에 처리해야 할 것 있다면 여기서 해주면 된다.

Ellipse의 속성으로 x:Name를 추가했다. 여기서는 x라는 네임스페이스를 사용했는데 네임스페이스는 최상위 Canvas태그 내에 지정되어 있다. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 의 코드가 네임스페이스를 지정하는 부분이고 Name를 사용하려면 이 부분이 지정되어 있어야 한다.



이제 자바스크립트로 핸들링을 해야 하는데 어느 것이나 마찬가지듯이 핸들링을 하려면 하기전에 일단 엘레먼트를 선택해야 한다. 어떤걸 가지고 핸들링 할건지 선택해야 머 핸들링하든지 말든지 할것 아닌가...

JavaScript

function silverlightOnLoad(sender, args) {
    alert("sivlerlight has Loaded");
            
    var element = document.getElementById("silverlightControl").content.root.Children.GetItem(0);
    //var element = sender.gethost().content.root.Children.GetItem(0);
    //var element = sender.findname("ellipse1");
    alert(element);
}


위의 함수를 넣으면 실버라이트 객체가 로딩됨과 동시에 sivlerlight has Loaded라는 메시지가 출력된다.  loaded함수는 2개의 object파라미터를 넘겨받는다. sender와 eventArgs인데 sender는 말 그대로 함수를 호출한 객체이고 eventArgs는 안써봐서 솔직히 잘 모르겠는데 MSDN에는 "This parameter is always set to null"라고 나타난다. ㅡ..ㅡ 위의 소스에서 sender는 Canvas가 된다.





그 다음에 XAML에 있는 Ellips 객체를 다루기 위해서 객체를 찾아야 한다. 4,5,6번줄은 모두 같은 결과가 나온다. 3가지 방법중(내가 알고 있는...) 편한 방법을 사용하면 된다.

실버라이트객체의 content에 root가 최상위 Canvas이다.(xaml파일에서 최상위에 볼수 있는 Canvas태그. 최상위 Canvas라고 한 것은 Canvas안에 또 Canvas가 들어갈 수 있기 때문이다.) 이 최상위 Canvas의 자식들(Children)중에서 GetItem을 통해서 원하는 객체를 찾아낼 수 있다.

4번 줄은 실버라이트객체를 통창적인 자바스크립트 코드를 이용해서 찾았다. 이전 포스팅의 html소스를 보면 실버라이트를 불러오는 object태그의 이름을 silverlightControl라고 준 것을볼수 있고 그냥 그 Object태그를 찾아온 것이다.
5번줄은 getHost() 메서드를 이용한 것이다. 실버라이트의 어떤 오브젝트에서도 getHost()를 사용하면 최상위 실버라이트객체를 얻어낼 수 있다. 솔직히 여기서는 sender가 Canvas이기 때문에 sender.gethost().content.root로 Canvas를 찾은 것은 다시 올라갔다가 원래 위치로 돌아온 좀 멍청한 짓이긴 한데 그냥 이런식으로 찾는다는 것을 알기 위해서...
6번줄은 제일 많이 사용하지 않을까 싶은데 sender의 객체로 findname()를 사용해서 해당이름의 엘레먼트를 찾아온 것이다. 자바스크립트의 document.getElementByID()처럼 직관적이다. GetItem()같은 경우는 위치가 바뀌면 소스도 바꾸어 주어야 하기 때문에.... findname()메서드는 어떤 Dependency Object에서라도(Dependency Object는 모든 실버라이트 Object의 최상위 객체이다.) 그 xaml의 엘리먼트를 찾아올 수 있다.

3가지중 어떤것을 쓰던지 간에 위코드에서는 alert메시지로 "Ellipse"가 튀어나온다.






그럼 이제 다룰 엘리먼트를 찾았으니까 먼가 해야지. Ellipse를 클릭하면 Rectangle가 생기도록 해보자. 위 함수의 마지막줄에 아래 코드를 추가하자.

element.AddEventListener("MouseLeftButtonDown", createRectangle);

MSDN에 보면 AddEventListener에 대한 정의가 다음과 같이 나온다.

object.AddEventListener(eventName, functionReference)
첫번째 파라미터는 이벤트이름이고 두번째가 해당이벤트에서 실행할 참조함수이다. 해당 object에서 eventName가 발생하면 functionReference()를 실행하는 것이다. eventName의 종류에 대해서는 해당 MSDN을 참고하면 된다. 즉 위의 코드는 Ellipse를 마우스 왼쪽클릭하면 createRectangle()를 실행하라는 뜻이다.

JavaScript

function createRectangle(sender, args) {
    var obj = document.getElementById("silverlightControl");
            
    var rect = obj.content.createFromXaml("<Rectangle />");
    rect["Canvas.Left"] = 150;
    rect["Canvas.Top"] = 10;
    rect.Width = 100;
    rect.Height = 100;
    rect.Stroke = "red";
    rect.Fill   = "SlateBlue";
    rect.StrokeThickness   = "5";

    obj.content.root.children.add(rect);
}


silverlightObject.content.CreateFromXaml(xamlContent)를 이용해서 XAML에 Rectangle엘레먼트를 추가하고 속성값을 할당한다. 그리고 add()함수를 이용해서 Rectangle엘리먼트를 추가하는데 여기서는 최상위 Canvas에 추가할 것이므로 document.getElementById("silverlightControl").content.root.children에다가 add를 해준다. 이렇게 해주면 Ellipse를 클릭했을때 Rectangle이 화면에 나타난다.


물론 이건 자바스크립트로 다루는 걸 익히기 위해서 이렇게 한것이지 동적으로 자바스크립트에서 다 생성할 필요없이 메타데이터의 역할인 XAML에서 생성하는 것이 훨씬 좋은 방법이다. 그게 메타의 역할이니까...

[JS]prototype.js로 URL의 쿼리스트링 값 가져오기 (parseQuery,toQueryParams)..

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

GET방식의 호출을 하면 주소뒤에 ?id=3&nick=outsider 같은 형식의 쿼리스트링이 붙는다. 이런 부분은 JSP나 ASP에서는 request객체를 이용해서 가져올 수 있지만 Javascript에서 이것을 다뤄야 할 때도 있다.

window.location.search

를 이용하면 ?id=3&nick=outsider라는 쿼리스트링이 그대로 튀어나온다. 이걸 그대로 가공해서 사용해도 되지만 prototype.js는 이걸 위한 메서드를 제공한다. (window.location.search는 prototype.js에서 제공하는 것은 아니고 javascript에서 제공하는 것이다.)

parseQuery()
toQueryParams()

Prototype Framework의 API문서를 보면 parseQuery()은 "toQueryParams()의 별칭"이라고 나온다. 결국 기능은 toQueryParams()만 있는건데 쿼리스트링을 파라미터와 값의 쌍으로 된 Object를 리턴해 준다. API문서에 자세한 예시들이 있기 때문에 보면 금방 이해가 될 것이다.

만약 http://www.test.com/test/test.jsp??id=3&nick=outsider 라고 호출했을 경우 다음 코드를 실행하면 주석해 보시된 내용의 값을 출력해 준다.

JavaScript

//var params = window.location.search.parseQuery();
var params = window.location.search.toQueryParams();
                
alert(window.location.search); // ?id=3&nick=outsider
alert(params.id);                    // 3
alert(params.nick);                 // outsider


1번과 2번줄은 아무것이나 사용해도 차이가 없다.

만약 정의되지 않거나 값이 없는 파라미터를 가져오려고 하면 undefined가 나온다.

[HTML]괜찮은 온라인 칼라피커..

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

칼라피커를 꽤 오랫동안 찾았다. 개발을 하다보면 아무래도 칼라 Hex코드가 상당히 필요하다. #000000이나 #FFFFFF정도는 외우고 있다고 하더라도 그레이칼라정도는 대충 느낌으로 할 수도 있지만 칼라는 원하는 칼라의 Hex를 찾기가 쉽지는 않다. 전에는 포토샵에서 스포이트로 찍어서 사용했는데 회사에는 포토샵이 없으니 그럴 수도 없는 노릇이었다.

Hex는 써야겠는데 익숙한 툴은 없다보니 자연히 온라인으로 눈이 갔다. 편하게 원하는 Hex값을 찾을 수 있는데가 없을까 하고 오랫동안 찾아다녔다. 네이버에서 찾으면 칼라표가 많이 나오는데 색상이 많으면 칼라표도 너무 길어지고 원하는 칼라를 찾기가 쉽지 않았다. kulerCOLOURIovers같은 사이트들도 있었지만 이런 곳은 디자이너들이 어울리는 색 매칭을 찾기 위한 곳이지 내가 원하던 것은 아니었다. 그러다가 fabooti라는 칼러피커 사이트를 찾아서 약간 썼었는데 다양한 기능이 있기는 했지만 나로서는 인터페이스가 좀 불편한 느낌이었다.


그러다가 찾았다.

colorpicker.com Logo

당황스럽게도 도메인도 너무나도!!! 직관적인 도메인의 사이트였다. colorpicker.com

Color Picker

아~~ 이 심플하고 직관적인 인터페이스!!! 내가 익숙한 포토샵의 칼라피커 인터페이스를 그대로 따온듯 하다. Hex코드도 바로바로 적용되서 나오고 Hex코드를 복사하기도 무척 쉽다. 다른 쓰잘데없는(최소한 나한테는) 기능없이 단순히 칼라피커의 역할에만 충실한 것이 딱 맘에 든다. 칼라피커 이정도 직관성은 있어야지.. ㅋㅋㅋ

IE 6,7, Firefox 2,3, Opera 9, Safari 3.1에서 모두 잘 돌아간다. ㅋㅋ

[Book] Short Coding - 알고리즘 트레이닝으로 배우는 코드 단축기법..

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

Short Coding - 8점
Ozy 지음, 서수환 옮김/한빛미디어



제목과 표지디자인이 인상깊어서 구입을 했다. 그리고 어떤 책을 볼까 하다가 집어 들었다.

내 개발 경험이 아주 얕기는 하지만 그래도 주워들은건 좀 있는데  이 책의 저자가 얘기하는 코딩의 세계는 아주특이하고 나로써는 처음 보는 것이었다. 이 책은 내가 보통의 기대하던 알고리즘을 이용한 코드단축이라던지 리팩토링 기법, 퍼포먼스 향상을 위한 튜닝 같은 부분에 대한 내용이 전혀 아니었다. 솔직히 읽기 전에는 그런 부분을 기대했었다.



여기서 말하는 숏코딩은 말 그대로 숏코딩이었다. 어떤 문제를 해결하기 위해서 소스를 얼마나 짧게 짜는가이다.  어떤 알고리즘적인 문제를 해결하는데 그냥 해결만 하는 것이 아니라 계속 고드단축을 시도해서 단축할 수 있는 데까지 단축하는 것이다. 여기서는 보통 PKU 온라인 심사(POJ)라는 국제 대학 프로그래밍 컨테스트에 도전하는 학생들을 위해서 만들어진 여러문제에 대해 각종 언어로 컴파일하고 실행해 볼 수 있는 사이트를 이용하고 있다.

어쨌든 이럭게 숏코딩을 하다보니 상당히 변태(?)적이 코드가 나온다. 컴파일러의 특징을 이용해서 include문을 아예 없애버린다던지 for문에 조건을 다 안준다던지, 변수선언에서 한바이트를 줄이기 위해 전역으로 선언한다든지 하는..... 완성된 코드를 보면 이게 코드인지 암호인지 모를정도이다... 보통 얘기하는 가독성, 정형화된 문법은 여기서 신경쓰는 바가 아니다.

이런 도전을 한다는 것이 나에게는 꽤나 흥미로왔다. 이런 세계도 있구나 하는..... 이책에서는 대부분의 소스를 C로 작성하고 있다. 대학때 잠시 배운 C실력으로 이해하기는 무리라고 생각했으나 후반부에 자바도 한색션정도 나오는데 역시 이해를 못했다. (ㅡ..ㅡ)


지은이도 얘기하듯이 여기서 배운 테크닉을 써먹을 수 있냐 하면 그렇지는 않다.  하지만 숏코딩을 하려면 알고리즘과 언어에 대한 충분한 이해가 필요하고 이런 도전을 하면서 지식은 더욱 늘어나고 가독성을 고려하지 않은 복잡한 소스를 보면서 독해력도 늘어갈 수 있다. 어려운 문제에 도전해서 내공을 높인다는 것인데 확실히 이걸하려면 보통 실력으로는 쉽지 않겠다는 생각은 든다.

처음 코딩을 하면 이것저것 해보고 싶은데 뭘 해야할지 막막할 때가 상당히 많은데 이럴 때 POJ의 알고리즘들을 (숏코딩은 아니더라도) 시도해 보면 공부에 큰 도움이 될꺼라고 생각한다. 당연히 쉬운 문제들은 아니다.

원래대로라면 문제하나하나를 다 같이 고민하고 짜보면서 해야 진짜일텐데 일단 C는 내 분야가 아니기도 했고 그렇게 읽으면 책읽는 속도가 너무 느려지기 때문에 속독하듯이 가볍게 본 편이다. 나에게 큰 도움을 준 책은 아니지만 상당히 신선한 충격을 주어서 별 4개

[DEV]Silverlight 1.0 시작하기..

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

지난 주 부터 실버라이트 교육을 받고 있다. 가끔 회사에서 직장인 환급 교육관련해서 메일이 오곤 했는데 그닥 눈에 띄는 것도 없고 교육에 대한 자세한 내용도 없고 해서 크게 신뢰할 수도 없다보니 그냥 항상 지나쳤었는데 이번 교육과정들은 웹개발쪽만 있어서 고민을 좀 했는데 마침 실버라이트 1.0/2.0 강좌가 눈에 띄어서 듣기로 했다.

어차피 내돈은 한푼도 안드는거고 주말에 시간만 좀 투자해 주면 되는거였기 때문에... ㅎㅎ 실버라이트 혹은 RIA관련 기술에 대한 관심이 계속 있었지만 다른 일에 치여서(핑계겠지만...) 시작을 전혀 못하고 있었는데 교육을 받으면 반강제(?)적으로도 하게 되고 새로운 랭귀지라서 기초만 좀 익히면 그 다음은 혼자서도 어느정도 할 수 있을 것이라고 생각을 해서 신청을 했다. 그래도 8주 주말 압박은 좀.. ㅡ..ㅡ




어쨌든 지금은 실버라이트 1.0을 배우고 있다. 내가 좀 착각하고 있던 것이 1.1을 없어지다 보니까 1.0도 신경을 안써버리게 된것.... ㅡ..ㅡ

일단 시작이니까 실버라이트 얘기를 좀 하면 MS가 작년에 RIA기술로 실버라이트1.0이라는 기술을 발표했다. 실버라이트는 웹에서 사용할 수 있는 RIA기술로서 윈도우즈 Vista가 출시되면서 등장했던 WPF의 일부기능을 추려서 실버라이트라고 내 놓은 것이다. RIA시장은 현재는 Flash/Flex가 장악하고 있다고 생각하고 있고 실버라이트가 최근에 치고 올라오고 있고 그 외에도  OpenLaszlo나 JavaFX등이 있다.



실버라이트는 브라우저별로 실버라이트 런타임만 설치하면 사용할 수 있기 때문에 플래시 플레이어처럼 어느정도 보급만 되면 불편없이 자연스럽게 사용할 수 있다. 자세한 내용은 잘 모르지만 리눅스 쪽에서도 문라이트라는 녀석이 있어서 리눅스에서도 실버라이트를 볼 수 있다.(실제로는 호환성이 어떤지 모르겠지만... 지금도 베타가 계속나오는 통에 윈도우에서도 런타임 설치에 좀 문제가 있는듯... 파폭에서 잘 설치 안될때도 많고... ㅎ)

실버라이트 1.0은 자바스크립트와 XAML로 이루어져 있다. 그래픽적인 요소들의 정보를 XAML이라는 이름의 XML로 가지고 있고 이것을 자바스크립트로 다루어서 동작하도록 할 수있다. 블랜드라는 툴을 이용해서 디자이너들은 XAML파일을 내보낼 수 있고 개발자는 XAML파일을 이용해서 비쥬얼 스튜디오로 실버라이트 개발을 할 수 있는 협업구조이다.(이런 형태의 협업은 Flex쪽에서도 거의 동일한듯....)

1.0은 내가 보기에는 발표정도의 의미가 강하다. MS가 우리 이런거 한다 하면서 시장 분위기 조성하고 준비하기 위한.... 모두가 알고 있듯이 진짜는 실버라이트 2.0에 있다. 원래는 1.0을 출시하고 올해 1.1을 출시하려고 했지만 MS에서 준비하다보니 1.1의 분량이 너무 많아서 1.1의 이름은 2.0으로 변경하였다. 2.0에서는 C#을 포함하여 여러가지 언어를 지원하고(정확한 지원 언어에 대해서 못찾겠네) 1.0에서 안되던 많은 부분을 지원하고 있어서 많은 사람들이 기대를 하고 있고 현재 Beta 2까지 나와있는상태이다.





일단 실버라이트를 돌려보자. 새로운 언어를 만나면 시작이 Hello World이듯이 실버라이트도 일단 띄워야 멀 하든지 말든지 할 것 아닌가. 현재 실버라이트 1.0에 대해서만 배우고 있는 관계로 일단 1.0에 대해서만 얘기한다. 2.0은 추후에....

Html

<object type="application/x-silverlight" id="silverlightControl" width="300" height="300">
    <param name="source" value="XMLFile.xaml"/>
    <param name="background" value="#1b2d3d" />
    <param name="onError" value="onSilverlightError"/>
</object>


Html파일안에 위처럼 Object태그로 이용해서 삽입할 수 있다.  background속성은 페이지의 배경색과 맞추기 위해서 넣은 속성이다. source 프로퍼티로 XAML파일을 지정해 준다. 어떤 내용을 어떻게 보여줄 지에 대한 정보를 답고 있다. 여기서는 간단한 도형만 보여준다.

Xml

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Ellipse Height="200" Width="200" Stroke="Black" StrokeThickness="10" Fill="SlateBlue" />
</Canvas>


위의 XAML파일은 Silverlight 1.0 QuickStarts에서 가져왔다. XAML에 대한 내용을 작성하기는 양도 많고 어디서 부터 해야할 지도 몰라서...



물론 실버라이트를 보려면 실버라이트 런타임이 설치 되어 있어야 하고 실버라이트가 설치되어 있지 않을때 자동적으로 인스톨링크가 연결된다거나 하는 처리는 되어 있지 않다. 실버라이트를 설치하려면 실버라이트 설치페이지를 통해서 설치할 수 있다. 책에는 Object태그로 실버리아트를 임베드하는 것은 사파리에서는 돌아가지 않아서 embed태그를 써야한다는데 런타임이 2.0으로 업데이트되서인지 지금은 object태그로 4대브라우저(IE, 파이어폭스, 오페라, 사파리)에서 다 잘 돌아간다.


덧) 이것저것 배우고 있기는 한데 아직 정리가 안되서 포스팅하기가 쉽지 않네....