phpsource/파일분석2002. 9. 16. 16:51
2002.9.16 - 0.0.1 패치1
  • get_head() 함수 수정
2002.9.9 - 0.0.1
  • 첫 배포판

'phpsource > 파일분석' 카테고리의 다른 글

{INI 파일}2.INI 핸들러  (0) 2003.06.25
{INI 파일}1.개요  (0) 2003.06.25
{TAR 파일}7.클래스  (0) 2002.09.09
{TAR 파일}6.zlib를 이용한 압축  (0) 2002.09.09
{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
Posted by 방글24
sketch2002. 9. 13. 10:26
인터넷상에 굴러다니는 글하나를 퍼올렸습니다. 이 글이 클래스를 염두에 두고 작성된 글이 아니나 프로그래밍에 대하여 다시 한번 생각할 수 있는 기회가 될 것같아 첨부하니 편하게 읽어주시기 바랍니다.
프로그래밍의 도(道)
The Tao of Programming
영역: 죠프리 제임스(Geoffrey James)
필사: 세쓰 로버트슨(Seth Robertson)
한역: 윤태원
제 1 권 : 무(無)
도사 프로그래머 가라사대 : "숨겨진 에러 코드를 찾아내는 방법을 익혔다면 하산할 때가 온 것이니라."
1.1
무(無)에서 이상스러운 기운이 생겨났도다. 그 기운은 홀로 외로이 움직이지 않았다. 그 기운은 움직이지 않았으나 동시에 끊임없이 움직이고 있었다. 그것이 바로 모든 프로그램의 소스이다. 나는 그 이름을 알지 못하느니, 그것을 '프로그램의 도(道')라고 부르게 되었다.
도가 위대하다면 운영체제(OS)도 위대하다. 운영체제가 위대하다면 컴파일러도 위대하다. 컴파일러가 아주 위대한 것이라면 애플리케이션은 위대하다.
사용자는 만족하고 그리하여 세상은 조화로 충만하도다.
프로그래밍의 도는 멀리까지 미치며 아침 바람과 함께 돌아온다.
1.2
도는 기계어를 낳았다. 기계어는 어셈블러를 낳았다.
어셈블러는 컴파일러를 낳았다. 그리하여 세상은 만가지도 넘는 언어로 가득하게 되었다.
모든 언어는 아무리 비천한 것일지라도 그 뜻한 바가 있다. 모든 언어는 소프트웨어의 음과 양(陰陽)을 나타낸다. 모든 언어는 도 안에 그 자리가 있는 법이다.
하지만 할 수만 있다면 코볼(COBOL)로는 프로그래밍하지 말지어다.
1.3
처음에 도가 있었다. 도는 시간과 공간을 낳았다. 그리하여 시간과 공간은 프로그래밍의 음과 양을 이루게 되었다.
도를 깨닫지 못한 프로그래머는 언제나 프로그램을 짤 시간과 공간이 모자라는 법이다. 도를 깨달은 프로그래머는 언제나 목적을 달성할 수 있는 충분한 시간과 공간이 있다.
세상의 모든 이치가 그러한 법이니......
1.4
현명한 프로그래머는 도를 듣고 따른다. 보통 프로그래머는 도를 듣고 찾아본다. 멍청한 프로그래머는 도를 듣고 웃어 넘긴다.
그 웃음이 없었더라면 도는 존재하지 않았을 것이다.
가장 높은 음이 가장 알아듣기 힘든 법. 앞으로 나아감은 바로 후퇴하는 법.
위대한 재능은 인생의 후반에야 나타나는 법. 가장 완벽한 프로그램에도 버그는 존재하는 법.
제 2 권 : 고대(古代)의 도사(道士)들
도사 프로그래머 가라사대 : "사흘간 프로그래밍을 하지 않으면, 삶에 아무런 의미도 없어지느니라."
2.1
고대의 프로그래머들은 신비롭고 심오하도다. 우리는 그들의 사상을 감히 측정할 수 없도다. 그리하여 우리는 그들의 외양을 묘사할 수밖에 없도다. 그들은 물을 건너는 여우처럼 빈틈이 없다. 전장에 나선 장군처럼 방심하지 않는다. 손님을 맞는 여주인처럼 친절하다. 조각하지 않은 나무토막처럼 단순하다. 어두운 동굴 속의 검은 연못처럼 불투명하다.
누가 감히 그들의 마음과 생각에 담긴 비밀을 알아낼 수 있으리요? 답은 오직 도 속에 있을 뿐이다.
2.2
위대한 도사 튜닝은 어느날 그가 기계가 된 꿈을 꾸었다. 잠에서 깨어난 튜닝이 탄식하며 가라사대 : "나는 기계가 된 꿈을 꾸는 튜닝인지, 튜닝이 된 꿈을 꾸는 기계인지 알 지 못하노라!"
2.3
아주 큰 컴퓨터 회사에서 온 프로그래머가 소프트웨어 전시회에 다녀와 상사에게 이렇게 말하였다. "다른 회사에는 어떤 프로그래머들이 일하고 있습니까? 그들은 멋대로 행동하고 외관에는 신경쓰지 않습니다. 그들의 머리는 길고 텁수룩하며, 그들의 옷은 낡고 구겨졌습니다. 그들은 숙소에서 만취해서 돌아다니며 제가 발표할 동안에 야유를 해 댔습니다."
상사가 가로되 : "너를 전시회에 보내지 말았어야 했다. 그 프로그래머들은 세상사를 초월한 사람들이니라. 그들은 삶을 어리석은 것으로 여기며, 우연의 일치로 생각한다. 그들은 아무런 거리낌없이 다닌다. 그들은 아무 것에도 신경쓰지 않으니, 그것은 그들이 프로그램만을 위해 살기 때문이다. 왜 그들이 사회적인 관습 따위에 신경을 쓰겠느냐?"
"그들은 도 속에 살고 있느니라."
2.4
제자가 스승에게 묻기를: "저 프로그래머는 설계도 않고, 문서 작성도 않으며 자기 프로그램을 테스트해 보지도 않습니다. 하지만 모두 그를 세계에서 가장 뛰어난 프로그래머라고 칭송합니다. 그 이유가 무엇입니까?"
스승이 답하기를: "그 프로그래머는 도를 깨달았느니라. 그는 더 이상 설계할 필요성을 느끼지 않는다. 그는 시스템이 다운되도 화내지 않으며 그저 우주의 질서를 거리낌없이 받아들이기 때문이다. 그는 더 이상 문서를 작성할 필요가 없다. 그는 다른 사람이 자기가 짠 코드를 이해하건 말건 신경쓰지 않기 때문이다. 그는 테스팅할 필요가 없다. 그가 작성한 프로그램은 모두 그 자체로 완벽하며, 고요하고 또 우아하다. 그의 프로그램은 모두 그 목적이 스스로 뚜렷하기 때문이다. 아, 그는 진정으로 도를 깨달은 사람이니라."
제 3 권 : 설계(Design)
도사 프로그래머 가라사대: "프로그램을 테스트하고 있을 때는 설계를 변경하기엔 이미 늦은 다음이니라."
3.1
옛날에 컴퓨터 전시회에 참석한 사람이 있었다. 그는 매일 전시장에 들어가면서 문 앞에 선 경비원에게 이렇게 말했다.
"나는 상점을 터는 기술로 유명한 도둑이오. 미리 경고하지만 이 전시회도 내 손길을 벗어나진 못할 것이외다."
그의 말에 경비원은 무척 신경이 쓰였다. 전시회에 출품된 컴퓨터 장비의 가치들이 가히 수십억원에 이르렀기 때문이다. 경비원은 자칭 도둑의 일거수일투족을 감시하였다. 하지만 그는 휘파람을 불면서 전시장에서 전시장으로 돌아다닐 뿐이었다.
자칭 도둑이 전시회장을 나갈 때 경비원은 그를 옆으로 데려가 몸수색을 실시하였다. 하지만 몸에는 아무 것도 없었다.
다음날, 그는 다시 돌아와 경비원의 약을 올렸다. "나는 어제 엄청난 수확을 올렸소. 오늘은 더 많은 것을 훔치고 말테요." 경비원은 그를 더욱 철저히 감시하였다. 하지만 아무런 소득도 없었다.
전시회가 끝나는 날, 경비원은 호기심을 도저히 억누를 수가 없었다. "도선생, 나는 도저히 이해할 수 없소. 궁금증으로 인해 나는 밤잠을 이룰 수 없을 것 같군요. 제발 나를 깨우쳐 주시오. 당신이 훔친 것은 대체 무엇이요?"
도둑은 가볍게 미소를 지었다. "나는 아이디어를 훔치고 있소."
3.2
옛날에 한 스승 프로그래머는 늘 구조화되지 않은 프로그램을 짰다. 한 제자가 그를 흉내내기 위하여 구조화되지 않은 프로그램을 짰다. 제자가 스승에게 자신의 성장을 평가해달라고 하자 스승은 프로그램이 구조화되지 않았다며 꾸짖었다. "뱁새가 황새를 따라가면 가랭이가 찢어지는 법이다. 구조를 초월하기 전에 먼저 도를 깨달아야 하느니라."
3.3
위(魏)나라의 조정에 한 프로그래머가 있었다. 위후(魏候)가 프로그래머에게 묻기를: "회계 프로그램과 운영체제 중에 설계하기 쉬운 것은 어느 쪽이요?"
"운영체제 이옵니다." 하고 프로그래머가 답했다.
위후는 믿을 수 없다는 표정으로 반문하였다. "어찌 회계 프로그램처럼 하찮은 것이 운영체제의 복잡함을 능가한다는 말이요?"
"그렇지 않사옵니다. 회계 프로그램을 설계할 때는 프로그래머가 서로 다른 생각을 지닌 사람들을 조율해야만 하옵니다. 회계 프로그램이 어떻게 작동해야 하며, 보고서는 어떤 양식으로 출력되어야 하며, 세법에는 어느 정도로 충실해야 하는지 각양각색으로 떠들기 마련이옵니다. 반면에 운영체제의 외양에는 아무도 신경쓰지 않사옵니다. 운영체제를 설계할 때는 프로그래머는 기계와 아이디어의 가장 단순한 조화만 추구하면 되옵나이다. 이것이 운영체제가 설계하기 쉬운 까닭이옵니다. 옛말에는 이를 일컬어 사공이 많으면 배가 산으로 간다고 하옵니다."
크게 감탄한 위후가 미소를 지으며 다른 질문을 던졌다. "그렇구려, 그런데 어느 쪽이 더 디버깅하기 쉽소?"
프로그래머는 아무런 답도 하지 못했다.
3.4
관리자가 도사 프로그래머를 만나 새 애플리케이션의 요구사항을 담은 문서를 건네주었다. 관리자가 묻기를: "다섯명의 프로그래머를 투입한다면 시스템을 설계하는데 얼마나 걸리겠소?"
"일년이 걸릴 것입니다." 도사가 간단하게 대답하였다.
"하지만 우리는 이 시스템이 지금 당장 필요하단 말이요! 프로그래머를 열명 투입하면 어떻겠소?"
도사는 인상을 지푸렸다. "그렇다면 이년이 걸릴 것입니다."
"프로그래머를 백명 투입한다면 어떻겠소?"
도사는 가볍게 한숨을 쉬며 답하였다. "그 경우에는 시스템이 결코 완성되지 않을 것입니다."
제 4 권 : 코딩(Coding)
도사 프로그래머 가라사대 : "잘 짠 프로그램은 그 자체로 천국이며, 못 짠 프로그램은 그 자체로 지옥이니라."
4.1
프로그램은 작고 민첩해야하며, 그 서브루틴은 마치 진주 목걸이처럼 연결되어 있어야 한다. 프로그램의 내용과 정신은 일관적이어야 한다. 프로그램은 너무 작아도 너무 많아도 아니되며, 필요없는 루프나 필요없는 변수가 있어서는 아니되며, 구조가 없어도 아니되며 지나치게 경직되어도 아니된다.
프로그램은 '최소 경악의 법칙'을 따라야 한다. 이 법칙이 무엇이냐고? 프로그램은 사용자를 최소로 놀라게 하는 방향으로 반응해야 한다는 뜻이다.
프로그램은 아무리 복잡하더라도 하나의 객체처럼 동작해야 한다. 프로그램은 외관보다는 내부의 논리에 따라 작성되어야 한다.
프로그램이 이러한 요구를 따르지 못하면 무질서와 혼란이 발생한다. 이를 고치는 유일한 방법은 프로그램을 다시 작성하는 것 뿐이다.
4.2
제자가 스승에게 묻기를: "프로그램을 짰는데 때로는 작동하고 때로는 작동하지 않습니다. 프로그래밍 법칙을 모두 따랐는데 왜 이런 일이 생기는지 도무지 알 수가 없습니다. 이유가 무엇입니까?"
스승이 답하기를: "너는 도를 깨닫지 못했기에 당황하는 것이니라. 사람들이 이성적으로 행동하리라 믿는 것은 오직 바보뿐이다. 너는 어찌하여 사람이 만든 기계로부터 이성적인 행동을 바라느뇨? 컴퓨터는 결정론을 흉내내는 것 뿐이다. 오직 도만이 완전하다. 프로그래밍의 법칙은 일시적이며, 오직 도만이 영원하다. 따라서 너는 깨달음을 얻기 위해 도를 명상해야 할 것이니라."
"하지만 제가 깨달음을 얻었는지 어떻게 알 수 있습니까?" 제자가 물었다.
"그 때가 되면 프로그램이 제대로 돌아갈 것이다." 스승이 말했다.
4.3
스승이 도의 본질을 제자에게 설명하고 있었다. "도는 아무리 사소한 것일지라도 모든 소프트웨어 내에 존재한다." 스승이 말했다.
"휴대용 계산기에도 도는 존재합니까?" 제자가 물었다.
"그러느니라." 스승의 대답이었다.
"비디오 게임에도 도는 존재합니까?" 제자가 물었다.
"비디오 게임에도 도는 존재하느니라." 스승이 말했다.
"퍼스널 컴퓨터의 도스에도 도는 존재합니까?"
스승은 불편한 듯 헛기침을 하더니 자세를 조금 바꾸었다.
"오늘의 수업은 여기까지다." 스승이 말했다.
4.4
프라이스 왕의 프로그래머가 소프트웨어를 짜고 있었다. 그의 손가락이 키보드 위에서 춤을 추었다. 프로그램은 에러 메시지 하나 없이 컴파일되었고 마치 봄바람처럼 가볍게 실행되었다.
"기가 막히군! 당신의 기술은 완전무결하구려!" 프라이스가 감탄하며 말했다.
"기술이라구요?" 프로그래머가 터미널에서 몸을 돌리며 말하기 시작했다.
"내가 따르는 것은 모든 기술을 넘어선 도입니다. 내가 처음 프로그램을 작성하기 시작했을 때는 프로그램 전체가 한 덩어리로 보였습니다. 삼년이 지나자 나는 더 이상 덩어리가 보이지 않았습니다. 그 때부터 나는 서브루틴을 사용하기 시작했지요. 하지만 이제는 내게는 아무 것도 보이지 않습니다.
내 존재는 형태없는 무 속에 존재합니다. 나는 아무런 감각도 느낄 수 없습니다. 내 정신은 아무런 계획도 세우지 않고 자유롭습니다. 그저 본능의 지시에만 따를 뿐. 간단히 말해 내 프로그램은 스스로 작성되는 것입니다. 가끔 어려운 문제가 발생하는 것은 사실입니다. 어려움이 다가오는 것을 다가오면 속도를 늦춥니다. 그리고 조용히 관찰합니다. 그리곤 코드에서 한줄만 바꾸면 어려움은 마치 연기처럼 사라지고 말지요. 그리고나선 프로그램을 컴파일합니다. 나는 조용히 앉아 일의 즐거움이 내 존재를 가득 채우는 것을 느끼며 즐깁니다. 나는 잠깐 눈을 감고 명상한 다음 터미널을 끕니다."
프라이스 왕이 가로되, "내가 고용한 모든 프로그래머들이 그대처럼 현명하기를!"
제 5 권 : 유지(Maintenance)
도사 프로그래머 가라사대 : "프로그램의 길이가 세줄밖에 안되더라도, 언젠가는 손 볼 필요가 생기느니라."
5.1
조심스레 사용한 문의 경첩에는 기름을 칠 필요가 없다. 흐르는 물에는 이끼가 끼지 않는다. 소리도 생각도 진공을 지나갈 수는 없다. 사용하지 않은 소프트웨어는 똥된다.
이들은 모두 위대한 미스테리들이다.
5.2
관리자가 어느날 프로그래머를 불러 물었다. "지금 짜고 있는 프로그램이 언제 끝나겠소?" 프로그래머가 즉시 답하기를. "내일까지 끝내지요."
"좀 비현실적인 얘기같군요. 정말로 언제까지 끝낼 수 있습니까?" 관리자가 다시 물었다.
프로그래머는 잠깐 생각을 하더니 말했다. "사실은 약간 추가하고 싶은 기능이 있습니다. 그걸 다 하려면 이주는 걸리겠는데요."
"그것도 사실 기대하기 힘든 것 같군요. 그냥 프로그램이 완성되면 알려주시오." 관리자가 툴툴대며 말했다.
프로그래머는 그러마고 답했다.
많은 해가 지나 관리자는 은퇴하게 되었다. 은퇴식장에 가던 도중 그는 프로그래머가 터미날 앞에서 잠들어 있는 것을 보게 되었다. 그는 어제 밤을 새가며 프로그래밍을 했던 것이다.
5.3
어느날 제자 프로그래머가 간단한 회계 프로그램을 짜라는 지시를 받았다. 제자는 많은 날을 열심히 일했다. 스승이 그의 프로그램을 실행해보니 스크린 에디터와 그래픽 처리루틴 몇가지와 인공지능을 응용한 인터페이스가 구현되어 있었다. 하지만 어디에도 회계와 관련된 기능은 없었다.
스승이 이에 대해 묻자, 제자가 시큰둥하게 대답했다. "그렇게 급하게 재촉하지 마세요. 언젠가는 회계에 관련된 기능을 넣을테니까요."
5.4
훌륭한 농부가 자신이 심은 쌀 한톨을 소홀히 하는 것을 보았는가? 훌륭한 선생이 반에서 가장 어리석은 학생이라고 무시하는 것을 보았는가? 훌륭한 아버지가 아이를 굶주리게 하는 것을 보았는가? 훌륭한 프로그래머가 코드를 고치는 것을 거부하는 것을 보았는가?
제 6 권 : 관리(Management)
도사 프로그래머 가라사대 : "프로그래머는 많이 고용하고 관리자의 수는 줄여라. 생산성이 절로 향상될 것이다."
6.1
관리자가 끊임없이 회의를 하면 프로그래머는 게임을 짠다. 회계사가 사분기 이익에 대해 불평하면 개발 예산은 삭감될 위기에 처한다. 수석 과학자가 푸른 하늘을 논하면 바람 구름이 몰려든다.
아, 이것은 진정한 프로그래밍의 도가 아니다.
관리자가 결론을 내면, 게임 프로그램은 잊혀진다. 회계사가 장기 계획을 세우면 조화와 질서가 회복된다. 수석 과학자가 신경쓰기 시작하면 문제는 곧 해결된다.
아, 이것이 진정한 프로그래밍의 도이다.
6.2
프로그래머는 왜 생산성이 낮은가? 그들의 시간이 회의로 낭비되기 때문이다.
프로그래머가 왜 툴툴거리는가? 관리자가 지나치게 참견하기 때문이다.
프로그래머가 왜 하나씩 회사를 떠나는가? 지쳤기 때문이다.
무능력한 관리자 밑에서 일하는 프로그래머는 자신의 직업을 소중히 여기지 않는다.
6.3
관리자가 해고될 위기에 쳐했다. 하지만 그 밑에서 일하던 프로그래머가 새로운 소프트웨어를 개발하여 큰 성공을 거두었다. 결과적으로 관리자는 자리를 지킬 수 있었다.
관리자는 보너스를 주려고 하였지만, 프로그래머는 거절하였다. 프로그래머 가로되. "나는 이 프로그램이 재미있다고 생각했기 때문에 작성했을 뿐입니다. 그러므로 나는 아무런 보상도 바라지 않습니다."
이 말을 들은 관리자가 말하기를, "이 프로그래머는, 비록 비천한 자리에 있으나, 종업원의 맡은 바 책무가 무엇인지 잘 알고 있다. 그를 보조 관리자로 승진시키도록 하라."
그러나 이 말을 들은 프로그래머는 다시 한 번 거절하였다. "나는 프로그램을 짤 수 있기 때문에 존재합니다. 만일 승진한다면 다른 사람의 시간을 갉아먹게 될 뿐입니다. 이제 가도 됩니까? 지금 짜고 있는 프로그램이 하나 있거든요."
6.4
관리자가 프로그래머를 찾아가서 말하기를: "당신의 출근 시간을 조정하기로 했소. 이제부터 아침 9시에 나오고 5시에 퇴근하도록 하시오." 이 말을 들은 프로그래머들은 모두 분노하였고, 몇몇은 즉석에서 회사를 그만두었다.
그래서 관리자가 말하기를: "좋아요. 그렇다면 작업 시간을 자유롭게 정하도록 하시오. 맡은 프로젝트를 스케쥴에 맞게 끝내기만 하면 상관하지 않겠소." 만족한 프로그래머들은 이제 정오에 출근하여 이른 새벽까지 일했다.
제 7 권 : 운용의 묘
마스터 프로그래머 가라사대 : "사장에게 컴퓨터 프로그램을 보여줄 수는 있다. 그러나 그가 컴퓨터 문맹에서 벗어나게 할 수는 없다."
7.1
제자가 스승에게 묻기를: "동방에는 본사라는 이름의 거대한 트리 구조가 있습니다. 그 트리구조는 부사장과 관리자들로 지나치게 비대해졌습니다. 트리구조는 '이리 가라' 또는 '저리 가라'는 메모를 무수히 내려보냅니다. 하지만 아무도 그 메모의 진정한 뜻이 무엇인지는 이해하지 못합니다. 그 가지에는 매년 새로운 이름들이 나붙지만 결국엔 아무런 소용도 없지요. 어떻게 이렇게 부자연스러운 존재가 있을 수 있습니까?"
스승이 답하여 가로되; "너는 이 방대한 구조의 존재를 깨달고, 거기에 아무런 이성적인 목적도 없다는 사실에 당황하고 있는 것이다. 본사의 그 끊임없는 방향 전환에서 아무런 즐거움도 느끼지 못하겠느냐? 우리를 보호하는 가지 아래서 아무런 방해도 받지 않고 프로그래밍할 수 있는 즐거움을 깨닫지 못했느냐? 왜 본사의 존재가 무가치하다는데 신경을 쓰는 것이냐?"
7.2
동방에는 어떤 물고기보다도 더 큰 상어가 있다. 이 상어는 대붕이라는 이름의 새로 변한다. 이 새가 일으키는 바람은 하늘을 가득 채우는 구름과도 같다. 대붕이 땅을 가로지르면 본사에서 보내는 메시지를 가져 온다. 이 메시지는 갈매기가 해변에 떨어뜨리는 똥처럼 프로그래머의 수중에 떨어진다. 그 후 대붕은 바람을 타고 푸른 하늘을 등에 업은채 집으로 돌아간다.
초보 프로그래머는 놀란 눈으로 대붕을 바라본다. 이해할 수 없기 때문이다.
보통 프로그래머는 대붕을 두려워한다. 대붕이 가져오는 메시지가 무섭기 때문이다.
도사 프로그래머는 터미날 앞에 앉아 일을 계속한다. 대붕이 다녀간 것을 알아차리지 못하기 때문이다.
7.3
상아탑에 사는 위대한 마법사가 새로운 발명품을 스승 프로그래머에게 가져왔다. 마법사는 거대한 검은 상자를 밀며 스승의 사무실로 들어왔다. 스승은 조용히 그를 지켜볼 뿐이었다.
"이 것은 통합적으로 분산된 다목적 워크스테이션이요." 마법사가 자랑스레 말하기 시작했다.
"인간환경공학적으로 설계된 독점 운영체제와 제6세대 언어, 그리고 복수의 최신 유저 인터페이스를 탑재하고 있지요. 이 워크스테이션을 제작하기 위해 수백명의 조수들이 몇 년이나 일해야 했소이다. 멋지지 않습니까?"
스승은 눈썹을 약간 치켜뜨며 대답했다. "정말 멋지군요."
"본사에서는 모든 사람들이 이 워크스테이션을 이용해서 새로운 프로그램을 개발해야 한다고 지시했소이다. 그러시겠습니까?"
"물론이지요. 워크스테이션을 즉시 컴퓨터실로 옮겨두겠습니다." 스승이 말했다.
마법사는 만족하여 자신의 탑으로 돌아갔다.
며칠 후 제자가 스승 프로그래머의 사무실로 들어와서 물었다. "새로 짠 프로그램의 리스트가 어디있는지 모르겠어요. 혹시 어디있는지 아세요?"
"물론이지. 컴퓨터실에 있는 검정색 상자 위에 있다." 스승이 말했다.
7.4
도사 프로그래머는 프로그램에서 프로그램으로 아무런 두려움없이 옮겨다닌다. 관리자가 어떻게 변해도 그의 위치는 변하지 않는다. 그는 프로젝트가 취소되더라도 해고되지 않는다. 왜 그럴까? 도사 프로그래머는 도로 충만하기 때문이다.
제 8 권 : 하드웨어와 소프트웨어
도사 프로그래머 가라사대 : "바람이 불지 않으면, 풀은 움직이지 않는다. 소프트웨어가 없으면 하드웨어는 쓸모가 없다."
8.1
제자가 스승에게 묻기를, "한 컴퓨터 회사는 다른 회사들에 비해 월등히 큽니다. 난장이들 사이에 선 거인처럼 보입니다. 이 회사의 한 부서만으로도 산업을 일으킬 수 있을 정도입니다. 왜 그렇습니까?"
스승이 답하여 가로되, "왜 그런 어리석은 질문을 하는가? 그 회사는 크기 때문에 큰 것이니라. 만일 그 회사가 하드웨어만 만들었다면 아무도 사지 않았을 것이다. 그 회사가 시스템의 유지보수만 했다면, 사람들은 그 회사를 하인처럼 다루었을 것이다. 하지만 그 회사는 이 모든 일을 하기 때문에 사람들은 그 회사를 신으로 여기는 것이다! 그들은 남들과 경쟁하려 들지 않기 때문에, 아무런 어려움없이 세상을 정복하는 것이다."
8.2
어느날 스승이 제자의 곁을 지나치고 있었다. 스승은 제자가 휴대용 게임기에 열중해 있음을 알았다. "미안하지만 내가 좀 볼 수 있을까?" 스승이 물었다.
제자는 깜짝 놀라 게임기를 스승에게 건네주었다. "이 게임은 Easy, Medium, Hard등 세단계로 이루어져 있구나. 하지만 이런 게임기에는 모두 또다른 레벨이 더 하나 존재하고 있다. 이 레벨에서는 게임기가 사람을 정복하려 들지 않으며, 사람도 게임기를 정복할 수 없다." 스승이 말했다.
"대단하십니다, 스승님." 제자가 탄성을 질렀다.
"어떻게 게임기에 또다른 레벨이 있다는 사실을 알아내셨나이까?"
스승은 게임기를 땅에 떨어뜨리더니 발로 밟아버렸다. 그러자 갑자기 제자는 깨달음을 얻었다.
8.3
개인용 컴퓨터로 작업을 하는 프로그래머가 있었다. 어느날 그는 자신의 작업실에 놀러온 메인프레임 프로그래머에게 자랑하기 시작했다."나를 좀 보라구. 나혼자만 쓸 수 있는 운영체제와 하드 디스크도 있어. 컴퓨터 용량을 다른 사람과 나누어 쓸 필요도 없지. 소프트웨어는 성능이 우수할 뿐 아니라 쓰기도 편해. 왜 메인프레임처럼 불편한 환경에서 일을 하는 거지?"
그러자 메인프레임 프로그래머는 자신의 시스템을 친구에게 설명하기 시작했다."메인프로그램은 컴퓨터실에서 명상하는 고대의 현인처럼 앉아 있다네. 그 디스크 드라이브는 마치 거대한 기게의 바다처럼 서로 연결되어 있지. 소프트웨어는 다이아몬드처럼 다양한 면을 지니고 있으며, 원시림처럼 서로 얽혀있네. 각각 독특한 프로그램들은 마치 거세게 흐르는 강물처럼 시스템으로 들어왔다 나가지. 그게 내가 메인프레임을 좋아하는 이유라네."
개인용 컴퓨터 프로그래머는 이 말을 듣고 할 말을 잃었다. 하지만 두 프로그래머는 죽을 때까지 친하게 지냈다.
8.4
갠지즈강으로 가던 하드웨어가 소프트웨어를 만났다. 소프트웨어 가로되, "너는 음이요 나는 양이로다. 우리가 함께 여행한다면 크게 유명해지고 많은 돈을 벌 수 있음에 틀림이 없도다."
그리하여 그들은 한쌍이 되어 세상을 정복할 야심을 품게 되었다.
그들은 찢어진 누더기를 입고 가시나무 지팡이를 집은채 절름거리는 펌웨어를 만나게 되었다. 펌웨어가 그들에게 가로되,
"도는 음과 양을 넘어 존재하느니라. 도는 호수의 물처럼 조용하고 움직이지 않느니라. 도는 명성을 구치 않으며, 따라서 아무도 그 존재를 알지 못하느니라. 도는 부를 구치 않으니, 도는 그 자체로 완전하기 때문이니라. 도는 시간과 공간을 넘어 존재하느니라."
크게 부끄러워진 소프트웨어와 하드웨어는 집으로 돌아가고 말았다.
제 9 권 : 에필로그
마침내 도사 프로그래머 가라사대 : "하산하거라."

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:24
함수에 의한 모듈화에서는 모듈화 단위가 함수 하나만 가능합니다. 앞에서 살펴보았듯이 2개 이상의 함수를 하나의 모듈로 만들려면 스코프(scope) 및 이름공간(namespace) 문제로 함수로는 불가능하며 이 때는 반드시 클래스를 이용하여야 합니다.
이상과 같이 살펴보았듯이 클래스가 필요할 때가 있고 함수가 필요할 때가 있습니다. 모든 경우에 다 클래스를 사용하는 것은 비효율적일 수 있습니다. 경우에 따라 적절히 선택하는 지혜가 필요합니다.
  1. 함수도 필요없을 만큼 간단한 소스를 작성한다면 함수에 의한 모듈화도 필요없고 구조화 프로그래밍만 하면 됩니다.
  2. 모듈화가 필요하기는 한데 작성된 함수들이 단순히 단타성 함수로만 사용된다면 함수를 이용하여 모듈화하세요.
  3. 모듈화 단위가 여러 개의 함수로 구성된 라이브러리라면 특별한 경우가 아니라면 클래스를 이용하여 모듈화하세요.
여러분에게 PHP에서 클래스를 이용하여 객체지향 프로그래밍을 하라고 권하지는 않겠습니다. 여러분의 판단에 맡기지요. 그러나 클래스를 이용한 모듈화 프로그래밍에는 망설이지 마십시요. 여러분이 생각하는 것처럼 클래스를 이용하였다고 해서 객체지향 프로그래밍이 되는 것은 아닙니다. 그러나 클래스는 모듈화를 위한 훌륭한 도구입니다. 모듈화 도구로써 함수가 삽이라면 클래스는 포크레인입니다.
PHP에서 함수라는 도구를 우리에게 제공하므로서 우리가 함수를 유효적절하게 이용할 수 있었듯이 클래스라는 도구 또한 우리는 최대한 이용하여야 할 것입니다. 클래스는 타도 대상이 아니라 프로그래밍을 하는 우리를 도와주는 친구입니다.

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:23
이름공간은 현재 동작하는 프로그램에 정의되어 있는 변수명, 함수명, 클래스명 등과 같은 이름을 기록하기 위한 공간에 관련된 매카니즘을 총칭합니다. PHP에는 아래와 같이 크게 3가지 이름공간이 존재하는 것으로 보입니다.
전역 이름공간 - 함수(또는 클래스) 바깥쪽에서 정의된 이름
지역 이름공간 - 함수(또는 메소드) 안에서 정의된 이름 또는 클래스 안에서 정의된 이름
내장 이름공간 - PHP 자체에 정의된 이름(연산자들과 같은 각종 키워드),
                      함수명과 같이 프로그램 어느 곳에서나 제한없이 접근할 수 있는 이름
이와 같이 이름공간이 독립적으로 분리되어 있으므로 동일한 이름이 서로 다른 지역에 존재할 수 있도록 허용하고 있습니다.
[code php;gutter:false] <?php

$str = "전역 이름공간의 변수";

function test() {
$str = "지역 이름공간의 변수";
echo "$str<BR>\n";

global $str;
echo "$str<BR>\n";
}

test();

?> [/code]
위의 소스와 같이 같은 함수 내에서 지역변수와 전역변수가 동시에 나타난다면 먼저 전역 이름공간을 참조하게 될 것입니다. 따라서 이 소스를 실행하면 아래와 같이 나타날 것입니다. 위의 소스와 같이 함수 내에서 사용되는 변수명은 지역 이름공간에서 찾게 됩니다. 전역 이름공간의 이름을 사용하려면 global 키워드로 먼저 선언해주어야 합니다.
지역 이름공간의 변수
전역 이름공간의 변수
함수마다 별도의 이름공간을 제공해 주기때문에 앞에서 설명한 모듈화가 가능하게 되지요.
만약 이름공간 안에 없는 이름을 참조한다면 어떻게 될까요? 물론 어떻게 처리하는가에 대한 매카니즘은 그 대상이 변수냐 함수냐 등에 의해 다르게 처리되겠지요. 변수인 경우라면 참조한 위치가 전역 위치면 전역 이름공간을 살펴보고 없으면 전역 이름공간에 새로운 이름을 생성합니다. 그리고 참조한 위치가 함수 내와 같은 지역 위치면 해당 함수의 지역 이름공간을 살펴보고 없으면 이 공간에 새로운 이름을 생성합니다.
함수라면 좀더 복잡할 것입니다. 함수를 정의하면서 함수명을 이름공간에 생성하려고 할 때 이미 해당 이름공간에 함수명이 있다면 중복된 함수 정의라는 에러메시지를 보여줄 것입니다. 반면에 함수를 실행하려고 이름공간을 참조하였을 때 이 이름공간에 해당 함수명이 없다면 정의된 함수가 없다고 에러메시지를 보여줄 것입니다.
여러 해동안 웹프로그래밍을 하다보면 나도 모르는 사이에 많은 함수들이 하드디스크에 쌓여가는 것을 볼 수 있습니다. 이 양은 적지 않은 분량으로 이러한 함수를 이용하여 파일 입출력을 다루고, 문자열을 편리하게 처리하도록 도움받게 됩니다.
그런데 이러한 함수의 분량이 쌓여가다보면 개발자는 동일하거나 비슷한 기능의 함수를 다시 작성하는 경우도 빈번하고 더 나아가 동일한 함수명을 사용하는 경우도 발생합니다.
PHP 는 이와 같이 동일한 함수명을 중복하여 정의하여 사용할 경우 에러를 발생시켜 줍니다. 이와 같이 프로그램에서 중복된 이름을 사용할 때 이를 방지하기 위한 매카니즘이 동작하여 이에 의해 중복된 이름을 사용하였을 때 강제적으로 에러를 발생시키도록 하는 것입니다. 이와 같이 해당 이름공간 안에 있는 모든 함수는 자신만의 이름을 가지게 됩니다.
PHP 에서는 대부분 함수를 이용하여 라이브러리를 구축할 때 파일 단위로 묶어 놓게 됩니다. 그런데 파일 단위로 묶여 있는 라이브러리마다 라이브러리 내에서 발생하는 사용자 정의 에러를 처리하기 위하여 에러를 처리하는 함수를 정의하여 사용하게 되지요. 예를 들면 아래와 같이 warning() 함수를 정의하게 됩니다.
[code php;gutter:false] function warning($msg) {
?>
<SCRIPT language=JavaScript>
<!--
window.alert("<?php echo $msg ?>");
//-->
</SCRIPT>
<?php
} [/code]
이러한 에러 처리 함수는 각 라이브러리마다 조금씩 다르게 정의할 수도 있고 때에 따라서는 동일하게 정의할 수도 있겠지요. 그런데 만약 a라는 라이브러리와 b라는 라이브러리에 모두 이와 같은 에러 처리 함수 warning() 함수가 있고 우연히 동일한 웹페이지에서 a와 b 라이브러리를 모두 불러들였다고 하지요. 웹페이지를 실행하면 PHP는 당연히 이름공간 매카니즘에 의해 중복된 함수를 정의하였다는 에러를 신속히 보여줄 것입니다.
여러분은 이러한 에러를 방지하기 위해 나름대로 대책을 세우셨을 것입니다. 에러 처리 함수를 별도의 파일로 구성하여 놓을 수도 있겠지요. 그리고 a와 b 라이브러리에서 에러 처리 함수가 포함된 파일을 포함(include)하겠지요.
아니면 a라는 라이브러리의 에러 처리 함수명을 warning() 대신에 a_warning()로 변경하고, b라는 라이브러리의 에러 처리 함수명을 b_warning()로 변경할 수도 있겠지요.
결국 어떠한 대책이 되었든지간에 함수를 이용하는 한은 불편하기도 하고 실수할 가능성도 상당히 높습니다. 그래서 PHP는 함수라는 도구보다 더욱 강력한 도구인 클래스라는 것을 우리에게 선물로 주었습니다. 위의 예에서 발생한 이름공간 문제를 클래스를 이용하여 해결하여 보지요.
[code php;gutter:false] class a {
function warning($msg) {
?>
<SCRIPT language=JavaScript>
<!--
window.alert("<?php echo $msg ?>");
//-->
</SCRIPT>
<?php
}
}

class b {
function warning($msg) {
?>
<SCRIPT language=JavaScript>
<!--
window.alert("<?php echo $msg ?>");
//-->
</SCRIPT>
<?php
}
} [/code]
여기서 클래스 a와 b가 동일한 파일에 있어도 좋고 다른 파일에 있어도 관계없겠지요. 일단 위와 같이 클래스 a, b 내에 동일한 이름의 에러 처리 함수(메소드) warning()를 정의하여 놓더라도 이름공간 문제가 발생하지 않습니다. 왜냐하면 클래스 a와 b는 서로 다른 이름공간을 가지게 되니까요.
그런데 에러 처리 함수를 클래스의 멤버로 정의하지 않고 일반 함수로 정의하게 되면 이 함수명은 전역 이름공간(global name space)에 있게 됩니다. 동일한 이름공간 내에서는 중복된 이름을 가질 수 없기 때문에 결국 일반 함수로 정의하면 문제가 발생하는 것이지요.
반면 클래스는 각 클래스마다 독립적인 이름공간을 가지기 때문에 함수명이 중복되어도 에러가 발생하지 않습니다. 아울러 클래스에서는 오버로딩, 오버라이딩과 같은 특성을 제공하기 때문에 이름공간의 융통성(?)이 막강하지요.
[주의] PHP에서는 오버로딩을 지원하지 않습니다. 오버라이딩도 너무 포괄적(?)으로 지원합니다.
함수를 통해 모듈화를 하더라도 여러 개의 함수가 모이다보면 함수명의 중복으로 인하여 문제가 발생하는 것입니다. 일반 함수명은 모두 동일한 전역 이름공간에 생성되며 따라서 함수가 많을 때는 중복될 가능성이 많아지게 됩니다. 중복되지 않도록 개발자가 직접 관리해야 하는데 사람이라는 것이 워낙 실수도 많고 기억에도 한계가 있다보니 자연히 한계에 부딪치게 되지요.
결국 여러 개의 함수로 구성된 라이브러리와 같은 경우에서는 라이브러리 전체를 하나의 모듈로 묶어줄 수 있는 강력한 모듈화 도구인 클래스로 감싸줌으로써 함수명의 중복에 따른 문제를 쉽게 해결할 수가 있는 것이지요.

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:22
모듈화 프로그래밍에서 우리는 함수를 이용하여 모듈화를 할 수 있다는 것을 알았습니다. 그런데 함수를 이용한 모듈화에는 한계가 있습니다. 하나의 함수 내에서 사용할 변수는 얼마든지 정의하여 사용할 수 있습니다. 즉 지역변수지요. 그런데 만약 2개 이상의 함수에서 공유해야 할 변수가 필요하다면 어떻게 할까요. 전역변수 외에는 방법이 없지요. 그런데 모듈화의 개념이 무엇이라고 앞에서 말씀드렸지요? 바로 블랙박스입니다. 블랙박스 안의 내용은 절대로 불법적(함수를 통한 정상적인 방법으로 접근하지 않는 것을 의미)으로 접근되어서는 안됩니다. 그런데 2개 이상의 함수에서 공유해야할 변수로 전역변수를 이용한다면 이 전역변수는 공유하고 있는 2개 이상의 함수 이외의 곳에서도 얼마든지 접근이 가능하지요. 모듈화 개념에서 벗어나는 것이지요.
아래와 같은 함수가 있다고 가정하지요. 왜 이렇게 작성했는가는 따지지 마세요. 설명하기 위한 것이니까요.
여기에서 $str은 함수 내에서만 사용할 수 있는 지역변수(local variable)입니다. $str 값은 get_string() 함수의 리턴값으로만 반환받을 수 있지 다른 방법으로는 접근할 수가 없습니다. 따라서 이 함수는 모듈화 개념에 맞게 잘 작성된 것입니다.
[code php;gutter:false] function get_string() {
$str = "1234567890";

return $str;
} [/code]
이것을 몇 개의 함수를 이용하여 문자열 자르기를 위한 라이브러리로 확장시켜보지요.
[code php;gutter:false] /*
문자열 자르기를 위한 라이브러리(일반 함수를 이용할 때)
*/

$bank;

function get_string() {
global $bank;
return $bank;
}

function set_string($str) {
global $bank;
$bank = $str;
}

function cut_string($len) {
global $bank;
$bank = substr($bank, 0, $len);
}

set_string("1234567890");
cut_string(4);
echo get_string(); // "1234"가 출력되겠지요. [/code]
set_string() 함수를 이용하여 자르고자 하는 문자열을 지정하고, cut_string() 함수를 이용하여 자를 문자열 길이를 지정하여 자르고, get_string() 함수를 이용하여 자른 문자열을 돌려받습니다.
이와 같이 문자열 자르기를 위하여 몇 개의 함수를 모아서 라이브러리화 시켰더니 모든 함수가 공유해야할 $bank 변수가 필요해 졌습니다.
이렇게 작성된 문자열 자르기 라이브러리를 볼 때 모듈화 관점에서 문제점이 무엇입니까? 앞에서도 언급하였듯이 모듈화가 되려면 함수명, 입력값, 출력값 외에는 외부세계에서 접근이 불가능해야 합니다. 그런데 $bank 변수가 전역변수(global variable)로 사용되다보니 문자열 자르기 라이브러리 외의 어느 곳에서도 쉽게 접근할 수 있는 화이트박스(?)가 되어 버렸지요.
이것이 함수를 이용한 모듈화의 한계입니다. 2개 이상의 함수에서 공유해야할 변수를 블랙박스 내에 담을 수 있는 도구가 바로 클래스입니다. 클래스라는 도구를 통해 모듈화가 보다 완전해 지는 것이지요.
[code php;gutter:false] /*
문자열 자르기를 위한 라이브러리(클래스를 이용할 때)
*/

class string {
var $bank;

function get() {
return $this->bank;
}

function set($str) {
$this->bank = $str;
}

function cut($len) {
$this->bank = substr($this->bank, 0, $len);
}
}

$string = & new string; // 객체 $string의 생성

$string->set("1234567890");
$string->cut(4);
echo $string->get(); // "1234"가 출력되겠지요. [/code]
[주의] PHP 와 C++ 언어에서 클래스를 이용할 때의 모듈화의 완전성을 비교해 볼 때 PHP의 모듈화는 다소 덜 완전합니다. 즉, C++에서는 액세스 권한(access right) 지정자 private를 이용하면 클래스 외부 세계에서는 해당 변수에 절대로 접근할 수 없으나 PHP에서는 아직 액세스 권한 지정자 개념이 도입되지 않았기때문에 객체를 통하여 변수에 접근할 수가 있습니다. 그러나 역시 객체를 통하지 않고는 접근할 수 없다는 면에서 볼 때 일반 함수를 통한 모듈화보다는 훨씬 뛰어난 모듈화 성능을 보여주고 있습니다.
[참고] PHP 가 아닌 C++ 또는 java와 같은 객체지향 프로그래밍에서의 변수의 사용범위는 더욱 다양합니다. 다른 말로하면 복잡하다는 말이기도 하지요. public, private, protected와 같은 액세스 권한 지정자에 의해 클래스 내에서의 사용범위를 조절할 수 있습니다.

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:21
우리도 웹 문서를 옛날 GW-BASIC에서 하던 것처럼 함수를 전혀 사용하지 않고도 작성할 수 있습니다. 그런데 왜 함수를 사용합니까? 가장 중요한 것이 모듈화이지요. 입력값과 출력값만 공개되어 있지 내부에서 이 값들이 어떻게 처리되는 지는 알 수 없지요.
요즘 게시판에 가면 심심치않게 등장하는 문자열 자르기 함수를 예로 들어보지요.
[code php;gutter:false] /*
함수명 : cut_string
입력값 : string, length
출력값 : string
기 능 : 지정된 문자열에서 지정된 글자수만큼만 되돌려 준다.
*/

function cut_string($str, $len) {
return substr($str, 0, $len);
} [/code]
이 문자열 함수를 이용하는 개발자에게 필요한 것은 함수명, 입력값, 출력값입니다. 그 외에 함수 내부적으로 입력값이 어떻게 처리되어 출력값을 내보내는지에 대하여는 전혀 알 필요도 없습니다.
만약 이 함수를 개선하여 2바이트 문자(한글 등)도 정상적으로 처리되도록 하기 위해서는 아래와 같이 함수 내부를 수정하여야 할 것입니다. 그러나 이 함수를 이용하고 있는 소스는 전혀 수정할 필요가 없겠지요. 입력값과 출력값이 같으니까요.
[code php;gutter:false] /*
함수명 : cut_string
입력값 : string, length
출력값 : string
기 능 : 지정된 문자열에서 지정된 글자수만큼만 되돌려 준다.
2바이트 문자(한글 등)도 정상적으로 처리되도록 한다.
*/

function cut_string($str, $len) {
if(strlen($str)<$len) {
return $str; //지정된 길이보다 문자열이 작으면 그냥 리턴
}

for($i=0; $i<$len-1; $i++) {
if(ord($str[$i])>127) {
$i++; //한글일 경우 2byte 이동
}
}

return substr($str,0,$i);
} [/code]
이와 같이 함수를 이용하면 함수 내를 하나의 블랙박스로 숨겨놓을 수 있습니다. 외부 세계와는 완전히 차단된 독립적인 세계이지요. 모듈화 프로그래밍은 이와 같이 부분적인 기능들을 모두 블랙박스로 만들어 놓은 후에 이러한 블랙박스를 하나하나 조립하여 전체적으로 완성시켜가는 것입니다.
여러분은 알게모르게 이미 함수를 통해 모듈화 프로그래밍을 하고 있으며 이를 통해 프로그램 개발에 많은 향상과 이점을 가질 수 있었습니다. 이러한 모듈화 개념은 프로그래밍을 하는데 없어서는 안될 무지무지하게 중요한 개념이지요. 함수를 통해 구현되는 모듈화는 함수 내의 정보를 외부세계와 독립적으로 구성하기 위한 것이며 다른 말로 하면 함수 내의 정보를 숨기기 위한 것입니다.
객체지향 프로그래밍에서의 캡슐화(encapsulation)라는 개념도 모듈화 개념과 비교할 때 그 역할이 동일합니다. 즉 블랙박스화이지요. 단지 블랙박스화 하기 위한 도구와 그 대상이 다를 뿐입니다. 모듈화의 도구로 함수를 이용하였듯이 캡슐화의 도구로 클래스를 이용할 뿐입니다. 캡슐화에 대하여는 더 이상 깊이 들어가지 않겠습니다. 그러나 분명히 이해하여야 할 것은 그 역할이 모듈화와 동일하다는 것입니다. 그래서 이 문서에서는 앞으로 클래스를 이용한 캡슐화를 그냥 모듈화라고 부르기로 하겠습니다.
이제는 아래와 같은 도식을 얻을 수 있겠지요.
모듈화 = 캡슐화 = 블랙박스화

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:20
1990 년대초에 객체지향 프로그래밍(Object-Oriented Programming)이라는 방법이 나타나기 전까지는 파스칼 또는 C를 중심으로한 구조화/모듈화 프로그래밍(Structured/Modular Programming)이 전세계를 지배하고 있었습니다.
2002 년을 보내고 있는 현시점까지도 웹프로그래밍 언어인 PHP에서는 구조화/모듈화 프로그래밍의 지배를 받고 있지요. 그러나 구조화/모듈화 프로그래밍에는 많은 문제가 있기 때문에 PHP도 객체지향 프로그래밍쪽으로 점점 무게가 실리게 될 것입니다.
어쨌든지간에 현재까지도 PHP를 지배하고 있는 구조화/모듈화 프로그래밍에 대하여 먼저 알아보고 그 다음에 과연 구조화/모듈화 프로그래밍을 할 때도 과연 객체지향 프로그래밍의 도구인 클래스를 사용해야 하는가에 대하여 숙고해 보도록 하겠습니다.
그럼 우선 클래스의 필요성을 살펴보기 전에 구조화/모듈화 프로그래밍에 대하여 살펴보도록 하겠습니다.
1970 년대에 제안된 구조적 기법(구조화/모듈화 프로그래밍)을 통하여 프로그래머는 체계적인 방법으로 보다 쉽게 프로그램을 작성할 수 있을 뿐만 아니라, 일단 작성된 프로그램은 누구나가 쉽게 읽고 이해할 수 있어서 이후에 프로그램을 쉽게 수정할 수 있었습니다.
구조화 프로그래밍(Structured Programming)
프로그램이 커지고, 기능이 복잡해지면 개발 뿐만 아니라 수정과 유지 보수에 오히려 더 많은 시간과 노력이 필요하게 됩니다. 이러한 문제에 대처하기 위하여 프로그램의 구조를 순차, 선택, 반복 제어 구조만으로 설계하여 처리 절차를 간단하고 명료하게 표현할 수 있는 구조화 프로그래밍 기법이 나타나게 되었습니다.
▶순차 처리
▶선택 처리
▶반복 처리
그 옛날 BASIC에서의 Go To문과 같은 분기를 허용하지 않고 일의 순서에 따라 시작부터 끝까지 한 방향으로 진행하도록 처리하는 것이 "순차 처리"이며, if 또는 switch 문과 같이 주어진 조건에 따라 명령문을 선택하여 처리하는 구조가 "선택 처리"이며, while, for next 문과 같이 주어진 조건을 만족할 때까지 일정한 범위의 명령문들을 반복 수행하는 구조가 "반복 처리" 구조입니다.
구조화 프로그래밍은 프로그램의 구조가 논리적으로 구성되어 있어 아래와 같은 특징을 가지게 됩니다.
▶코딩이 쉽다(분석,설계,제작)
▶프로그램을 읽기 쉽게 한다(가독성)
▶테스트를 쉽게 한다(테스트)
▶수정하기 쉽다(유지 보수)
모듈화 프로그래밍(Modular Programming)
프로그램을 작성할 때 큰 프로그램을 한번에 작성하는 것이 아니라 기능별로 나누어 우선 부분별 작성을 한 다음, 각각의 작은 프로그램들을 서로 연결시켜 하나의 완성된 프로그램을 만드는 방법으로 기능별로 나누어진 각 모듈은 각각 이 하나의 기능을 수행하며 그 기능을 수행하기 위하여 필요한 모든 코드와 변수를 포함하도록 하는 프로그래밍 방식입니다.
프로그램 덩치가 큰 프로그램을 모듈별로 나누지 않고 단지 구조화 프로그래밍만을 이용하여 하나로 작성하기는 무척 어렵습니다. 그러나 구조화 프로그래밍을 적용하기 전에 먼저 모듈화 프로그래밍을 적용한 후에 각 모듈별로 구조화 프로그래밍을 적용하게 되면 그 구현이 매우 쉽게 됩니다.
모듈화 프로그램밍은 아래와 같은 특징을 가짐으로 말미암아 구조화 프로그래밍과 마찬가지로 프로그램의 구조가 논리적으로 구성되어 있어 프로그램의 작성/수정이 용이하고, 이해하기가 쉽습니다.
▶하나의 모듈은 유일한 하나의 입구(Entry point)와 유일한 출구(Exit point)를 갖는다.
▶하나의 모듈은 독립적인 구조를 갖는다.
   (프로그램내에서 하나의 독립적인 기능을 수행)
▶모듈은 개별적으로 테스트가 가능하다.

Posted by 방글24
phpclass/클래스활용2002. 9. 13. 10:09
부제:클래스를 이용한 모듈화 프로그래밍
PHP 를 가지고 웹프로그래밍을 하면서 과연 클래스를 사용해야 하는지에 대하여 살펴보겠습니다. 클래스가 객체지향 프로그래밍의 도구이기는 하지만 여기서는 객체지향개념을 도입하지 않고 구조화/모듈화 프로그래밍에서의 모듈화 개념, 좀더 구체적으로 말하면 스코프(scope)와 이름공간(name space)이라는 개념을 가지고 클래스를 사용할 필요가 있는지에 대하여 살펴보고자 합니다. 객체지향개념을 가지고 클래스를 사용해야 한다고 설명하면 반론이 만만치(?) 않을 것이기 때문에 가능한한 불필요한 논쟁을 피하고자 합니다.
본인의 전공이 컴퓨터 공학 내지는 소프트웨어 공학이 아닌 고로 이론적인 면에 서투른 점이 많이 보일 것입니다. 그러한 부분은 기탄없이 지적하여 주시면 감사하겠습니다.

Posted by 방글24
phpsource/파일분석2002. 9. 9. 16:48
여기서 공개하는 hTarFile 클래스는 바로 TAR 아카이브를 생성하거나 또는 풀 수 있도록 작성된 소스이며 PHP에 내장되어 제공되고 있는 zlib 라이브러리(gz로 시작하는 함수들)를 이용하여 압축할 수 있도록 하였습니다.
hTarFile 클래스 0.0.1 버전 설계의 기본 컨셉은 기존의 유닉스 tar 유틸리티의 사용법만 알면 별문제없이 사용하도록 하겠다는 것입니다. 따라서 이미 tar 유틸리티를 사용할 줄 아는 유닉스 사용자라면 별 어려움없이 hTarFile 클래스를 이용할 수 있으리라 생각합니다.
객체 생성 및 생성자
[code php;gutter:false] require_once("class.hTarFile.php");
$my = & new hTarFile; [/code]
public 메소드
void root(string path-to-files);
root 메소드로 지정하는 path-to-files 인자는 묶고자 하는 파일들의 기본 디렉토리를 의미합니다. 클래스 내의 모든 메소드는 이 기본 디렉토리를 베이스로 처리하기 때문에 매우 중요합니다. 지정하지 않으면 null로 처리되므로 TAR 아카이브를 다루어주는 tar 메소드에서 디렉토리를 완벽하게 지정하여야 합니다.
또 한가지 중요한 것은 여기서 지정되는 path-to-files는 hTarFile 클래스를 이용하기 전에 먼저 해당 서버의 쉘 명령을 이용하여 생성시켜야 하며 TAR 아카이브 또는 tar.gz 파일이 기록되는 디렉토리는 반드시 디렉토리 내에 파일을 기록할 수 있도록 퍼미션을 조정하셔야 합니다. 가장 쉬운 방법은 퍼미션을 777로 설정하는 것이지요. 물론 윈도우 서버에서는 퍼미션 대신에 "읽기전용"으로만 해놓지 않으면 됩니다.
이와 같이 생성 또는 추출하고자 하는 TAR 아카이브 및 TAR 아카이브에 속할/속한 멤버파일들의 기본 디렉토리를 root 메소드로 지정합니다. 일단 root 메소드로 디렉토리가 지정된 후에는 tar 메소드에서는 이 기본 디렉토리를 기준으로하여 상대디렉토리가 지정됩니다.
[code php;gutter:false] $my->root("/tmp/hFiles");
$my->tar("cfz sample.tar.gz s1.txt"); [/code]
묶고자 하는 파일 s1.txt는 /tmp/hFiles 에 있으며, 또한 생성하고자 하는 sample.tar.gz 파일도 /tmp/hFiles 에 생성됩니다. 만약 root 메소드에 지정된 디렉토리가 절대디렉토리가 아니라 상대디렉토리로 지정하였다면 기준이 되는 디렉토리는 현재 실행중인 문서가 있는 디렉토리가 됩니다.
int tar (string options, string tar_filename, string files or dirs)
[code php;gutter:false] $my->tar("cfz sample.tar.gz s1.txt s2.txt s3.txt subdir1 subdir2"); [/code]
사용법은 리눅스에서 제공되는 tar 유틸리티와 거의 유사합니다. tar 유틸리티와 다른 점은 옵션 앞에 붙게 되는 -(minus) 부호가 생략되었다는 것입니다. 다른 것은 동일합니다. 물론 기능적인 것으로 보면 tar 유틸리티가 제공하는 모든 기능을 제공하지는 않으며 그 중에 꼭 필요한 옵션만 제공합니다. 또한 tar 유틸리티에서는 x 옵션을 주었을 때 TAR 아카이브 파일명 뒤에 파일명이나 디렉토리명을 지정하면 해당 파일 또는 디렉토리의 내용만 추출하게 됩니다. 그러나 hTarFile 클래스에서는 파일이나 디렉토리명을 지정하더라도 이를 무시하고 전체를 추출하도록 되어 있습니다. 이 부분은 향후 업그레이드하면서 업하도록 노력하겠습니다.
TAR 아카이브 생성이나 추출에 성공하면 멤버파일 리스트를 되돌려 주며 실패하면 false 값이 되돌려 줍니다.
[code php;gutter:false] require_once("class.hTarFile.php");
$my = & new hTarFile;

$my->root("/tmp/ext");

if (!$files=$my->tar("xfz sample.tar.gz")) {
die("unable to extract TAR archive");
} else {
printf("<P>TAR archive was successfully extracted!</P>\n");

foreach ($files as $file) {
printf("%s<BR>\n", $file);
}
} [/code]
1) TAR 아카이브로 묶기
리눅스의 tar 유틸리티에서 여러 개의 파일을 TAR 아카이브로 묶기 위해서는 아래와 같이 하게 되지요.
tar -cf  tar-file file | dir ......
예를 들면
tar -cf sample.tar s1.txt s2.txt sub1 sub2
이 명령을 수행하면 s1.txt, s2.txt 파일과 sub1, sub2 디렉토리에 있는 모든 파일을 하나의 파일 sample.tar에 묶어 버리지요. 이를 hTarFile 클래스의 메소드 tar를 이용한다면 아래와 같습니다.
[code php;gutter:false] $my->root("/hwooky");
$my->tar("cf sample.tar s1.txt s2.txt sub1 sub2"); [/code]
이 문장들을 수행하게 되면 "/hwooky" 디렉토리에 있는 s1.txt, s2.txt와 /hwooky/sub1, /hwooky/sub2 디렉토리에 있는 모든 파일을 sample.tar 아카이브 파일로 묶게 됩니다.
2) TAR 아카이브을 풀기
리눅스의 tar 유틸리티에서 TAR 아카이브를 여러 개의 파일로 풀기 위해서는 아래와 같이 하게 되지요.
tar -xf  tar-file
예를 들면
tar -xf sample.tar
이를 hTarFile 클래스의 메소드 tar를 이용한다면 아래와 같습니다.
[code php;gutter:false] $my->root("/tmp/hFiles/extract");
$my->tar("xf sample.tar"); [/code]
앞에서 설명하였듯이 이 메소드를 수행하기 전에 root 메소드에서 지정한 "/tmp/hFiles/extract" 디렉토리를 먼저 만들어주고 퍼미션을 쓰기가능하도록 (예를 들면 chmod 777) 설정하여야 제대로 파일을 풀어줄 수 있습니다.
3) tar.gz 파일로 압축하기
리눅스의 tar 유틸리티에서 여러개의 파일을 TAR 아카이브로 묶음과 동시에 자동적으로 gzip 명령으로 압축하기 위해서는 z 옵션을 추기하여야 합니다.
tar -cfz  tar-file file | dir ......
예를 들면
tar -cfz sample.tar.gz s1.txt s2.txt sub1 sub2
이 명령을 수행하면 s1.txt, s2.txt 파일과 sub1, sub2 디렉토리에 있는 모든 파일을 하나의 파일로 묶음과 동시에 gzip 형식으로 압축하여 sample.tar.gz 파일로 저장합니다. 이를 hTarFile 클래스의 메소드 tar를 이용한다면 아래와 같습니다.
[code php;gutter:false] $my->tar("cfz sample.tar.gz s1.txt s2.txt sub1 sub2"); [/code]
4) tar.gz 파일을 압축해제하기
리눅스의 tar 유틸리티에서 여러개의 파일을 TAR 아카이브로 묶음과 동시에 자동적으로 gzip 명령으로 압축하기 위해서는 z 옵션을 추기하여야 합니다.
tar -xfz  tar-file
예를 들면
tar -xfz sample.tar
이를 hTarFile 클래스의 메소드 tar를 이용한다면 아래와 같습니다.
[code php;gutter:false] $my->tar("xfz sample.tar"); [/code]
메소드 tar에서 지원하는 옵션
hTarFile 클래스의 메소드 tar에서 지원하는 옵션을 정리하면 아래와 같습니다.
< 지원하는 옵션 >
지원하는 옵션 기  능

c

TAR 아카이브 생성

f

TAR 아카이브 파일명 지정

x

TAR 아카이브 추출

z

TAR 아카이브를 압축 및 해제

이 옵션 중에서 f 옵션은 반드시 지정하여야 하고 z 옵션은 압축할 필요가 있을 때만 지정하면 됩니다. 나머지 c와 x 옵션은 둘 중에 하나만 선택하십시요. 묶으려면 c 옵션을 선택하고 풀려면 x 옵션을 선택하십시요.

'phpsource > 파일분석' 카테고리의 다른 글

{INI 파일}1.개요  (0) 2003.06.25
{TAR 파일}8.클래스 다운로드  (0) 2002.09.16
{TAR 파일}6.zlib를 이용한 압축  (0) 2002.09.09
{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
{TAR 파일}4.본문 구조  (0) 2002.09.09
Posted by 방글24
phpsource/파일분석2002. 9. 9. 16:47
PHP에서 제공하는 함수에는 파일을 압축할 수 있는 zlib 라이브러리를 기본적으로 제공하고 있습니다.
압축하기
리눅스의 gzip 프로그램의 출력과 호환성을 유지하기 위해서는 zlib 라이브러리에서 제공하는 함수 중에서 gzencode 함수를 이용하여야 합니다. 이 함수에 의해 얻은 값은 gzip 프로그램의 출력값과 호환성을 가지므로 리눅스의 gzip 프로그램 또는 윈도우의 윈도우커맨더를 가지고 압축을 풀 수가 있습니다. 예를 들어 gzencode 함수를 이용하여 gz 파일을 생성해 주는 사용자 정의 함수를 작성하면 아래와 같습니다.
[code php;gutter:false] function gzcreate($gzfile, $contents) {
if (!$contents=gzencode($contents)) { // PHP4 >= 4.0.4
return false;
}

if (!$fp=fopen($gzfile, "wb")) {
return false;
}

fwrite($fp, $contents);
fclose($fp);

return true;
} [/code]
위 소스 중에 fopen 함수에서 mode 인수를 "wb"로 설정하였습니다. 유닉스에서는 이진(binary)을 의미하는 "b"를 사용하지 않더라도 정상적으로 파일을 처리해 줍니다. 그러나 윈도우에서는 이진 파일과 텍스트파일을 구분하여 저장하거나 읽지 않으면 저장된 파일을 정상적으로 다룰 수 없습니다. 가끔가다 자료실에 있는 이미지 파일이나 압축파일을 다운로드할 때 파일의 헤더부분만 읽어오므로 아무런 내용도 담기지 않은 파일이 다운로드될 때가 있습니다. 이럴 때는 해당 파일이 정확히 이진 모드로 다루어졌는지 확인하여야 합니다. 따라서 리눅스나 유닉스 계통에서는 별 문제가 없는데, 윈도우 서버에서 그런 문제가 발생할 수 있습니다. 따라서 윈도우에서 이미지 파일 또는 압축파일과 같이 바이너리 형태의 파일을 읽거나 쓸 때는 fopen 모드 인자에 반드시 "b" 옵션을 추가해야 정상적으로 다룰 수 있습니다. 유닉스에서는 "b" 옵션을 사용하지 않으며, 설사 "b" 옵션을 지정하더라도 그냥 무시해 버립니다.
압축해제하기
예를 들어 gzib 함수를 이용하여 압축된 파일을 풀기위해서는 대략 아래와 같이 사용자 정의 함수 gzextract 함수를 작성하면 될 것입니다.
[code php;gutter:false] function tarextract($gzfile) {
if (!$fp=fopen($gzfile, "rb")) {
return false;
}

$contents = fread($fp, filesize($gzfile));
fclose($fp);

if (!$contents=gzdecode($contents)) { // PHP4 >= 4.0.4
return false;
}

return $contents;
} [/code]
위의 코드가 제대로 실행될 것 같습니까? 아닙니다. 2002년 8월 31일 현재 PHP에서는 gzencode 함수만 제공할 뿐 gzdecode 함수를 제공하고 있지 않습니다. 그러나 http://www.php.net/manual/en/function.gzencode.php를 보시면 gzdecode 함수를 구현해 주는 팁이 공개되어 있습니다. 그 내용은 아래와 같습니다.
henryk@ploetzli.ch
14-Feb-2002 07:28

Well, I was looking for a gzdecode too and didn't consider the temporary file example above
to be very elegant.
However, as is noted in the very first comment: gzencode() only adds a 10 byte header.

I don't quite know what this header is supposed to be used for, but gzinflate() certainly
doesn't like it, so I stripped it off:

function my_gzdecode($string) {
$string = substr($string, 10);
return gzinflate($string);
}

That's useful to read HTTP-Connections that were compressed by mod_gzip.
--
Henryk Plotz
Gruße aus Berlin


tychay@alumni.caltech.edu
03-Apr-2002 03:53

The 10 byte string in gzencode is the standard gzip header. The first two bytes (1f 8b)
define the return as a gzip file, the third byte (08) means that the body is compressed using
the "deflate" algorithm. The rest is padding (00)'s.

Technically, I believe one should check if the third byte is hex 08 and if so strip off the
first ten bytes and last four bytes and run inflate on it. The last four bytes are file size
and checksum bits.

In practice, you can get away with just stripping the first 10 bytes and running inflate on
it.

Hope this helps,

terry
이 팁에 의해 gzdecode 함수를 작성하면 대략 아래와 같이 될 것입니다.
[code php;gutter:false] function gzdecode($data) {
if("\x1f\x8b\x08" == substr($data, 0, 3)) {
return gzinflate(substr($data, 10, -4)); // PHP4 >= 4.0.4
}
return false;
} [/code]
그런데 이렇게 작성된 gzdecode 함수도 그리 완벽하지는 않습니다. 위에서 설명한 gzencode 함수로 생성된 압축파일을 푸는데는 전혀 문제없이 동작합니다만 리눅스의 gzip 또는 윈도우의 윈도우커맨더, 알집 등으로 압축한 파일은 정상적으로 풀지를 못하네요. 즉, 팁에 의해 작성된 사용자 정의 함수 gzdecode는 리눅스의 gzip 프로그램의 출력과 완전한 호환성을 유지하지는 못하고 있습니다. 이러한 부분은 PHP에서 향후 공식적으로 gzdecode 함수를 제공하여야 가능할 것으로 보입니다. 아니면 좀더 개선된 팁이 공개되든가......

'phpsource > 파일분석' 카테고리의 다른 글

{TAR 파일}8.클래스 다운로드  (0) 2002.09.16
{TAR 파일}7.클래스  (0) 2002.09.09
{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
{TAR 파일}4.본문 구조  (0) 2002.09.09
{TAR 파일}3.헤더 구조  (1) 2002.09.09
Posted by 방글24