최근 정말 우연히 Programming Erlang(조 암스트롱, 인사이트)이라는 책을 접했는데, 함수형 언어이고 분산 처리에 적합하게 설계되며 실제로 많이 쓰이고 있다는(!) 것에 감명을 받아 열심히 공부하고 있다. 아직 다 읽지는 못했지만 공부 한 내용을 블로그에 정리해 두려고 한다. (아직 공부한 지 일주일도 되지 않아 코드가 세련되지 못할 수도 있으니 코멘트 부탁드립니다.)
얼랭을 처음 보았을 때의 느낌은 함수형 언어라는 면에서는 LISP와 굉장히 닮았고(실제로 LISP의 많은 철학과 용어를 차용한 것 같다) 문법은 Scala와 많이 유사하다는 것이었다. 일반적으로 C나 Java와 같은 언어로 프로그래밍을 시작한 사람들에게 있어 가장 혼란스러운 부분은
변수가 없다.
반복문이 없다.
일 것이다. 저장해야 할 자료는 모두 함수의 매개변수에 담아 놓고, 반복문을 작성하는 대신 함수를 재귀호출해야 한다는 함수형 언어의 특징이 낯설 수도 있었을텐데, 다행히 나는 Scheme에 조금은 익숙한 상태라 큰 반감 없이 받아들일 수 있었다.
그럼 본론으로 넘어가서 Erlang으로 Factorial을 계산하는 코드를 작성해 보고 실행 시간을 비교해 보고자 한다. 우선, 가장 쉽게 생각할 수 있는 코드는 다음과 같을 것이다.
좋은 코드이지만, Erlang의 장점인 병렬 처리를 충분히 활용하지 못한 코드인 것 같다. 이번에는 병렬 처리를 위해 다음과 같은 코드를 생각할 수 있다.
이 코드는 크게 네 부분으로 구성된다. 우선 fact/1은 작은 문제의 답을 모으는 collector를 띄운 후 문제를 작은 문제로 분할한다. 이 때 작은 문제의 크기는 T의 값에 의해 결정된다. 우선은 T=10000이라는 상수로 두었다. split/4는 문제를 작은 문제들로 분할하는 함수이다. 큰 문제를 T 이하의 크기의 작은 문제 하나와 나머지 크기의 문제로 나눈 후 각각을 푸는 방식이다. 일종의 Divide & Conquer라고 생각할 수도 있겠다. fact/2, fact/3은 먼저 살펴 본 코드와 크게 다르지 않고, 다만 값을 반환하는 것이 아니라 C로 보낸다는 것이 다르다. 마지막으로 collector/3은 작은 문제의 개수를 기억하고 있어서 그 개수 만큼의 답을 얻으면 얻은 답의 곱을 fact/1로 보낸다.
가령 50000!을 계산하고자 한다면, 이 코드는 10000! * (10001 * ... * 20000) * ... * (40001 * ... * 50000)을 계산할 것이다. 싱글 코어라면 오히려 문제를 분할하고 합치는 데에 overhead가 발생하여 성능 저하가 일어나겠지만, 멀티 코어 시스템에서는 작은 문제를 각 코어에서 처리할 수 있으니 더 빠른 성능을 보여 줄 것이라 기대할 수 있다.
실제로, 성능 분석을 해 보면 50000!을 계산하는 데에 처음 제시한 코드는 3095ms, 병렬 처리를 사용한 두 번째 코드는 1059ms가 소요되었다.(i3 머신에서 statistics/1 사용하여 5회 테스트 한 평균) 대략 3배 정도 빠르다는 것을 알 수 있다!
심심하여 큰 수를 자유롭게 계산할 수 있는 또 하나의 언어인 Python으로도 팩토리얼을 구하는 함수를 작성한 후 분석을 해 보았다.
같은 조건에서 5회 테스트 평균을 구해 보았더니 5999ms가 나왔다. 이것은 병렬 처리를 사용하지 않은 Erlang 버전의 2배, 병렬 처리를 사용한 Erlang 버전의 6배 수준이다. 아, Erlang 좋구나.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
C에서 코드 길이를 줄이고 깔끔하게 만들기 위해 많이 사용하는 것이 바로 삼항 연산자(ternary operator)이다. ?:으로 구성되는 삼항 연산자의 사용법은 다음과 같다.
result = Condition ? resultWhenTrue : resultWhenFalse;
위 코드는 Condition이 true일 때 result에 resultWhenTrue가 대입되고, Condition이 False일 때 result에 resultWhenFalse가 대입된다. if문을 쓰면 오히려 소스가 보기 싫어지고 이해하기 어렵게 될 때 복잡한 연산 사이에 잘 사용하면 참 간편한 녀석이다.
그러나 Python을 배우면서 삼항 연산자는 공부한 기억이 없다. 코딩을 하면서 색상값을 증가시켜야 하는 부분이 있었다. 색상값이기에 최댓값을 255로 제한해야 했는데, C 같았으면 삼항 연산자를 이용해서 할 터였다. newColor=(oldColor*factor)>255?255:oldColor*factor와 같이 말이다. 그러나 Python에서는 if문을 쓰자니 지저분해지고, 분명히 다른 방법이 있을 것이라는 생각이 들어 찾아보았더니 여러 가지 방법이 존재했다.
2.5부터 지원되는 공식 삼항 연산자
다행스럽게도, Python 2.5부터 기본적으로 공식 삼항 연산자가 지원된다고 한다. C와 비교하면, ?와 : 대신 if, else를 쓰고, 순서가 조금 바뀌었다.,
result = resultWhenTrue if Condition else resultWhenFalse
읽었을 때 자연스럽게 의미가 있는 문장으로 읽히는 것은 좋지만 resultWhenTrue와 resultWhenFalse 사이에 Condition이 들어 있어 가독성 면에서는 조금 부정적인 면이 있지 않나 생각한다.
튜플을 이용한 방법:
Python에서 True는 1이고, False는 0이다. 따라서 조건을 시퀀스의 인덱스로 사용할 수 있다.
result = ( resultWhenFalse, resultWhenTrue )[ Condition ]
형태는 간결하지만 처음 보는 사람의 경우 그 의미를 이해하기까지 시간이 걸린다. 또한 resultWhenFalse와 resultWhenTrue를 미리 계산해 놓기 때문에 미리 계산하면 안되는 경우(조건에서 인덱스의 범위를 검사하여 범위 안에서만 원소에 접근해야 하는 경우 등)에는 부적절하다.
논리 연산자를 이용한 방법:
x and y는 x를 먼저 실행한 후 결과가 False이면 x를 리턴하고, True이면 y를 계산한 후 이를 리턴한다. x or y는 x를 먼저 실행한 후 결과가 True이면 x를 리턴하고, False이면 y를 계산한 후 이를 리턴한다. 자세한 설명은 Documentation에 잘 나와 있다. 이와 같은 특성을 이용하면 논리 연산자로도 삼항 연산자를 구현할 수 있다.
result = Condition and resultWhenTrue or resultWhenFalse
만약 Condition이 True라면 and 연산자는 resultWhenTrue를 리턴할 것이다. resultWhenTrue가 True라면 or 연산자는 resultWhenTrue를 리턴하므로 결과적으로 전체 문장은 resultWhenTrue를 리턴한다. 만약 Condition이 False라면 and 연산자는 Condition, 즉 False를 리턴할 것이다. or 연산자는 앞에 있는 문장이 False이므로 뒤에 있는 resultWhenFalse를 리턴하므로, 전체 문장은 resultWhenFalse를 리턴한다. 이 방법의 큰 문제는 resultWhenTrue가 항상 True일 때에만 사용할 수 있다는 것이다. 만약 resultWhenTrue가 False라면 Condition이 True일 때 or 연산자는 resultWhenTrue 대신 resultWhenFalse를 리턴할 것이다. 이를 해결하기 위해 약간의 수정을 한다.
result = (Condition and [resultWhenTrue] or [resultWhenFalse])[0]
resultWhenTrue를 담고 있는 리스트는 항상 True이므로(원소 개수가 1개 이상이면 True) 둥근 괄호는 resultWhenTrue와 resultWhenFalse 중 하나를 원소로 가지는 리스트를 리턴할 것이고, 이의 첫 번째 원소를 취하면 우리가 원하는 값을 얻을 수 있다. 논리 연산자의 특성상 이 방법은 조건이 거짓일 때에는 아예 resultWhenFalse를 계산하지 않는다.
2.5버전부터는 새로운 연산자가 생겨 굳이 편법을 사용하지 않아도 되게 되었지만 편법을 쓴 사람들이 쓴 다른 코드를 읽을 때에는 조금 도움이 되지 않을까.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
9월 초순부터 중순까지는 원서 접수 기간이다. 인곽에서 주로 지원하는 대학은 서울대학교, KAIST, POSTECH, 연세대학교 등이다. 올해는 GIST가 학사 과정을 개설하면서 선택의 폭이 조금 넓어졌다. 그러나 세종 과학고등학교가 첫 졸업생을 내면서 경쟁자가 170여명 늘어나기 때문에, GIST의 선발 인원 80명으로 이를 완충시키기에는 조금 부족한 듯 보인다. 나는 KAIST를 주력으로 해서, GIST와 연세대학교에 원서를 넣었다.
방학이 끝나고부터 열심히 쓰기 시작한 자기소개서는 9월 초에 마무리가 되었다. 각 학교별로 요구하는 사항이 비슷하기 때문에 하나만 잘 써 놓으면 쓰는 데에 크게 어려움은 없었다. 다만 GIST는 과학 기술의 긍정적 측면과 부정적 측면, 그리고 우리가 가져야 할 자세에 대해 에세이를 쓰라고 요구해서 조금 힘들기도 했다. 나름대로 열심히 쓴다고 자료 조사도 많이 하고 책도 참고해가면서 썼지만, 별로 개성 있는 글이 나온 것 같지는 않아서 많이 아쉽다.
이번 금요일에 가장 마지막으로 KAIST의 원서 접수가 시작되었다. KAIST 원서 접수만 마무리 되면 모든 원서 접수는 끝나고 정말로 공부 할 일 밖에 남지 않게 된다. 그러나 사실 어떻게 공부를 해야 할지를 잘 모르겠다. 화학을 좋아하는 학생은 화학을, 물리를 좋아하는 학생은 물리를 공부하면 되지만, 정보를 좋아한다고 정보를 공부하기는 많이 힘든 게 사실이다. 당장 닥친 입시에서 전문성 평가 과목에 정보는 없기 때문이다. 그러나 역시 자기가 좋아하는 과목을 공부하는 게 제일이라고, 수학 공부부터 해야 되는 것을 알면서도 우선순위는 컴퓨터 관련 책을 읽는 것이 더 높다. 그러니 늘 마음은 불편하다. 수학 문제를 옆에 놔두고 "Beginning Linux Programming"을 읽노라면 뭔가 찜찜하다.
그래도 이제 진짜 얼마 남지 않았으니 좋아하는 건 잠시 접어 두고 당장 해야 할 것을 해야겠다. 곧 끝나니까, 끝나고 진짜 좋아하는 걸 공부하려면, 지금은 일단 대학에 붙는 게 중요하니까 말이다. KAIST 10학번으로서 내년부터는 KAIST Life를 쓸 수 있도록!
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
초등학교 6학년 때 컴퓨터 선생님의 추천으로 처음 알게 된 정보올림피아드, 그 때부터 매년 도전해 왔지만 지금까지 전국 대회에는 단 한 번도 진출해 보지 못했다. 전국 대회랑은 연이 멀었는지, 번번이 진출에 실패해왔던 것이다.
5월 30일, 수학 수행 평가를 이틀 남긴 토요일이 지역 본선 시험일이었다. 올해부터 전국 대회 진출 인원이 한 명 확대되어 더욱 큰 기대를 가지고 쳤던 시험이다. 문제는 (적어도 나에게는) 작년보다 쉬웠다. 이 부분에 대해서는 많은 사람들의 의견이 엇갈리는 것 같지만, 그래도 대다수가 작년보다는 쉬웠다는 데에 동의할 것이라 생각한다.
시험 보고 난 느낌은 좋았다. 1, 2번은 정해(正解)로 푼 것 같고, 3번도 제법 괜찮게 푼 것 같았다.
6일 후인 6월 5일, 결과가 나왔다. 은상. 드디어 전국 대회 진출이구나 싶었다. 진출 인원이 한 명 확대된 덕을 봤다는 소리를 듣지 않아도 될 것 같아 다행이었다. 대상은 같은 학교 후배였다. 악마님도 은상, 축하합니다.
문제는 전국대회이다. 많이 어렵다지만, 열심히 준비해서 수상하리라.
p.s. 너무 오랜만에 쓰는 탓인지 영 글이 안써지네요.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
어젯밤 MBC 황금어장 <무릎팍도사>에 안철수가 출연했습니다.
그의 인생이야기를 들으면서 감동과 더불어 우리의 청소년들, 특히나 이다음에 우리사회의 리더의 역할을 할 가능성이 높은 과학고의 학생들이 꼭 봐야할 프로그램이라고 생각되었지만 볼수 없는 환경에 놓인 우리학생들을 위해 이글을 씁니다.
우리나라의 빌게이츠라고 빗댈 만큼 그는 존경받는 경영인이고 '시대정신'이라고 할수 있는 분입니다. 그는 자신을 비효율적인 의사라고 말했습니다.(힘든 의사공부를 마쳤지만 의학을 써먹지 못했으니까 효율성에 있어서는 매우 뒤떨어진 인간이었다고 말했다.)
27년간을 학생으로 살았고 의사였고 CEO였고 프로그래머였고 박사이고 석좌교수입니다.
그는 평범한 두뇌를 가졌다고 할 수없는 천재였지만 그보다 그를 더 존경할 수 있는 것은 남들보다 몇 배 더 노력하며 살았다는 것입니다.
매일 4-5시간을 자면서 의대공부와 백신 개발을 하는 생활을 7년동안이나 했다고 합니다. 돈을 벌기위해서나 자신의 영달을 위해서가 아니라 사회공익을 위해서, 자신이 사회로부터 받은 혜택을 사회로 돌려주어야 한다는 사명감에서 백신개발을 하고 무상으로 배포를 했다고 합니다.
의사로서 최연소 박사학위를 획득하고 모 대학의 학과장을 할 만큼 성공했다고 할 수 있었던 그가 백신프로그램 개발과 의사라는 직업 중에 과감히 의사라는 직업을 포기했고 그 선택에 대한 후회를 한 적은 없었다고 했습니다.
당시에 소프트 웨어시장은 돈도 되지않고 외면받 때였습니다.
그런데도 의사는 많았지만 백신 개발자가 없었기에 그는 과감히 백신개발자의 길을 택했다고 했습니다. 군대 입대하던 새벽까지도 V3프로그램을 완성시켜놓고 가야한다는 사명감으로 겨우 프로그램을 마치고 그냥 군입대를 하는 바람에 가족한테 입대한다는 말도 전하지 못했다고 했습니다. 그가 얼마나 책임감이 강하고 열정적인 사람이었는지 전율이 느껴질 정도였습니다.
1995년 안철수연구소라는 국내 최초의 보안 소프트웨어회사를 세웠으나 개인에게는 무상으로 백신을 제공하고 기업들에게만 회사유지를 위해 돈을 받기로 하였습니다.
어쩌면 그가 아니었다면 지금쯤 우리가 마음놓고 쓰고 있는 백신프로그램들을 외국의 보안회사에서 비싼값에 사서 써야하고 그렇게 되면 개인적으로나 국가적으로 엄청난 부의 유출이 되었을테고 안보의 핵심이라고 할 수있는 정보보안을 외국에 맡겨야하는 현실이 되었을지도 모릅니다.
보안회사를 차렸지만 늘 직원월급을 주는 일도 힘들었다고 합니다. 의사였던 아내의 월급으로 월급을 줄때도 있었다고 할 만큼 힘든 날들이 계속되었을 때 미국의 대기업에서 천만불에 안철수연구소와 V3를 팔라고 했지만 그는 단번에 'No'라고 했습니다. 그 이유는 자신에게는 돈밖에 돌아오는 것이 없지만 회사의 직원들은 모두 정리해고 당할테고 자국의 백신은 없어지고 외국기업의 백신이 지배하는 나라가 될 것이 뻔했기에 대답에 고민할 가치도 없었다고 합니다. 그는 진정한 애국자인셈입니다.
1997년 체르노빌 바이러스의 출현은 안철수연구소를 흑자의 반열에 올려놓는 계기가 되었습니다. 그때 사회적으로 엄청난 손실과 혼란이 있었기에 우리나라에서 처음으로 뉴스의 첫머리에 컴퓨터바이러스에 대한 소식이 전해지고 백신프로그램에 대한 관심이 증폭되었다고 합니다. 그 때를 계기로 그의 회사는 흑자 경영을 하게 되었다고 합니다.
그러나 그는 능력있는 사람이 사회에 도움을 주어야한다는 생각에서 회사가 가장 최고점에 이르른 시점에 과감히 CEO를 버리고 미국으로 경영학공부를 하러 떠나게 됩니다.
능력있는 사람들이 도덕성이 결여되고 책임감이 없을때 사회에 더 큰 해악이 된다는 그의 말이 오늘날 우리에게 시사하는 바가 크다고 생각되어집니다.
특별한 재능과 능력을 가지고 태어난 사람들이 자신이 가진것을 나누려 하지않고 자신의 영달만을 위해 살 때 그가 진정한 멋진 삶을 산다고 할수 없을 것입니다. 그런점에서 안철수는 진정 멋진 삶을 살고 있다는 생각이 들었습니다.
그는 담배도 하지않고 한때는 술도 마셨지만 지금은 술도 마시지 않고 물론 욕도 해본적이 없고, 그래서 무릎팍도사는 묻습니다. “그렇게 참고 살면 행복합니까?”
그러나 그는 참고 산 것은 아니라고 했습니다. 잠깐은 참지만 그렇게 오랜 세월을 어떻게 참고 살겠습니까? 저는 참고 산 것이 아닙니다. 그냥 내가 하고 싶은 일을 하고 그래서 행복합니다. 하고 말했습니다. 일탈을 모르는 청교도적인 생활을 해온 그였지만 그는 진정 행복한 사람으로 보였습니다.
그는 지금 카이스트 석좌교수로서 사회에 기업가정신을 불어넣고 후학들을 양성하는 일을 하고 있다고 합니다. 이처럼 멋진 그가 우리의 아이들에게 미래에 대한 희망과 꿈을 불어넣는 일을 하고 있다는 것이 너무나 마음 든든하게 생각되어집니다.
과학고에서 우리 미래를 이끌어나가려고 열심히 공부하고 있는 우리 아이들이 카이스트에 입학하여 이처럼 멋진 교수님 밑에서 진정한 삶이 무엇인지 배울 수 있다는 것이 어쩌면 제2의, 제3의 안철수를 배출할 수 있으리라는 믿음에서 우리미래의 희망을 보는듯했습니다.
그는 '자신에게 줄 수 있는 가장 큰 선물은 자신에게 기회를 주는 것이다' 라는 말을 했습니다. 우리 젊은이들에게 진정한 도전정신을 갖게 하는 말이라고 생각됩니다. 그는 우리 젊은이들이 도전정신이 없고 안정 지향적이라고들 하는데 그것은 우리사회구조가 도전정신보다는 안정적인 직장이나 황금만능주의로 내몰고 있는 현실 때문이라고 지적하였습니다.
진정으로 멋진 삶을 살 줄아는 행복한 안철수 그가 있어서 어젯밤 무릎팍도사를 보는시간내내 그의 해맑은 웃음만큼이나 행복한 시간이었습니다. 그리고 우리도 이처럼 존경할만한 사람이 있어서 든든하고 행복하였습니다.
좋은 글 감사합니다^^
1학년 때 존경하는 과학자에 대해 조사하고 발표하는 기회가 있었습니다. 그 때 제가 존경하는 과학자로 뽑은 분이 안철수 교수님이셨습니다. 말씀하신 것과 같이 사회 공익을 위해 열정적으로 도전하는 모습이 너무 아름다웠기에 가장 존경한다고 자신 있게 말할 수 있었습니다. 그 후로 귀국하셔서 KAIST 석좌 교수로 부임하셨다는 말을 듣고 너무 기뻤습니다.
이렇게 다시금 그 분을 생각나게 해 주시니 꼭 KAIST에 가야겠다는 마음이 더욱 절실해지네요. 감사합니다^^
왜 프로그램 이름이 記憶のカケラ가 되었냐고 하면 그냥 장난 삼아 X-Japan의 Rusty Nail이라는 곡의 첫 가사인 記憶のカケラ를 프로젝트명으로 삼은 것이 결국 프로그램 이름으로 굳어졌습니다. 본래 개인적으로 사용하던 콘솔판 프로그램의 이름은 'Memory Helper'였습니다(-_-).
아이콘도 도저히 만들 자신이 없어서 '내 그림' 폴더에서 가장 눈에 띄는 '귀리' 사진의 일부를 잘라서 만들었습니다. 누런 아이콘의 정체는 바로 '귀리'입니다.
단어장은 맨 윗줄에 단어의 개수가, 그 다음 줄부터 단어와 뜻이 번갈아 한 줄에 하나씩 있는 형태를 취합니다. 즉, 다음과 같습니다.
3 dog 개 cat 고양이 pig 돼지
아무튼, 첫 프로그램이다보니 이것 저것 부족한 게 많습니다. 단어장 형식도 제한이 심하고, 여러 가지 허접해 보이는 것이 사실입니다만, 자체 기능은 쓸 만 하니 너그러이 봐 주셨으면 합니다. 버그가 있을 경우 이 포스트에 댓글로 남겨 주시면 다음 판올림에 적용하도록 하겠습니다.
개발 환경 : Microsoft Visual Studio 2005 개발 언어 : Visual C# 개발 기간 : 약 1달
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
와우...이건 뭐 간지의 초절정이구만...ㅋㅋ
...라기보다 굳이 설치형식으로 만들 이유는 없어 보이는데......
...라기보다 글 제목이랑 파일 이름에는 1.00 버전인데 설치 프로그램에는 1.01 버전이라고 뜨는군..
...라기보다 태그에 Rusty Nail이랑 X-Japan은 왜 들어가 있는거냐...ㅡ.ㅡ;;
...라기보다 설치 폴더를 일본어로 하면 일부 컴퓨터에서는 문제가 생기잖냐...
...라기보다 단어장 파일은 유니코드 인식도 되는거냐?? UTF-16 LE, UTF-16 BE, UTF-8, ASCII 등 전부 됨?
버전 불일치는 실수.
굳이 설치 파일 형식으로 만든 건 .NET Framework 문제도 있고 sample wordlist도 설치하려고 한 것이지만.
설치 폴더가 일본어여서 문제가 생길지는 아직 잘 모르겠다만, 적어도 테스트에서는 아무 문제 없었고, 한국식 한자와 카타카나는 웬만하면 잘 지원하니까.
단어장은 다 인식 가능함.
사용해 보니 너무 좋은 프로그램입니다. 그렇치 않아도 제작자가 누구인가 궁금했는데 오늘 웹서핑중 제작자의 홈피를 알게되었습니다. 저는 이 프로그램으로 건축학에 대한 공부를 메모하여 암기하고 있는데, 공부성질상 답이 좀 길어서 답안난에 나오는 글자수를 현재보다 두배정도 키웠으면 하는 바램이 있는데 가능한지요? 좋은 프로그램 만들어주셔서 정말 감사드립니다.감사합니다. cindy6588@empal.com.
원하던기능이 들어있는 암기프로그램이네요.
처음 설치하고 실행하니 단어가안나와서 이것저것해보다보니 활성제목표시줄색을 쓰더라고요;; 일단 바꿔서 사용하니 문제는 없지만 나중에 수정좀 해주세요..
그리고 일본한자공부에 활용하려고 하는데요 한자 크기가 너무 작아서 알아보기 힘드네요. 글자 크기를 조절할수 있었으면 하는 바램이 있네요..
method 통신의 방법을 설정한다. "POST"와 "GET", "PUT" 중 하나를 넘겨줄 수 있는데, "POST"의 경우 실제 http 자체에 내용을 넣어 전달하는 것이고, "GET"의 경우 '?' 기호와 '&' 기호를 이용하여 주소에 여러 변수의 값을 담아 넘겨주는 방법이다. "PUT"의 경우 거의 쓰이지는 않는 방법이다.
url 통신할 파일의 주소를 적어준다. 절대 경로와 상대 경로 둘 다 상관 없지만 주의할 점은 같은 서버 내에 있어야 접근이 허가된다는 것이다.
asynch 통신의 동기/비동기 여부를 결정한다. true일 경우 비동기 통신, false일 경우 동기 통신이 된다. 기본값은 true, 즉 비동기 통신이다. AJAX의 큰 장점 중 하나가 비동기 통신이므로 주로 true로 사용한다.
username, password 해당 페이지에서 username과 password를 요구한다면 이 인자를 통해 username과 password를 전달한다.
27라인에서는 콜백 함수를 설정하고 있다. 콜백 함수란, 직접 호출하지 않아도 특정 이벤트에 자동으로 호출되는 함수를 말한다. onreadystatechange라는 이벤트에 CallBack()이라는 함수를 할당함으로써 onreadystatechange 이벤트가 발생할 경우 자동으로 CallBack() 함수가 호출된다.
28라인의 send() 함수는 실질적으로 통신을 하는 함수이다. 인자로는 전달할 데이터를 넣어주는데, "GET" 방식에서는 null을, "POST" 방식에서는 전달할 데이터를 넣어주면 된다.
서버에서 응답하기
이렇게 하여 서버로 요청이 넘어가면 서버에서는 time.php 파일을 열어 응답을 한다. 응답은 일반 웹 페이지를 뿌리는 것과 똑같이 하면 된다. 즉, php로 응답을 할 경우 echo로 뿌려 준 모든 소스코드가 응답이 된다.
time.php에서는 GetServerTime.html에서 요청을 전달받고 바로 응답을 한다. header 함수의 경우 응답 http의 헤더를 설정하는 부분인데, 꼭 응답의 헤더에서 Content-Type, 즉 mime을 text/xml로 설정해야 클라이언트에서 XML 데이터로 받아 처리할 수 있다. 그렇지 않을 경우 XML 데이터임에도 불구하고 XML로 인식을 하지 못하게 된다.
ReadyState
XMLHttpRequest 객체를 사용하는 모든 과정에서 이 객체의 속성 중 하나인 readystate가 계속 변하게 되며, 변할 때마다 onreadystatechange라는 이벤트를 발생시킨다. readystate는 다음과 같이 5가지의 값을 가질 수 있다.
0 객체는 생성되었으나 open 함수는 호출되지 않음 1 open 함수는 호출되었으나 send 함수는 호출되지 않음 2 send 함수는 호출되었으나 아직 서버로부터 응답이 오지 않음 3 서버로부터 응답이 일부만 도착함 4 서버로부터 모든 응답이 도착함
즉 실제로 응답을 처리해야 하는 시점은 readystate가 4인 때이다.
onreadystatechange 이벤트의 콜백 함수로 CallBack() 함수를 설정했으니 readystate가 0~4로 바뀔 때마다 CallBack() 함수가 호출된다. CallBack() 함수에서는 매번 readystate의 값을 검사하여 4일 경우에만 응답을 처리하면 된다.
하지만 readystate가 4인 경우에도 올바르지 않은 응답이 올 수 있다. 가령, 접근 권한이 없어 접근하지 못했을 때에도 readystate는 4가 될 수 있다. 이 때에는 XMLHttpRequest의 status 속성을 검사하면 된다. status는 성공적인 응답이 왔을 때에 200으로 설정되므로 이를 검사한다.
응답 처리하기
이렇게 readystate==4 && status==200의 조건을 만족했을 경우 서버로부터 성공적인 응답이 도착한 것이므로 xhr에는 응답이 저장된다. 이 응답은 두 가지 방법으로 접근할 수 있다.
첫 번째 방법은 xhr.responseText로 접근하는 것이다. 서버에서 XML 데이터가 아닌 Text 데이터를 리턴했을 경우 사용한다. XML을 리턴했더라도 이를 Text의 형태로 받고 싶다면 이를 이용한다.
두 번째 방법은 xhr.responseXML로 접근하는 것이다. 이 방법은 응답의 Content-type이 text/xml인 경우에만 성공적으로 처리된다. 이 방법은 DOM Object의 형태로 XML 문서에 접근할 수 있어 매우 편하다. 또한 AJAX 자체가 본래 XML을 사용하도록 만들어 진 것이므로 주로 이 방법을 사용하게 된다.
DOMDocument
DOMDocument란, XML 데이터를 효과적으로 제어/조작하기 위하여 고안된 객체이다. XML 데이터를 통째로 읽어 메모리에 트리의 형태로 저장해 놓고 다음의 명령어들을 통해 검색/추가/제거/수정 등의 작업을 할 수 있다. element라는 DOM Object가 존재한다고 가정하고 설명한다.
접근 element.childNodes : element의 모든 자식 노드를 배열로 반환한다. element.firstChild : element의 첫 번째 자식 노드를 반환한다. element.lastChild : element의 마지막 자식 노드를 반환한다. element.parentNode : element의 부모 노드를 반환한다. element.nextSibling : element의 다음 형제 노드를 반환한다. element.previousSibling : element의 이전 형제 노드를 반환한다. element.nodeValue(=data) : element의 값을 반환한다. element.hasChildNodes(); : element가 자식노드를 가지면 true, 가지지 않으면 false를 반환한다. element.getAttribute(name); : element의 attribute 중 이름이 name인 attribute의 값을 반환한다.
검색 element.getElementsByTagName(tagname); : 이름이 tagname인 모든 노드를 배열의 형태로 반환한다. element.getElementById(tagID); : ID가 tagID인 노드를 반환한다.
추가 document.createElement(tagname); : tagname의 이름으로 새로운 노드를 생성한다. document.createTextNode(text); : text의 값으로 새로운 텍스트 노드를 생성한다. element.appendChild(child); : child를 맨 마지막 자식 노드 뒤에 추가한다. element.insertBefore(new, target); : new를 target 바로 앞에 추가한다.
제거 element.removeChild(child); : element의 자식 노드 중 child를 삭제한다.
변경 element.replaceChild(new, old); : element의 자식 노드 중 old를 new로 대체한다. element.setAttribute(name, value); : element의 속성 중 이름이 name인 속성의 값을 value로 설정한다. element.removeAttribute(name); : element의 속성 중 이름이 name인 속성을 삭제한다.
마무리
기본적으로 서버와 통신하는 방법을 알아보았다. 사실 위의 소스코드를 그대로 실행하면 시간이 바뀌지 않는다는 것을 알 수 있다. 이는 인터넷 임시 파일이 생성되어 분명 페이지가 바뀌었음에도 불구하고 컴퓨터에 저장된 임시 파일을 읽어들여서 바뀌지 않은 내용을 보여주기 때문이다. 이 때에는 요청하는 주소를 계속 변화시키기 위하여 주소에 랜덤값을 같이 넘겨 주는 것이 좋다. 예를 들어 다음과 같다.
url="time.php?key=" + Math.random();
위와 같이 하면 매번 다른 주소로 요청이 넘어가기 때문에 저장된 임시 페이지를 읽어오지 않아서 매번 다른 값을 볼 수 있다.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
프로그램을 작성할 때 소수를 구해야 할 일이 종종 있다. 이 때에는 조건에 따라 두 가지 방법 중 적절한 것을 골라서 사용하게 된다.
2 ~ √N 중 약수 검사하기
이 방법은 N이 소수인지 아닌지를 판별하는 방법으로, 매우 직관적이다. 일반적으로 √N까지의 수 중에 N의 약수가 없으면 그 이후의 수에도 N의 약수가 없다는 것을 가지고 N의 소수 여부를 검사하는 방법이다.
위 프로그램은 입력한 수가 소수인지 아닌지를 알려준다. 2부터 √N까지의 수 중에 N의 약수가 있는지를 검사하는 방법이다.
위 방법은 특정 수의 소수 여부를 판별하기에는 빠르다는 장점을 가지고 있다. 하지만 일정 범위의 모든 수 중 소수를 구할 때 쓰기에는 아래의 방법보다 훨씬 비효율적일 수 있다.
에라토스테네스의 체
이 방법은 에라토스테네스가 고안한 방법으로, 여러 수를 체를 이용해 거르는 모양과 흡사하다고 해서 아리스토테네스의 체라고 불리운다.
2부터 N까지의 수 중 소수를 구한다고 하자. 이 때 K가 소수일 때 K의 배수는 소수가 될 수 없다. 가장 작은 소수는 2이며, 따라서 2의 배수는 소수가 될 수 없다. 이 때 모든 2의 배수에 체크를 시켜둔다. 체크되지 않은 수 중 가장 작은 수는 3이고, 3의 배수에도 모두 체크한다. 이러한 방법으로 N까지 검사하면 2~N 사이에 있는 모든 소수를 빠른 시간 내에 구할 수 있다.
아리스토테네스의 체를 C로 작성해보면 위의 소스와 같다. 2의 배수는 모두 소수가 아니라는 점에 착안하여 메모리 사용과 실행 속도를 반으로 줄이는 방법도 있으나 편의상 그러한 방법은 사용하지 않았다.
위의 방법을 쓰면 상당히 빠르게 소수를 구할 수 있다. 특히 수가 커지면 커질 수록 처음의 방법보다 더 빠른 결과를 보여준다. 다만, 메모리가 많이 쓰이고 임의의 수의 소수 여부를 판단하는 데에는 적절치 못하다.
출력 부분을 제외하고 2부터 N까지의 모든 소수를 구할 때의 수행 속도는 다음과 같다.
N
수행 속도(tick)
10,000
0
100,000
15
1,000,000
282
10,000,000
3265
100,000,000
33813
수행 속도의 단위로 쓰인 tick은 ms와 거의 같은 단위로 봐도 무방하다. (따지자면 차이가 있지만 같다고 간주하자.) 대부분의 프로그램 문제에서는 1초 내에 처리할 것을 요구하므로 1,000,000 정도까지의 소수를 구하는 데에는 무리가 없을 것이다.
다만 주의할 점은 특정 범위(N~M)의 소수를 구하고 싶어도 2부터 M까지 돌려야 한다는 것이다.
문제의 요구에 따라 두 방법 가운데 적절한 방법을 골라 쓸 수 있어야 할 것이다.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
AJAX는 Asynchronous JAvascript & XML의 약자로, 말 그대로 자바스크립트와 XML을 이용하여 서버와 비동기적으로 통신하는 것을 일컫는다. 이를 이용하면 좀 더 다이나믹한 웹 페이지를 꾸밀 수 있게 된다.
일반적으로, 서버와 통신하기 위해서는 한 번의 페이지 이동을 거쳐야 한다. 왜냐 하면 서버측 프로그램은 페이지가 바뀔 때 호출이 되고, 이 때 서버의 정보를 얻어올 수 있기 때문이다. 물론 HTML등의 단순한 문서는 서버측의 프로그램이 필요 없을 수도 있겠지만, DB에 Access하는 페이지의 경우 일반적으로는 한 번의 작업을 할 때마다 페이지를 이동하여 서버측 프로그램을 호출해야 한다.
하지만, AJAX를 이용하면 서버 작업 시 페이지 이동이 불필요하게 되어서 사용자로 하여금 훨씬 편하게 사이트를 이용할 수 있게 한다.
AJAX를 이용한 대표적인 사이트를 꼽으라면 구글 맵스를 들 수 있을 것이다. 이는 프로그램으로 나와 있던 Google Earth를 웹 상으로 옮겨놓은 것이라고 생각하면 된다.
AJAX가 구현된 대표적인 사이트로 꼽히는 'Google Maps'의 페이지 모습이다.
처음 보는 사람이라면 '이거 뭐 다른데서 서비스하는 지도랑 똑같잖아?'라고 생각할 수도 있다. 하지만 분명히 큰 차이점이 있다. 다른 곳은 이용할 때 ActiveX 플러그인을 설치할 것을 요구한다. 하지만 구글 맵스는 어떠한 설치도 필요없다. 이것이 구글 맵스의 가장 큰 장점인 것이며, AJAX의 장점을 여실히 보여주는 예이다.
ActiveX가 없는 순수한 웹페이지인데도 페이지 전환이 없이 깔끔하게 지도를 표시하고 있다.
AJAX를 이용하면 어떤 것이 가능한 것인지 충분히 볼 수 있었다고 생각된다.
AJAX의 핵심요소는 XMLHttpRequest와 DOM이다.
XMLHttpRequest : 페이지 전환 없이 서버로 Http를 이용하여 정보를 전달하고 받아오는 자바스크립트 객체이다. 본래 IE가 처음 지원하였으나 현재는 대부분의 브라우저가 지원하고 있다. DOM : XML 데이터를 관리하는 객체이다. XML 자료가 주어지면 몇 가지 함수를 통해 파싱, 추가, 삭제, 수정 등을 자유롭게 할 수 있도록 도와준다.
기본적인 원리를 간단히 설명하자면, XMLHttpRequest라는 객체에 여러 가지 정보를 담고 서버로 이를 전송한다. 그러면 서버가 이를 받아 처리를 한 후 그 결과값을 다시 클라이언트로 전송한다. 클라이언트는 서버에서 받아온 결과값을 이용하여 실시간으로 페이지를 갱신하게 된다.
태터툴즈의 자동 저장기능에 감사드립니다. 한 번 잘못 눌렀는데 다행히 다 저장되어있네요.. 저도 아직 AJAX를 공부하고 있는 입장이지만, 공부해 나가면서 계속 포스팅하겠습니다.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
FindFirstFile : 파일 검색을 시작한다. 파일 검색 문자열이 잘못되었거나 다른 이유로 함수 실행이 실패했을 경우 INVALID_HANDLE_VALUE로 Define된 상수값을 반환한다. 성공했을 경우 파일 검색 핸들을 반환하고 두 번째로 전달되는 구조체에 첫 번째로 발견되는 파일의 정보를 넣어준다.
LPCSTR lpFileName 파일 검색 문자열을 넘겨준다. 예) "c:\*.*" 혹은 "c:\*.txt"
LPWIN32_FIND_DATA finddata 파일 검색 데이터 구조체의 포인터를 넘겨준다.
FindNextFile : 다음 파일의 정보를 얻는다. 함수 실행이 성공하였을 경우 TRUE를, 실패하였을 경우 FALSE를 반환한다. 함수 성공시 두 번째 인자로 전해지는 구조체에 파일의 정보를 넣어준다.
HANDLE hFind FindFirstFile이 반환한 파일 검색 핸들을 넘겨준다.
LPWIN32_FIND_DATA finddata 파일 검색 데이터 구조체의 포인터를 넘겨준다.
FileClose : 파일 핸들을 닫는다. FindFirstFile에 의해 열린 파일 핸들을 닫는다. 성공하였을 경우 TRUE를, 실패하였을 경우 FALSE를 반환한다.
HANDLE hFind FindFirstFile이 반환한 파일 검색 핸들을 넘겨준다.
실제 사용 예는 다음과 같다.
(2003/2005)LPCSTR 캐스팅에 문제가 있는 경우 Project -> Properties -> Configuration Properties -> General -> Character Set을 Not Set으로 설정하기 바랍니다.
2008년 1월 19일 이후 작성된 모든 글에 대해서 퍼가는 것을 금지합니다. 퍼가고자 하시는 분은 링크를 달아 주시기 바랍니다.
댓글을 달아 주세요
좋구나.