(출처 : http://www.buggymind.com/366 )

소프트웨어 개발 방법론 중 가장 널리 쓰이고 있는 것은, 아마 아직도 폭포수(waterfall) 방법론일 것 같습니다. 요구사항 분석 - 설계 - 개발 - 검증으로 이어지는 이 단순한 방법론은 그 단순성과 명료함 때문에 '그다지 심각한 고민 없이도' 현업에 도입되어 쓰이고 있습니다. 그런데 폭포수 방법론에는 대관절 무슨 문제점이 있길래 그토록 많은 비난의 대상이 되고 있는 걸까요?

이미 많은 증거들이 있어서 사실 제가 또 언급할 필요까지는 없는건데, 집으로 돌아오는 비행기 안에서 이런 저런 생각하다보니 이런 결론에 이르게 되더군요. '단순성'

폭포수 방법론은 사실 프로젝트 진행중에 벌어지는 다양한 상황을 처리하기에는 좀 지나치게 단순합니다. 일단 요구사항 분석이 끝났다고 치죠. 그러면 설계 단계가 진행되는데, 이 와중에 새로운 요구사항이 등장한다면? 제품을 개발하는 사람들이 어떻게 대응할 것이냐와는 별개로, 방법론 자체는 그런 상황을 처리하기에 그다지 걸맞지 않습니다. 사람들이 유연하게 대처하면 괜찮습니다만, 사실 그런 지경에 이르면 '방법론'이라고 부르기 껄끄러워지죠. 지키지 않는 방법론을 과연 방법론이라고 부를 수 있을까요?

사실 폭포수 방법론은 그 단순성을 커버하기 위해 굉장히 많은 문서들을 요구합니다. (아마 해 보신분들은 아실 듯.) 가능한한 모든 시나리오를 문서에 적어두고, 그 틀을 벗어나는 상황이 벌어지지 않기를 기대하죠. 유스케이스 문서에 장황하게 적혀있는 개발 시나리오는 그 중 한 예입니다. 하지만 예외 상황(exceptional case)이 한 가지만 새로 생기더라도, 유스케이스 문서는 고쳐져야 합니다. 유스케이스 문서의 양이 너무 많아서, 대체 어디를 고쳤는지 추적하기가 좀 난감하다는 점도 문제죠.

폭포수 방법론의 대척점에 서 있는 개발 방법론들은, 그래서 가능하면 프로젝트 개발의 각 단계를 '제어 가능한' 작은 단계들로 쪼개려고 합니다. 스프린트(sprint) 같은 것은 그 좋은 예로, 한두주 단위로 쪼개진 기간 안에 설계-개발-검증을 완료하고 또 그 다음 구간에 설계-개발-검증을 반복합니다.

각각의 구간이 굉장히 짧기 때문에, 그 구간이 진행되는 만큼은 불확실성(uncertainty)을 적절히 통제할 수 있습니다. 그 구간이 끝나야만 새롭게 등장한 요구사항들을 검토할 수 있죠. (애자일 개발 방법론도 그 중 한가지입니다.)

그런데 단순히 하나의 방법론에서 다른 방법론으로 이행한다고 해서 크게 나아지지 않는 것이 있습니다. 그건 프로젝트에 참여하는 사람 사이에 발생하는 역학관계죠. 그런 역학관계때문에 발생하는 문제를 해결하려면, 누군가는 프로젝트에 참여하는 사람에게 긍정적인 영향을 끼칠 수 있도록 수직적 관리방식에 영향력을 행사하거나, 아니면 팀원들간의 소통방식을 개선해야 합니다.

이 문제는 사실 개발 방법론의 한 부분일수도 있고 아닐 수도 있습니다만, 적어도 프로젝트의 성공을 위해서는 반드시 고려해야 하는 부분입니다. 방법론이 달라진다고 해서 프로젝트에 대한 압박이 사라지지는 않겠습니다만, 그런 스트레스에 대응하는 내적 능력은 달라질 수 있습니다. 프로젝트를 수행하는 데 필요한 방법론을 개선하는 데 있어서 가장 크게 고려해야 하는 부분은 그런 내적 능력을 증진시켜 팀원 모두가 적절한 수준의 항상성을 유지할 수 있도록 만드는 것이 되어야 할 겁니다.

보통 스트레스가 적절한 수준 이상으로 늘어나면 그런 항상성을 유지하는 것이 불가능하기 때문에, 결국 프로젝트를 성공으로 이끄는 것은 (적절한 능력을 가진 팀원들이 모여있다는 가정 하에서) 결국 스트레스를 어떻게 관리할 것이냐 하는 부분으로 귀결되는 일이 많죠. )


스트레스를 관리하는 방식은 여러가지가 있겠습니다만, 최근까지 등장한 방법들은 대략

1. 업무 시간이 일정 시간 이상이 되지 않도록 하여 팀원들이 휴식할 수 있도록 하는 방법
2. 팀원들에게 프로젝트 결과후 성과에 대한 유무형의 보상을 제시하여 감내하도록 하는 방법
3. 팀원들의 의사소통 방식을 개선하여 업무와 관련한 스트레스를 줄이는 방법
4. 프로젝트 수행에 관계된 수직적 관리 오버헤드와 태스크 스위칭을 줄이는 방법
5. 프로젝트 진도와 성과를 정량적으로 추정할 수 있도록 하여 보고 오버헤드를 줄이는 방법

등등이 있겠습니다. 이 중 5는 4와 관련이 있고, 3은 1과 관련이 있습니다. 1이 되도록 하면 가장 좋겠지만, 프로젝트 말미에는 불가능한 경우가 많기 때문에 2가 반드시 있어야 합니다. 2를 흔히 우리는 비전(vision)이라고 부르는데, 비전 없는 프로젝트가 팀원의 이직을 초래하는 경우가 많기 때문에 주의해야 합니다.

비전을 제시할 때 주의해야 할 것은, 비전에 대한 착시효과입니다. 팀원들은 비전이 없다고 생각하는데, 관리자는 비전이 있다고 생각하는 경우가 그 한 예입니다. 관리자가 보는 비전과, 팀원들이 생각하는 비전은 굉장히 많이 차이가 날 수 있습니다. 따라서 2는 3과도 관련이 있습니다. 비전이 하나로 수렴되려면, 관리자와 팀원 간의 의사소통 방식이 개선될 필요가 있습니다. 비전은 이야기하지 않으면 알 수 없는 부분 중 하나이기 때문에, 관리자와 팀원은 서로를 설득하거나 비전에 대한 간격을 줄이기 위해 애쓸 필요가 있습니다.

비전을 제시하는 가장 좋은 방법은, '무엇이 어떻게 나아질 것인지'에 대한 정량화된 지표를 제시하는 것입니다. 아쉽게도, 사람들은 '심증'이라도 없으면 아무것도 믿지 않습니다. 프로젝트가 종료된 후 팀원들이 떠나는 것은, 아무도 그 부분을 어떻게 제시할 것인지 고민하지 않기 때문이기도 합니다.

그래서 떄로 프로젝트를 관리하는 것은 단순히 야근을 하지 않는 회사를 만드는 것 그 이상입니다. 성공적인 프로젝트 개발 방법론을 만들고 싶으신가요? 어쩌면 정말로 중요한 것은 그 너머 어딘가에 있을지 모릅니다. 방법론이 잘못되어 프로젝트가 실패하는 것이 아닌지 의심하고 계시다면, 여러분의 프로젝트가 팀원들에게 어떤 비전을 제시하고 있는지 자문해 보세요.

세상에는 비전 하나만으로 야근을 견뎌낼 사람들이, 아직은 많으니까요.

 

(출처 : http://www.zdnet.co.kr/news/news_view.asp?artice_id=20091129180815&type=det)


체계화된 프로세스와 산출물들로 무장한 개발방법론은 회사에 필요한 이상적인 무기를 제공해줄 것 같지만, 개발방법론을 도입해 크게 효과를 본 회사를 찾기는 쉽지 않다. 개발방법론이 개발을 더 지연시키고 개발자들을 번거롭고 힘들게 한다고 하기도 하고 개발방법론을 도입해서 사용하다가 포기하고 다른 방법들을 기웃거리기도 한다. 왜 이렇게 성공적으로 개발방법론을 도입하는 것이 어렵고, 개발방법론을 효과적으로 소프트웨어 개발에 적용하기 위해서는 어떻게 해야 하는지 알아보자.

독자들 중에서도 개발방법론들을 경험해 본 사람들이 꽤 있을 것이다. 실제로 개발방법론을 경험해 봤다면 그 개발방법론이 실제 소프트웨어를 개발하는 데 얼마나 도움이 되었는지 묻고 싶다. 즉, 이전에 나름대로의 방법으로 알아서 개발하던 때와 비교하면 얼마나 나아졌는지 묻고 싶다. 진짜 개발이 더 빨라지고 생산성이 높아졌는지? 아니면 개발은 오히려 느려졌고 과거보다 번거로울 뿐이지만 그래도 문서를 남겨야 나중에 정보 공유가 가능하니까 따르는 것인지 묻고 싶다.

필자는 소프트웨어 개발 컨설턴트로서 여러 개발자들이 이러한 질문에 답변하는 내용을 들을 기회가 많다. 그 중에 개발방법론은 고객이 요구하기 때문에 어쩔 수 없이 적용한 경우가 많았고, 실제로 개발하는 데는 필요도 없는 문서를 많이 만들어야 했으며, 그로 인해 개발에 더 많은 시간이 소요되었다는 얘기를 종종 듣게 된다. 하지만 회사에서 시키기 때문에 억지로 하곤 한다고 말한다. 시중에 개발방법론은 넘쳐나는데 왜 개발방법론을 적용해 큰 효과를 봤고 개발 생산성이 크게 향상되었던 경험을 접하기가 어려운 것일까?

■개발방법론은 필요하다

회사가 작을 때는 소프트웨어를 개발하는 데 있어서 대부분 확실한 개발 체계 없이 시작한다. 대부분의 경우 이렇게 주먹구구식으로 또는 가내수공업 형태로 소프트웨어 개발을 시작해도 별 문제가 없다. 체계가 없다는 것은 소프트웨어를 개발하는 데 문서를 제대로 만들지도 않고, 정형화된 프로세스 없이 개발자들의 경험에 의해 주먹구구식의 절차를 통해 별도의 개발 시스템 없이 순전히 개발자들의 기억력과 약간의 기록만 가지고 개발하는 것을 의미한다.

그렇게 개발하더라도 대부분 큰 문제에 봉착하지 않는다. 대부분의 정보라는 것도 그리 방대하지도 않아서 개발자들의 머릿속에 잘 저장되어 있고, 시스템도 그리 복잡하지 않아서 몇몇 소수의 개발자들이 머리를 맞대고 개발해도 별 문제가 없다. 또 충성심 가득한 개발자들은 회사에 언제까지나 있을 것 같고, 문제가 발생하면 특공대처럼 문제를 빠르게 해결한다.

이러한 시기에는 오히려 주먹구구 방식이 훨씬 빠르고 비용이 적게 든다고 생각할 수 있다. 실제로 이런 개발 방법이 여타 개발방법론을 적용한 개발 방법보다 효율이 더 높은 경우도 있다. 소수의 개발자에게 너무 많은 부분을 의존하고 있는 이런 방식은 장점인 것처럼 보이지만, 사실은 대단히 큰 위협요소가 된다.

성장하는 회사는 조직이나 소프트웨어의 규모가 점점 커지고, 개발해야 하는 제품의 수와 개발자는 점점 늘어가고, 더 이상 주먹구구식으로는 개발이 어려워진다. 회사는 점점 성장하는데 여전히 주먹구구식으로 개발하고 있다면 개발 과정은 점점 혼란스러워지고 설상가상으로 대부분의 정보를 머릿속에 담고 있는 개발자가 퇴사를 하기도 한다.

개발방법론은 이렇게 소수의 개발자에 편중되어 있는 대부분의 리스크를 시스템적으로 커버할 수 있도록 한다. 문서도 만들어야 하고, 프로세스도 따라야 하기 때문에 당장에는 기존의 주먹구구식의 방식보다는 시간도 많이 들어가고 비용도 많이 들어가는 것처럼 보이지만, 그 대가로 리스크를 줄일 수 있다.

모험심이 가득한 벤처 회사라면 얼마든지 리스크를 감수할 수 있겠지만, 회사가 점점 커지면 리스크보다는 비용을 선택하게 되어 있다. 따라서 주먹구구식으로 시작한 소프트웨어 회사라도 규모가 커지면 자연스럽게 개발방법론에 눈을 돌리게 된다.

이렇게 개발방법론을 시도해보기 위해 개발방법론 도입을 도와주는 컨설팅회사에 의뢰를 하기도 하지만, 대부분은 인터넷이나 책을 통해 개발방법론을 배워보려고 시도한다.

■개발방법론을 공짜로 배울 수 있을까?

개발자들은 인터넷에서 수많은 소스 코드 샘플을 보고 개발에 활용해 왔듯이, 개발방법론도 인터넷에서 특정 개발방법론의 템플릿과 샘플 그리고 프로세스를 가져와서 따라하면 개발방법론을 그럴싸하게 흉내 낼 수 있을 것으로 생각하기도 한다.

하지만 실제로 따라해보면 생각만큼 잘 되지 않는 것이 사실이다. 일단 기존에 주먹구구식으로 개발하던 개발자들은 개발방법론에서 제시하는 템플릿을 보게 되면 생전 처음 보는 내용도 많을 뿐더러 왜 그러한 것이 필요한지 진짜 의미를 이해하기 어렵고, 어떻게 작성해야 하는 것인지 파악이 잘 안 되는 것이 일반적이다. 그리고 이것이 정말로 자신의 회사에서 필요한 것인지 또는 필요 없는 것인지 판단이 안 되기도 한다.

그래서 일단 이것저것 시도를 해보고 효과가 신통치 않으면 나중에 “그거 해봤는데 별로더라”라는 자신만의 편협한 평가를 내리기도 한다. 이러한 서투른 시도는 개발방법론에 대한 나쁜 인식만 키워주기 때문에 아니 한 만 못하다.

여러 개발방법론에서 제시한 문서들이 작성하기 부담스럽다고 문서를 적게 작성해도 된다는 XP, 애자일(Agile) 등에 쉽게 눈을 돌리곤 하는데, 이 또한 너무 쉽게 접근해 실패하는 경우도 많다. XP 방법론이 모든 종류의 소프트웨어를 커버하는 것은 아니지만, 나름대로 적절하게 쓰이면 훌륭한 개발방법론인 것은 사실이다. 하지만, 왠지 간편해 보인다고 만만하게 접근하다간 큰 코 다칠 수 있다.

소프트웨어를 개발하는 데 있어서 가장 어려운 것 중에 하나가 무엇을 만드는지 결정하는 일이다. XP 방법론에서는 이러한 스펙 작성의 어려움을 덜고자 다른 접근을 하는데, 이것이 마치 스펙을 작성하지 않아도 되고, 문서를 적게 만들어도 되기 때문에 개발자들에게는 최고의 개발방법론인 것처럼 생각할 수도 있지만, 그리 만만한 것은 아니다. 스펙 대신 테스트를 이용하고 있지만, 이 또한 공짜로 되는 것은 아니다. 기존에 이미 분석 능력을 가지고 있고, 유닛 테스트(Unit test)에 능통한 경우라면 무리 없이 받아들일 수 있지만, 주먹구구 방식에 익숙한 경우라면 이 또한 어려운 도전이 될 수 있다.

즉, 그냥 쉽게 배우고 프로세스, 템플릿을 좀 익혀서 개발방법론을 제대로 적용해 보기는 어렵다. 공짜로 배워보기에는 개발방법론은 그리 만만하지 않다.

■몸에 맞지 않은 개발방법론이 문제

그렇다고 컨설팅을 통해 개발방법론을 도입하는 경우도 그렇게 쉬운 것은 아니다. 여기에는 몇 가지 함정들이 도사리고 있다. 자칫하면 이론에 치우치기 쉽고 회사의 역량이나 규모에 걸맞지 않은 무거운 개발방법론을 도입하게 되기도 한다. 개발방법론을 도입하려는 회사는 어떤 개발방법론이 자신의 회사에 알맞은지 직접 판단하기 어려우므로 외부의 전문가의 판단에 의존하는데 외부의 전문가가 실전 경험이 부족한 경우 회사의 특징과 역량 수준을 고려하지 않고 거대 개발방법론을 기계적으로 도입할 수 있다.

이 경우 큰 Learning Curve를 겪게 되고 결국 이를 극복하지 못하고 실패할 가능성이 높다. 따라서 자신의 회사에 알맞은 수준의 개발방법론을 선택해야 하는데, 이렇게 몸에 딱 맞는 개발방법론을 선택하는 것도 쉬운 일은 아니다.

또, 개발방법론을 하나 정해 놓고 회사의 모든 프로젝트에서 그 개발방법론을 무조건 따르게 하는 것도 문제다. 모든 프로젝트는 그 성격이 다른데, 하나의 개발방법론을 무조건 따르게 되면 간단한 프로젝트에서도 과도한 비용을 지불해야 한다. 이는 개발방법론이 자칫 관료화되는 것을 조심해야 한다는 뜻이다. 애초에 개발방법론을 도입한 이유를 망각하고 관리자나 프로세스 부서에서는 무조건적인 강요로 효율성을 떨어뜨리는데, 애초에 개발방법론을 도입할 때 유연하게 적용을 할 수 있는 여지를 남겨 둬야 할 것이다.

■방법론의 목적은 효과적인 개발

소프트웨어 개발방법론의 근본 목적은 소프트웨어를 빠른 시간 안에 적은 비용을 들여 요구되는 품질의 소프트웨어를 만들어내는 것이다. 이런 과정에서 개발자들이 혹사되어서는 안 되며 개발자들은 자연스럽게 소프트웨어 전문가로서의 능력이 향상되어야 한다. 즉 프로젝트도 성공하고 개발자에게도 도움이 되어야 진정한 방법론인 것이다.

그렇지 않고 단순히 절차를 지키기 위한 방법론, 개발자는 희생하면서 프로젝트만 어떻게든 성공하기 위한 방법론은 반쪽짜리일 뿐이다. 그럼에 불구하고 개발방법론은 왠지 무겁고 형식적이고 소프트웨어를 개발하는 데 진짜 도움은 되지 않는다는 생각들은 개발방법론 시도 실패에 대한 반작용으로 생겨난 경험담들 때문이다.

■국내 현실은 도 아니면 모

국내 대부분의 소프트웨어 회사는 소프트웨어를 개발하는 방법에 있어서 아래 세 가지의 부류로 나눌 수 있다.

첫째, 주먹구구식으로 소프트웨어를 개발하는 회사. 특별한 프로세스 없이 개발자들의 경험에 의존해 자체적으로 약간의 문서를 만들면서 소프트웨어를 개발하고 있는 회사. 주로 작은 회사들이며 개발자가 100명 이상인 중견 기업들도 상당히 많은 회사들이 이 단계에 머물러 있다.

둘째, 거대 방법론을 도입해서 흉내 내는 회사. 이 경우도 상당수가 내부적으로는 주먹구구이나 형식적으로는 방법론을 따라하고 있다. 주로 대기업에 해당하며 이들 기업은 개발 효율성보다 리스크 감소에 더 관심이 많으며 개발자들보다 회사의 힘이 압도적으로 크므로 추진력 강하게 이러한 개발방법론을 도입할 수 있고, 이러한 무리한 도입 과정에서 벌어지는 비효율성은 개발자들이 요령껏 편법을 이용해 피해가는 경우가 많다. 즉, 내용보다는 형식에 치우친 경우라고 할 수 있다. 이 경우 리스크는 줄어드나 개발 효율성도 따라서 줄어들어 일정 수준 이상을 넘을 수가 없다.

셋째, 거대 방법론이 회사에 맞지 않음을 깨닫고, 다시 주먹구구 개발방법으로 되돌아 온 회사. 그러면서 다른 방법이 없을까 고민하고 있는 회사들이다. 이런 실패의 경험이 반복될수록 내부에 불신이 쌓여가므로 쉽게 새로운 시도를 못하고 주먹구구와 개발방법론 사이를 떠도는 경우이다.

물론 이 세 부류에 속하지 않은 회사들도 있다. 그런 회사들은 스스로를 잘 알고 있으므로 별도로 언급할 필요가 없을 것이다. 그리고 그런 회사는 그리 많지 않다. 첫째와 셋째는 ‘도’에 해당하고 둘째는 ‘모’에 해당하는 경우이다. ‘도’도 바람직하지 않고 ‘모’도 소프트웨어를 개발하는 데 비효율적이다. 가장 좋은 경우는 ‘개’나 ‘걸’처럼 회사의 규모와 개발자들의 역량이 같이 성장해 나가면서 그 단계에서 딱 필요한 것들을 차근차근 하나씩 도입해 나가면서 내재화시켜 나가는 것이다.

■뭐든지 단계가 있는 법

뭐든지 배우려면 그 단계가 있고, 차근차근 배우고 익혀나가야 한다. 예를 들어서 골프를 배우고 싶다면 어떻게 될까? 소프트웨어를 취미로 개발하고 있는 것은 아니므로 골프로 프로 선수가 되는 것을 목표로 삼는 경우를 예로 들어보자.

골프를 처음 배워나가면서 타이거 우즈가 공을 치는 방법이 가장 완벽하다고 해서 그 방법을 그대로 따라하기란 불가능하다. 타이거 우즈가 그렇게 공을 치기까지는 십 수 년의 훈련이 필요했고, 타이거 우즈에 가장 알맞은 방법으로 진화해 온 것이다.

그런데 타이거 우즈가 그 방법으로 세계에서 가장 골프를 잘 치는 사람이 되었다고 그것을 그대로 흉내 내는 것은 어리석은 짓이다. 사실 그대로 흉내 내는 것 자체도 불가능하다. 타이거 우즈와 똑같이 치는 방법을 책을 쓰면 책 한 권은 넘을 것이다.

하지만 타이거 우즈는 그 방법을 일일이 생각하면서 공을 치지 않는다. 그 방법이 몸에 익었을 뿐이다. 그냥 공을 치면 저절로 되는 것이다. 이를 ‘내재화’가 되었다고 한다. 그 최고의 방법을 모델로 놓고 그대로 따라하고 훈련한다고 해서 그 방법을 익힐 수 있는 것은 아니다. 그러한 단계로 가기 위해서는 기초부터 배워나가는 방법이 따로 있을 것이다. 또 우리 몸에 맞는 모델은 타이거 우즈의 방법이 아닐 수도 있다. 그런데 최고의 방법이 타이거 우즈의 방법이라고 따라하는 것은 무리한 시도이며 대부분 포기하게 될 것이다.

진짜 프로골퍼를 목표로 하고 골프를 배우고 있다면 타이거 우즈가 골프를 치는 것을 그대로 따라하는 것이 좋은 방법이 아님을 누구나 알 수 있을 것이다. 재미로 마구 골프를 쳐보다가는 평생 프로선수가 되지 못할 것이다. 누구나 상식적으로 생각해도 아주 기초부터 차근차근 훈련을 받아나가야 한다는 것을 알 수 있을 것이다.

그런데 소프트웨어 세상에서는 이런 섣부른 시도들이 종종 발생한다. 개발자들의 역량은 아직 기초 수준인데 세계 최고의 방법론들을 도입해서 시도하면 개발자들도 저절로 세계 최고의 역량을 갖출 수 있을 것으로 착각하는 것 같다.

■개발방법론이 가르쳐주지 않는 것

개발방법론은 소프트웨어 회사라면 당연히 갖추고 있어야 하는 것은 가르쳐주지 않는다. 즉, 소스 코드를 어떻게 관리하고, 버그는 어떻게 추적할 것이며, 빌드/릴리즈는 어떻게 할지는 크게 상관하지 않는다.

하지만, 이러한 것들이 아직 체계적으로 갖춰지지 않는 회사가 개발방법론을 도입한다고 하면 따라가기만 하는 것도 벅차고 성공적으로 내재화되기는 어려울 것이다. 축구팀이 기초 체력은 갖추지도 못하고 기본적인 드리블이나 슛 실력이 부족한 상태에서, 다양한 전술과 전략을 익혀봤자 말짱 허사일 것이다. 여기서 말하는 기초 역량은 개발자에게 있어서 설계, 코딩 능력을 말하는 것은 아니다.

우리나라 개발자들의 코딩 능력은 전 세계 어디 내놔도 손색이 없을 만큼 뛰어나다. 여기서 말하는 기초 역량은 소프트웨어 회사라만 기본적으로 갖춰야 할 요소들과 설계, 코딩을 제외한 소프트웨어 전문영역의 다양한 지식들을 말한다. 이러한 것들은 워낙 당연한 것들이기 때문에 개발방법론을 만든 사람들은 소프트웨어 회사라만 당연히 보유하고 있어야 하는 것으로 생각한다.

방법론에서는 그러한 것들은 너무나 당연한 것이라 어떤 방법을 사용하든 별 개의치 않는 경우가 많기 때문에, 그러한 기초조차 제대로 갖추고 있지 않은 소프트웨어 회사라면 현재의 수준을 자각하지 못하고 자칫 그럴듯하게 포장된 방법론만 눈에 들어올지도 모른다. 이런 경우 방법론은 공염불이 되기 십상이다. 방법론을 고민하기보다는 기초부터 다져야 하는 경우이다.

■개발자들의 역량

기초란 회사에만 적용되는 것은 아니다. 개발자들도 개발방법론을 따라 개발하기 위해서는 필요한 역량이 있다. 가장 먼저 방법론 하면 산출물이 떠오르는데 대부분의 개발자들은 문서를 작성하는 데 익숙하지도 않고 그보다 먼저 문서 작성을 싫어한다. 이러한 상황에서 템플릿만 잔뜩 제공하고 이를 만들어내라고 하면 보통 괴로운 일이 아니다.

그럼 이쯤에서 의문이 생긴다. 과연 개발자가 문서를 잘 작성한다는 것은 무엇을 말하는 것인가? 개발자들 스스로도 본인이 문서를 잘 작성하고 또 잘 작성할 능력이 있는지 알지 못하는 경우도 많다. 개발자들의 문서 작성 능력을 한번에 알아내기는 어렵지만, 아래와 같은 질문을 해보고 싶다.

소프트웨어를 개발하면서 문서를 만드는 이유가 무엇이라고 생각하는가?

1. 고객이 원해서
2. 나중에 유지보수를 위해서
3. 개발 시간과 비용을 단축하려고

이 중에서 1이나 2라고 답하는 사람들은 아직 문서를 제대로 작성할 능력이 낮을 가능성이 높다. 그 동안 문서를 형식적으로 작성해 왔거나, 문서 작성을 거의 하지 않고 개발을 해오면서 문서는 거추장스러운 것이라고 생각하고 있는 경우가 많을 것이다.

이런 상태라면 개발방법론은 정말 거추장스러운 방해밖에 될 수 없다. 3번이라고 자신 있게 답할 수 있는 사람들은 개발하면서 문서들도 진정 필요한 시점에서 필요한 내용으로 작성했을 것이고, 그렇게 오랜 시간 훈련이 되어 필요한 문서 작성에 능숙할 것이다. 하지만 이렇게 3번이라고 자신 있게 답할 수 있는 개발자들이 많지 않은 것이 현실이다.

방법론에서 만들어내는 수많은 문서들은 문서 자체가 목적이 아니다. 모든 문서들은 다음 작업을 진행하는 데 필요하기 때문에 만드는 것이다. 따라서 다른 개발자들이 내가 만들어 놓은 문서들을 보고 그 다음 작업을 진행할 수 있어야 한다.

즉, 내가 작성한 스펙문서를 보고 설계를 담당한 개발자는 설계를 할 수 있어야 한다. 또 테스트팀은 테스트 계획과 테스트 케이스를 만들어낼 수 있어야 한다. 그리고 기술문서팀(Techpub)에서는 스펙문서만 보고도 매뉴얼을 작성할 수 있어야 한다. 또한 빌드/릴리즈팀에서는 빌드 준비를 할 수 있어야 한다. 하지만, 분석 역량이 부족한 개발자에게 템플릿만 제공해 스펙문서를 만들어 낸들 제대로 설계가 가능하고 테스트 케이스를 만들어 낼 수 없다.

그리고 방법론을 도입하고 약간의 교육으로 그런 수준까지 역량을 끌어올리기는 어렵다. 오히려 거대한 방법은 역량을 차근차근 끌어올리기에는 거추장스러운 옷처럼 방해 요소가 될 수 있다. 차라리 방법론 전체보다는 각 회사에 필요한 기초적인 부분을 추출해 조금씩 적용하는 것이 좋을 것이다. 그러한 과정을 거치면서 개발자들의 역량도 같이 키워나가야 한다.

여기서 필요한 것은 분석, 설계, 프로세스, 형상관리, 테스트 등 개발에 필요한 다양한 것들이다. 이러한 지식과 경험은 하루 아침에 배운다고 익힐 수 있는 것이 아니고, 회사에서 일하면서 조금씩 쌓아 나가는 것들이다. 또한 개발자 혼자서 스스로 익힐 수 있는 것도 아니고, 회사와 같이 개발 업무를 해나가면서 계속 배우고 익혀나가야 하는 것들이다.

■잘못 사용되는 개발방법론

개발방법론을 사용하는 이유가 고객이 해당 개발방법론을 적용하기를 원해서인 경우가 종종 있다. 이러한 경우 고객들도 목적이 개발방법론은 아니지만, 소프트웨어 개발에 대한 전문지식이 모자라므로 회사의 규정에 의해서든 여러 연유로 인해 개발방법론 적용을 요구하게 된다. 이 과정에서 개발방법론을 효과적으로 추려내서 적용하지 못하고 전체를 그대로 적용해 달라고 요청하는 일이 발생한다.

고객은 개발방법론 교과서에 나온 대로 기계적으로 산출물과 프로세스를 요구하고 소프트웨어 개발사는 비효율적인 것을 알아도 고객이 원하므로 울며 겨자 먹기 식으로 무조건 따라야 하는 경우가 많다. 하지만 우리나라 개발자들이 어떤 개발자인가. 모든 난관은 헤쳐 나가는 방법이 있다. 방법론에서 요구하는 문서는 어쨌든 만들어내고 있다.

다양한 편법을 통해 문서를 만들어 내고 있고, 대부분의 경우 문서들이 실제 소프트웨어를 개발하는 데 도움이 되지 않더라도 고객이 요구하는 문서는 충족하고 있다. 이렇다 보니 문서 작업은 소프트웨어를 개발하는 데 도움이 되기는커녕 시간만 축내는 낭비요소가 되곤 한다. 하지만 고객의 요구사항이기 때문에 따르는 수밖에 없다.

그 결과, 이렇게 만들어 낸 산출물은 고객에게도 실제로는 아무런 쓸모없이 책꽂이만 차지하는 경우가 허다하고 개발자들은 방법론에 대한 부정적인 생각만 키워나가게 된다. 이렇게 잔뜩 만들어낸 산출물은 유지보수 시 매우 유용하게 사용될 것으로 홍보하지만, 막상 유지보수 때는 개발에 참여했던 개발자를 찾게 되고 문서보다도 소스 코드를 가지고 유지보수를 하게 된다. 이런 것들이 반복되면 개발자들은 개발방법론이란 형식적이고 실제 소프트웨어를 개발하는 데는 별 도움이 안 된다고 생각하게 되고 진짜 제대로 된 방법을 더욱 더 배우기 어렵게 만든다.

■고객의 무리한 개발방법론 적용 요구

개발 회사는 아무리 개발방법론을 효과적으로 적용하려고 해도 이렇게 고객이 기계적으로 또는 규정에 의해 무리하게 개발방법론을 요구하는 경우에는 어쩔 도리가 없다. 실제로 고객이 개발방법론을 콕 찍어서 **CBD 또는**OOP 방법론을 요구하기도 하는데, 고객을 잘못 만나면 30~40종류 이상의 산출물을 에누리 없이 만들어 내야 하는 경우도 있다. 또 마일스톤마다 산출물을 검사하기도 하기 때문에 프로젝트가 끝나고 밤샘해서 산출물을 만들어 낼 수도 없는 노릇이다.

이러한 경우에는 진짜로 소프트웨어를 잘 개발하기 위해 필요한 문서와 고객의 요구 때문에 어쩔 수 없이 만들어야 하는 문서를 구별할 필요가 있다. 사실 웬만한 규모의 소프트웨어까지는 주요 문서 2, 3개로 충분히 프로젝트를 진행할 수 있고, 그 외의 문서들은 가능하면 최소한의 노력으로 고객의 요구를 만족시켜주는 수준으로만 만들어주는 것이 가장 효율적일 것이다.

이러한 상황에서 진짜 개발에 필요한 문서와 고객의 요구 때문에 어쩔 수 없이 만드는 문서의 구별이 없다면 자칫 모든 문서가 형식적으로 작성될 수도 있다. 이 과정에서 개발자들은 모든 문서에 대한 거부감만 커지고, 방법론을 제대로 적용한 것 같지만 실제 개발은 주먹구구와 다름없게 될 수도 있다. 아니 오히려 주먹구구에다가 문서를 잔뜩 만들어야 하므로 주먹구구만도 못한 경우가 될 수도 있다.

■방법이 목적인 개발방법론

이쯤 되면 개발방법론이 진짜 필요한 것인지 오히려 개발을 방해하는 것인지 헷갈리기도 한다. 하지만 서두에서 말했다시피 개발방법론의 목적은 소프트웨어를 적은 비용으로 짧은 시간에 효과적으로 개발하는 데 있다. 하지만 개발방법론을 만든 사람들의 진짜 목적은 돈을 버는 것이다. 방법론을 팔아서 돈을 버는 회사들은 자신들의 개발방법론을 비싸게 많이 팔아야 한다. 그리고 누구나 쉽게 흉내 낼 수 없게 만들어야 한다.

그래서 자신들의 개발방법론을 다른 방법론들과 차별화하기 위해 노력하고 점점 복잡하게 만들게 된다. 그래야 아무나 따라할 수 없게 되고 또 더욱 비싼 값에 팔 수 있다. 이러다 보니 소프트웨어 업계에는 소프트웨어를 개발하는 수많은 개발방법론들이 넘쳐나고 점점 복잡해지고 있다. 그 반작용으로 간단하다고 어필하고 있는 개발방법론이 출현하기도 한다.

이렇게 되니 대부분의 개발방법론 자체가 잘못된 것은 아닐지라도 우리 회사에 알맞은 개발방법론을 찾기란 쉬운 일이 아니게 돼 버렸다. 오히려 잘못된 함정에 빠지기 쉬운 상황이 된 셈이다.

특히 이전에 어느 정도 경험과 기초가 되어 있는 회사들은 개발방법론을 바라볼 때 어느 정도의 판단 능력을 가지고 자신의 회사에 필요한지 그렇지 않은지 판단할 수 있겠지만, 주먹구구에서 시작한 대부분의 소프트웨어 회사들은 그저 혼란스럽기만 할 것이다.

■어떻게 해야 하나?

필자의 경험에 의하면 국내의 많은 소프트웨어 회사들은 거대 개발방법론을 당장 도입하기에는 아직 적당한 상황이 아니다. 개발방법론을 거론하기 이전에 소프트웨어 회사라면 필수적으로 갖춰야 할 조직과 시스템을 먼저 갖추고 회사에 필수적인 프로세스를 만들어가면서 회사와 개발자 모두 필수 역량을 갖출 때쯤 그리고 회사가 좀 더 크고 복잡해지면 방법론을 생각해보는 것이 좋겠다.

또, ‘자전거’를 만드는 회사에서 ‘우주선’을 만드는 방법론을 사용해서는 안 된다. ‘자전거’ 정도의 소프트웨어를 만드는 수많은 국내 소프트웨어 회사들은 거대 개발방법론이 필요하지 않다. 고객이 요구해서 방법론을 꼭 적용해야 하는 경우가 아니고 자체적으로 소프트웨어를 잘 개발하는 것이 목적이라면, 회사에 알맞은 작고 가벼운 개발방법론이면 충분할 것이다.

럼 소프트웨어 회사가 갖춰야 할 필수 역량에는 무엇이 있는가? 가장 먼저 소스 코드 관리시스템, 버그 관리시스템, 빌드 자동화 등 기본적인 인프라스트럭처 시스템들은 갖춰야 한다. 물론 이것이 그렇게 쉬운 것은 아니다.

실제로 이들을 사용하는 많은 회사들이 기본적인 기능만 사용하고 있음에도, 전혀 이런 시스템들의 도움을 받지 않고 소프트웨어를 개발하고 있는 회사들보다는 훨씬 나은 형편이다. 이런 시스템들을 사용해 개발하다 보면 자연스레 그러한 시스템들에 묻어 있는 소프트웨어 개발 철학을 익히게 되고 기본적인 개발 프로세스도 배울 수 있게 된다.

또, 조직적인 측면으로는 소프트웨어 개발에 필수적인 전문 조직이 기본적으로 필요하다. 대부분의 소프트웨어 회사는 처음 시작하게 되면 개발자들이 전문성을 가리지 않고 온갖 일들을 다하게 된다. 개발도 하고 테스트도 하고 고객지원도 하고, 심지어는 영업을 하기도 한다.

하지만 회사의 규모가 커져 가는데 소수의 개발자들이 개발하던 방식과 똑같이 개발하고 있다면 효율성은 점점 떨어져 간다. 이럴 때는 꼭 필요한 부분부터 전문화된 팀으로 구분하고 전담자를 둬서 해당 분야의 전문성을 높이고 개발자는 개발에 집중할 수 있도록 해줘야 한다. 이러한 대표적인 분야는 테스트와 빌드/릴리즈다. 아직도 테스트를 전적으로 개발자들이 담당하고 있는 회사들이 많다.

개발자 10명만 있는 조직보다는 개발자 7명과 테스터 3명이 있는 조직이 더 효율적인 경우가 많다. 개발자들은 자신이 개발한 소프트웨어를 잘 테스트하지도 못하는데, 해당 소프트웨어의 스펙을 상세히 아는 사람이 개발자 밖에 없고 별도의 테스터를 뽑아도 개발자만큼 제품을 알아서 테스트하기 어렵다고 개발자에게 테스트를 계속 맡기는 것은 잘 하지도 못하는 일을 비싼 인건비를 주고 계속 맡기는 것과 같다.

테스트를 별도의 조직에 맡기는 것이 제품의 품질을 더 높여주고 비용 효율적이며 개발자는 개발에 더 집중할 수 있게 한다. 또 이와 더불어 빌드/릴리즈팀은 빌드/릴리즈 과정을 자동화하고 효율을 높임으로써 그 동안 보이지 않지만 많은 비용을 차지하던 것을 절약하면서도 개발을 더 원활하게 진행하도록 지원한다.

이런 회사의 기본 역량 확보와 더불어 개발자들은 문서를 작성하는 능력, 리뷰하는 능력, 분석 능력, 설계 능력 등 개발자들이 갖춰야 할 코딩 능력 외의 필수 능력들을 쌓아 나가야 한다. 이들은 학교에서 배울 수도 없고, 실무를 통해 오랜 시간에 걸쳐서 차근차근 쌓아 나가야 하는 것들이다.

이렇게 기본적인 조직, 프로세스, 시스템을 갖춰나가면 소프트웨어 회사가 내적으로나 외적으로 기본적인 역량을 갖추게 된다. 이쯤 되면 어떤 개발방법론을 접하더라도 이전보다는 조금 더 잘 이해할 수 있게 된다.

개발방법론을 성공적으로 도입하기 위해서는 소프트웨어 회사와 개발자들이 기초 역량을 갖추고 있어야 한다. 회사가 어느 정도 역량을 갖추고 판단력이 생기면 무작정 좋다고 하는 개발방법론을 도입하기보다는 회사의 수준에 알맞은 방법들을 취사선택해서 조금씩 받아들이는 방법을 택하게 될 것이다.

결국 개발방법론의 목적인 소프트웨어를 빠른 시간 내에 적은 비용으로 효율적으로 개발한다는 것에 좀 더 가까워질 수 있다.

mkfifo(const char *pathname, mode_t mode)

- 2개의 매개 변수가 필요하네.

- mkfifo(파이프사용할 파일명, 모드)

- 이걸로 FIFO 파일을 생성하면 이후로는 이파일을 가지고 파이프로 이동할 수 있다.

- 동일한 fd를 이용한다면 다른 프로세스에서도 메시지를 받을 수 있다.

- 주고 받는 양방향 불가.

 

수신하는 곳

#include 
#include 
#include 
#include 
#include 

#define  FIFO_FILE   "/tmp/fifo"
#define  BUFF_SIZE   1024

int main( void)
{
    int   counter = 0;
    int   fd;
    char  buff[BUFF_SIZE];

    if(mkfifo(FIFO_FILE, 0666) == -1)
    {
        perror( "mkfifo() failed\n");
        return -1;
    }

    if (( fd = open( FIFO_FILE, O_RDWR)) == -1)
    {
        perror( "open() failed\n");
        return -2;
    }
    printf("FD=%d\n", fd);

    while( 1 )
    {
        memset( buff, 0x00, BUFF_SIZE);
        read( fd, buff, BUFF_SIZE);
        printf( "%d: %s\n", counter++, buff);
    }
    close(fd);
    return 0;
}
/* The end of function */
송신하는 곳

#include 
#include 
#include 
#include 
#include 

#define  FIFO_FILE   "/tmp/fifo"

int main( void)
{
    int   fd;
    char *str   = "TEST FIFO IPC";

    if ( -1 == ( fd = open( FIFO_FILE, O_WRONLY)))
    {
        perror( "open() failed\n");
        return -1;
    }
    printf("FD=%d\n", fd);

    write(fd, str, strlen(str));
    close(fd);
    return 0;
}
/* The end of function */

수신쪽 결과 
$ ./recv 
FD=3
0: TEST FIFO IPC
1: TEST FIFO IPC
2: TEST FIFO IPC

송신쪽 결과
$ ./send 
FD=3
$ ./send 
FD=3
$ ./send 
FD=3

 

=============================================

open함수는 파일 열고 fd를 반환한다.

write함수는 바로 그 fd에다가 쓴다.

같은 시스템에서 같은 파일을 열면

동일한 fd를 가지게 되므로 위와 같이 쓸 수 있다.

=============================================

출처 http://forum.falinux.com/zbxe/?document_srl=420145

'Language > C' 카테고리의 다른 글

C FAQ (malloc 오류)  (0) 2012.07.12
C FAQ (포인터 선언 에러)  (0) 2012.07.12
mkfifo 함수 예제  (0) 2012.07.06
popen 함수 pclose 함수 예제  (0) 2012.07.06
pipe 함수 예제  (0) 2012.07.06
다차원 배열을 1차원 배열로 변경하고자 할 때  (0) 2011.08.11

popen()

- 명령어를 shell을 기동 시켜서 열고 pipe로 연결한다.

- 이를 위해서 내부적으로 fork(), pipe()를 사용한다.

- 실행 쉘인 /bin/sh에 -c 옵션을 사용하여 전달

 

pclose()

- popen으로 열린 파이프 핸들 사용을 종료한다.

 

 

 

#include 
#include 
#include 
#include 

int main()
{
    FILE *fp = NULL;
    char cmd[1024] = {0,};
    char buffer[1024];
    pid_t   ppid;
    pid_t   *pid;

    snprintf(cmd, sizeof(cmd), "pidof -x /usr/sbin/sshd");

    fp = popen(cmd, "r");
    if( fp==NULL) {
        return -1;
    }

    fgets(buffer, sizeof(buffer), fp) ;
    printf("%s\n", buffer);
    pclose(fp);
    return 0;
}
실행결과 화면
$ ./a.out 
5967

 

 

 

 

 

 

 

 

 

=============================================

 

그냥 pidof 명령을 실행해준다. 내부의 ssh데몬의 pid를 가져다가

뿌려주는 역할을 한다.

'Language > C' 카테고리의 다른 글

C FAQ (포인터 선언 에러)  (0) 2012.07.12
mkfifo 함수 예제  (0) 2012.07.06
popen 함수 pclose 함수 예제  (0) 2012.07.06
pipe 함수 예제  (0) 2012.07.06
다차원 배열을 1차원 배열로 변경하고자 할 때  (0) 2011.08.11
C언어 - 스트림(Stream)이란?  (0) 2011.08.11

pipe()

- 하나의 파이프 및 파이프에 대한 두 개의 파일 디스크립터가 생성

- 하나의 파이프를 프로세스들이 공유

#include "sys/types.h"
#include 
#include 
#include 
#include 

#define MAXLINE 4096 /* max line length */ 

/* err_sys("") --> return(1) */

int main(void)
{
    int n, fd[2];
    pid_t pid;
    char line[MAXLINE];

    if (pipe(fd) < 0) {
        printf("pipe error \n");
        return(-1);
        /* err_sys("pipe error"); */
    }

    if ( (pid = fork()) < 0) {
        printf("fork error \n");
        return(-2);
        /* err_sys("fork error"); */

    } else if (pid > 0) { /* parent */

        close(fd[0]);
        write(fd[1], "Hello world\n", 12);

    } else { /* child */
        close(fd[1]);
        n = read(fd[0], line, MAXLINE);
        write(STDOUT_FILENO, line, n);
    }

    return(0);
}
/* The end of function */

=============================================================

파이브열고

포크로 자식 프로세스 만들어다가

read시키는데

이떄, 부모프로세스는 write으로 파이프의 내용을 읽어온다.

결국 위의 코드의 결과는

printf("%s\n", "Hello world");

와 동일하게 나옴. write함수에서 fd들어갈곳에 STDOUT_FILENO플래그를

넣었으니깐.

=============================================================

pipe() 함수는 파일 디스크립터 쌍을 생성하네, 2개 생성하는데.

filedes[2] => filedes[0] Read, filedes[1] Write. 용도로 만든다.

사용법
#include <unistd.h>

int pipe(int filedes[2]);

=============================================================

fork()함수는 Child process 생성하는 기본적인 멀티 프로세싱 함수

사용법
#include <unistd.h>

pid_t fork(void);

=============================================================

close()함수는 pipe로 열린 descriptor 닫아버리는 함수

SYNOPSIS
#include <unistd.h>

int close(int fd);

=============================================================


출처

1. advanced programming in the unix environment

 2. http://gatolu.tistory.com/entry/%ED%8C%8C%EC%9D%B4%ED%94%84-%ED%95%A8%EC%88%98 

'Language > C' 카테고리의 다른 글

mkfifo 함수 예제  (0) 2012.07.06
popen 함수 pclose 함수 예제  (0) 2012.07.06
pipe 함수 예제  (0) 2012.07.06
다차원 배열을 1차원 배열로 변경하고자 할 때  (0) 2011.08.11
C언어 - 스트림(Stream)이란?  (0) 2011.08.11
리눅스 시스템 프로그래밍 8장 IPC  (0) 2011.08.11

2006.12.31 13:01:27 (*.138.143.127)

14819

54 / 0

이번 시간에는 시리얼 통신에서 자료를 수신하는 부분을 구현하려 합니다. 그러나 송신 보다 수신하는 부분은 생각할 점이 있습니다. 전송이야 이쪽에서 필요할 보내기만 하면 되기 때문에 "언제라는" 시간적인 문제가 없습니다. 그러나 수신은 자료가 언제 올지를 모르죠. 기다려야 한다는 인데, 자료가 때까지 마냥 시리얼 포트만 쳐다 보고 있을 없습니다. 다른 일도 처리 해야죠. 해야할 일이 산더미처럼 쌓였는데, 마냥 포트만 쳐다 없습니다

   

이럴 쉽게 생각할 있는 것이 일을 처리하는 중에 잠시잠시 포트를 확인하는 방법입니다. 가령 예를 들어서 아래와 같이 하는 것이죠.

while( 1)

{

  // 다른 업무를 실행

  if 0 < read( fd, buf, BUF_MAX_SIZE)

  {

    // 수신 자료를 처리

  }

}

물론 이와 같은 방법도 좋습니다만 ?자료 수신 이외의 이벤트 처리, 예로 통신에 에러가 발생하지 않았는지 등을 확인을 위해서는 다른 확인 루틴을 작성하고 if 절을 추가해야 합니다. 그러나 무엇보다도 read()함수가 block 버리면 루틴 자체가 block되어 버리는 매우 문제를 가지고 있습니다.

   

이럴 사용하는 것이 POLL입니다.

   

poll()

POLL 확인하고 싶은 여러 가지 사건( 이하 event) 미리 등록해 놓고 사건들이 발생했는지 확인할 있는 편리한 방법을 제공해 줍니다. POLL 이용한 작업 진행 과정을 정리해 보면,

  1. 체크하고 싶은 여러 event 등록
  2. poll() 함수를 호출하면
  3. event 발생하면 poll() 함수 호출 후에 바로 복귀하지만,
  4. 발생된 event 없으면 하나 이상이 발생할 까지 time-out 시간 만큼 대기하게 됩니다.
  5. event 발생면 해당 event 배열 아이템의 값이 변동이 되는데,
    변동을 확인하여 어떤 event 발생했는지를 있습니다.

장황한 설명 보다는 먼저 간단한 예를 보여 드리고 후에 자세한 설명을 드리도록 하겠습니다. 예제는 이해를 돕기 위해 상수를 사용하지 않았고, 함수로 분리하지 않았습니다.

예제

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <termios.h> // B115200, CS8 등 상수 정의
#include <fcntl.h> // O_RDWR , O_NOCTTY 등의 상수 정의

int main( void)
{
int fd;
int ndx;
int cnt;
char buf[1024];
struct termios newtio;
struct pollfd poll_events; // 체크할 event 정보를 갖는 struct
int poll_state;

// 시리얼 포트를 open

fd = open( "/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK ); // 디바이스를 open 한다.
if ( 0 > fd)
{
printf("open error\n");
return -1;
}

// 시리얼 포트 통신 환경 설정

memset( &newtio, 0, sizeof(newtio) );
newtio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;

tcflush (fd, TCIFLUSH );
tcsetattr(fd, TCSANOW, &newtio );
fcntl(fd, F_SETFL, FNDELAY);

// poll 사용을 위한 준비

poll_events.fd = fd;
poll_events.events = POLLIN | POLLERR; // 수신된 자료가 있는지, 에러가 있는지
poll_events.revents = 0;

// 자료 송수신

while ( 1)
{
poll_state = poll( // poll()을 호출하여 event 발생 여부 확인
(struct pollfd*)&poll_events, // event 등록 변수
1, // 체크할 pollfd 개수
1000 // time out 시간
);

if ( 0 < poll_state) // 발생한 event 가 있음
{
if ( poll_events.revents & POLLIN) // event 가 자료 수신?
{
cnt = read( fd, buf, 1024);
write( fd, buf, cnt);
printf( "data received - %d %s\n", cnt, buf);
}
if ( poll_events.revents & POLLERR) // event 가 에러?
{
printf( "통신 라인에 에러가 발생, 프로그램 종료");
break;
}
}
}
close( fd);
return 0;
}

  예제를 보시면 struct pollfd 사용했습니다. struct pollfd 내용을 보면 아래와 같습니다.

struct pollfd

{

  int fd;             // 대상 파일 디스크립터

  short events;   // 발생된 이벤트

  short revents;   // 돌려받은 이벤트

};

  1. fd 감시 대상인 디스크립터, 핸들이 되겠습니다.
  2. events 체크하고 싶은 event 모음입니다. 여기서 체크가 가능한 것은 아래와 같습니다.
  • #define POLLIN 0x0001 // 읽을 데이터가 있다.
  • #define POLLPRI 0x0002 // 긴급한 읽을 데이타가 있다.
  • #define POLLOUT 0x0004 // 쓰기가 봉쇄(block) 아니다.
  • #define POLLERR 0x0008 // 에러발생
  • #define POLLHUP 0x0010 // 연결이 끊겼음
  • #define POLLNVAL 0x0020 // 파일지시자가 열리지 않은 같은, Invalid request (잘못된 요청)
  1. revents event 발생 여부를 bit 별로 갖는 값입니다.

   

  , 이제 예제를 보겠습니다.

struct pollfd poll_events; // 체크할 event 정보를 갖는 struct

poll() 사용하기 위한 변수를 선언했습니다. poll_events 에는 감시 대상인 디스크립터와 어떤 event 감시할지 결정해서 bit 값으로 지정해 것입니다.

int poll_state;

poll() 수행한 결과값을 갖습니다. 값은 반드시 체크해야 하는데, 아래와 같은 반환값을 갖습니다.

   

poll() 수행 반환

  

반환

설명

음수

반환 값이 음수라면 치명적인 에러가 발생한 것입니다. 한번 이렇게 음수로 에러가 발생하면 이후 계속 음수값이 날라 옵니다. 거의 대부분 프로그램을 다시 실행해야 됩니다. 반드시 체크해야 겠지요.

0

지정한 대기시간, time-out 지나도록 발생한 event 없습니다.

양수

event 발생했습니다.

poll_events.fd = fd;

감시 대상인 디스크립터를 지정합니다.

poll_events.events = POLLIN | POLLERR; // 수신된 자료가 있는지, 에러가 있는지

체크하고 싶은 event 대해 비트값으로 설정하여 지정해 줍니다.

poll_events.revents = 0;

revents 0 으로 청소해 주고요.

poll_state = poll( // poll() 호출하여 event 발생 여부 확인
(struct pollfd*)&poll_events, // event
등록 변수
1, //
체크할 pollfd 개수
1000 // time out
시간
);

체크할 event 정보를 넘겨 줍니다. 1 체크할 pollfd 개수입니다. 예제를 가지고는 pollfd 개수가 필요한지 이해가 안되시죠. 예제에는 감시하는 디스크립터가 개이지만 프로그램에 따라서는 한번에 여러 개의 디스크립터를 관리할 경우가 많습니다.

   

관리할 디스크립터가 많을 , 각각을 변수로 처리하는 보다 배열로 처리하는 것이 편하겠죠. 이래서 poll() 편리합니다. poll() 변수 하나 외에도 배열을 받을 있으며, 한번의 호출로 모든 event 발생 여부를 확인할 있어 매우 편리합니다.

   

참고

앞으로 강좌를 진행하면서 말씀 드리겠습니다만 poll() 사용하는 다른 장점은 서로 다른 특징의 디스크립터를 사용한다 해도 프로그램 코드를 통일할 있습니다.

예로 rs232c 포트 10개와 tcp/ip 소켓 10개를 한번에 제어하는 프로그램을 작성했을 경우 역시 하나의 배열로 구성해서 poll() 사용할 있기 때문에 rs232c 처리와 tcp/ip 처리하는 프로그램 코드를 통일할 있습니다.

   

1000 time-out 시간으로 발생한 event 없을 경우 poll() event 발생할 까지 time-out 시간 동안 대기하게 됩니다.

시간 값은 msec 1000 1초를 의미합니다. 0 이면? 바로 복귀합니다. -1 이면? evevnt 발생할 까지 기다리게 됩니다. , block 버리죠.

if ( 0 < poll_state)

poll() 함수 결과가 양수라면 event 발생한 것입니다.

if ( poll_events.revents & POLLIN)

발생한 event 중에 POLLIN 있는 지를 확인합니다. POLLIN 해당되는 bit 1 세트되어 있다면 POLLIN으로 AND 값은 0 아닐 것입니다. 이렇게 비트값을 확인하여 event 발생 여부를 확인할 있습니다.

cnt = read( fd, buf, 1024);

write( fd, buf, cnt);

printf( "data received - %d %s\n", cnt, buf);

자료 수신 event 발생했으므로 fd로부터 자료 값을 읽어 들이고, 예제 테스트를 위해 다시 자료를 전송합니다. 또한 화면에도 수신한 자료를 뿌리고 있죠.

예제에 대한 설명은 여기 까지 드리겠습니다. 어떻게 자료 송신부터 수신까지 이해가 되시나요? 다음 시간에는 지금까지의 예제를 좀더 발전시켜서 한번에 여러 포트와 통신하는 방법을 말씀드리겠습니다. 조금씩 조금씩 발전 시켜 나가는 거죠.....^^

   

글을 읽어 주셔서 감사합니다.

게시물을...

목록 수정 삭제

엮인글 주소 : http://forum.falinux.com/zbxe/?document_srl=405838&act=trackback&key=2fe

   

   

2007.11.07 15:35:11 (*.126.183.43)

최강산

좋은공부되었습니다

요즘 통신관련 프로그램을 짜고 있는데 도움이 많이 되네요^^

2008.04.10 17:20:30 (*.94.41.89)

xerxer

감사합니다. 대략 감을 잡는데 도움이 되네요.

번호

제목

글쓴이

날짜

조회

19

TCP/IP 프로그래밍 방법

3

   

장길석

2007-03-19

21449

18

TCP/IP, UDP/IP 2

장길석

2007-03-14

12124

17

TCP/IP, UDP/IP 1

1

장길석

2007-03-14

17479

16

시리얼 통신에서 전송 속도 계산

장길석

2007-03-11

14785

15

CRC 위치는 어디가 좋을까?

장길석

2007-03-11

11932

14

CRC 계산

2

장길석

2007-03-10

19695

13

DLE 프로토콜 소개

5

   

장길석

2007-03-10

15188

12

프로토콜에 대해서

   

장길석

2007-03-10

20903

11

poll 이야기 1

장길석

2007-02-28

12714

10

rs232c 라이브러리 상세 분석

   

장길석

2007-02-23

16492

9

rs232c 통신 라이브러리

6

   

장길석

2007-02-23

16850

  

시리얼 통신 - 자료 수신을 위한 poll

2

장길석

2006-12-31

14819

7

시리얼 통신 예제 전체 설명

장길석

2006-12-29

14978

6

시리얼 통신 - data bit size parity

장길석

2006-12-29

10968

5

시리얼 통신 - start bit stop bit

1

장길석

2006-12-29

11594

4

시리얼 통신 - 통신 속도 결정

장길석

2006-12-29

11466

3

시리얼 통신 - 통신포트 열기

2

장길석

2006-12-29

23781

2

시리얼 통신 - 프로그램 분해 설명 시작!!

장길석

2006-12-29

15260

1

시리얼 통신 첫회

   

장길석

2006-12-24

20326

 

http://blog.daum.net/pinkky/6818685 (원본)

NMS는 Network Management System의 약자로, 네트워크 관리 시스템 또는 망 관리 시스템이다.

이 말의 의미는 NMS는 네트워크를 관리하는 시스템이며

그 관리 대상이 네트워크 또는 망이라는 의미이다.

즉, 관리 대상이 네트워크 또는 망이라는 사실을 알 수 있다.

말장난 같다는 생각이 들지는 모르겠지만 NMS에서 관리대상의 정의란 매우 중요하다.

 

그렇다면 네트워크란 무엇인가?

네트워크라는 것은 전산 자원간의 연결 전산자원까지 포함해서 - 이다.

"내 PC랑 네 PC랑 연결해서 잘 사용하고 싶어"라는 개념에서

네트워크의 개념이 출발한다고 보면 되겠다.

   

그렇다면 여기서 네트워크 관리자의 임무는 무엇일까?

네트워크 관리자는 이 네트워크가 잘 운영되도록 필요한 모든 조치를 취하는 사람이다.

그렇다면 네트워크 관리 시스템은 네트워크 관리자가 하는 일을 모두 가져갈 수 있는가?

답은 누구나 예상하겠지만 "NO. 아니오!" 이다.

NMS는 네트워크 관리자가 하는 일을 대체하기 시스템이라기 보다는

네트워크 관리자가 네트워크를 잘 관리할 수 있도록 보조하는 역할이라고 생각하는 편이 더 정확하다.

A와 B 두 전산자원을 잘 연결하여 쓰고 있던 어느 날

갑자기 두 전산자원 사이에 연결이 끊어지는 일이 발생하였다.

이러한 경우가 네트워크에서 장애가 발생하였다라고 보는 상황이다.

 

여기서 장애 발생 상황을 인지할 수 있는 경우의 수를 생각해 보도록 하자.

첫 번째 전산자원 A를 사용하고 있던 운영자가 전산자원 B에 대한 연결하여 사용하는 프로그램을 사용하다가 연결이 끊어졌다는 것을 발견할 수 있다.

두 번째 전산자원 A를 사용하고 있던 운영자가 다른 업무 도중 우연히 연결이 끊어진 것을 발견할 수 있다.

세 번째 전산자원 A 주변을 지나가던 누군가(운영자일 수도 있다)가 우연히 전산자원 A 또는 B에 꽂혀 있던 케이블이 빠진 것을 발견할 수도 있다.

네 번째 네트워크 관리자가 아주 부지런한 사람이거나 아니면 할 일이 없어서 네트워크 상태를 수시로 확인하다가 연결이 끊어진 것을 발견하는 경우도 있겠다.

   

그럼 이제 네트워크 관리자가 이 상황을 인지하기까지 걸리는 시간을 생각해 보자.

첫 번째 상황의 경우 사용자가 프로그램을 사용하기 시작하는 시간까지 연결이 끊어진 것을 발견하여 네트워크 관리자에게 통보할 때까지 걸리는 시간이다. 이 시간은 수 초에서 수 시간 또는 수 일이 걸릴 수도 있다. 게다가 이 사용자가 네트워크 관리 업무와 전혀 상관이 없는 사람인 경우 네트워크 관리자에게 말을 안하고 있는 경우도 많이 있다. 

 

두 번째 상황의 경우도 마찬가지이다. 운영자가 네트워크와 상관없는 업무를 하다가 장애를 인지하는 것을 그리 쉬운 일이 아니다. 마찬가지로 알고도 네트워크 관리자에게 전달 않거나 늦게 전달하는 경우가 빈번하다.

 

세 번째 상황의 경우는 그리 기대하지 않는 것이 좋겠다.

오히려 지나가다가 케이블을 건드려 빠지게나 하지 않으면 다행이다.

 

네 번째 네트워크 관리자가 수시로 확인하던 도중 발견하면 아주 다행스러운 경우에 해당된다.

네트워크 관리자가 바로 장애에 대한 조치를 취할 수 있기 때문이다.

   

네트워크는 연결되어 있는 상태에서 의미가 있기 때문에 정상적인 네트워크 구조에서는 연결이 안되는 상태가 있어서는 안된다. 일단 연결된 망에서 필요로 하는 주된 기능이 이 네트워크가 정상적으로 운영되고 있는지 상태를 알고 싶다라는 라는 필요이므로 NMS의 주 기능은 이 장애 관리로부터 시작하게 된다.

 

----------------------------------------------

NMS의 주된 역할이 장애를 인지하는 것이라고 알게 되었다.

   

그럼 이제 장애를 어떻게 인지할 것인가를 생각해 보자.

   

먼저 가장 쉬운 것은 모두가 아는 것처럼 대상 장비 또는 시스템에 ping을 때려 보는 것이다.

조금 더 잘 아는 사람은 SNMP Polling을 한다고 말할 것이다.

   

먼저 이 ping이라는 것에 대해 알아보도록 하겠다.

네트워크 분야에 종사하는 사람이라면 이 ping이라는 것이 뭐하는 것인지는 다들 잘 알고 있을 것이므로 이 ping으로 네트워크 관리를 어떻게 하면 되며, 문제점이 무엇인가만 살펴보도록 하자.

   

ping으로 네트워크를 관리하는 방식은 매우 간단하다.

관리 시스템으로부터 ping request에 대한 response가 없으면 장애로 보는 것이다.

그럼 네트워크 관리자가 모든 전산자원의 IP에 모두 ping을 때리고 있으면 어떨까?

그리고 ping이 안되는 장비가 있으면 조치를 하는 것이다.

일견 아주 단순하고 아무 문제도 없어 보인다.

   

그러나, 그렇게 단순한 문제만은 아니다.

여러분이 command(cmd) 창을 열고 자기 ip로 ping을 때려 보자.

========================================================================

C:\Documents and Settings\R51>ping 147.6.97.1

Pinging 147.6.97.1 with 32 bytes of data:

Reply from 147.6.97.1: bytes=32 time<1ms TTL=255

Reply from 147.6.97.1: bytes=32 time<1ms TTL=255

Reply from 147.6.97.1: bytes=32 time<1ms TTL=255

Reply from 147.6.97.1: bytes=32 time<1ms TTL=255

Ping statistics for 147.6.97.1:

    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),

Approximate round trip times in milli-seconds:

    Minimum = 0ms, Maximum = 0ms, Average = 0ms

C:\Documents and Settings\R51>

=========================================================================

   

그럼 Reply from 어쩌고 하면서 응답이 3~4번 떨어질 것이다. ttl=xx ms 하는 구문과 함께 말이다.

그럼 이 ping에 대한 응답이 네 번 중 한 번 없다고 장애일까?

아님 두 번? 아님 세 번 모두를 장애로 볼까?

장비가 다른 트래픽을 처리하느라 바쁘다면 ping 응답이 안 올 수 있다.

(ping은 우선 순위가 밀리기 대문이다.)

또는 네트워크 대역이 그리 좋지 못해서 timeout (보통 0.8ms) 이 나는 경우도 있다.

그럼 그런 것을 고려해서 0.8을 1.2나 2.0 정도로 늘려 줄 수도 있다.

도스에서 win98에서 xp에서 그리고  리눅스나 sun, hp 등 unix 시스템에서 이 ping utility의 사용법은 조금씩 다르며, 네트워크 관리자라면 ping의 옵션 정도는 알고 있어야 한다.

   

지금 여러분은 네트워크 관리자의 관리 정책이 적용되는 상황을 보고 있다.

장애정의 : 자원의 ip에 ping을 실행하여 응답이 없으면 장애로 인지한다.

기준설정 : 비지니스 rule 적용

         기준 1) 응답 세번에 모두 답이 없는 경우만을 장애로 인지한다. timeout은 1.5ms로 한다.

         기준 2) 응답이 한번이라도 없으면 무조건 장애로 본다. timeout은 0.8로 한다.

         기준 3) 저 위에 있는 것을 장비 또는 ip 별로 다 다르게 주었으면 좋겠다.

                   나중에 바꿀 수도 있으면 더 좋겠다.

         추가 조건 ) ping이 한번 빠지면 노란색, 두번 빠지면 빨간색으로 해주었으면 좋겠다.

                         ip가 없는 interface는 어떻게 하느냐... 등등...

기준 1은 굉장히 Loose하게 적용되는 경우이며, 약간의 지연은 장애로 보지 않겠다는 정책이다.

기준 2는 타이트하며 작은 지연도 허용되지 않는 크리티컬한 네트워크 운영 정책이다.

기준 3은 대부분의 사이트에서 원하는 방식이며, 추가조건도 꼭 따라 붙는다.

   

(이런 조건을 충족하는 NMS가 잘 아는 whatsup gold 나 openview nnm이라는 제품이다.

뭐 아는 사람은 다 알겠지만, 개인적으로 whatsup gold는 ping 장애관리 전문 제품으로 가격대비 성능으로는 최고라고 보고 있다. openview nnm은 비싸고 또 좋은 제품이다. 다만 쓰기가 매우 어렵고(영어) 우리나라 관리자들은 별로 좋아하지 않는다. 여기서 사족을 조금 더 달자면 openview nnm은 정말 괜찮은 제품이다. EMS나 NMS를 만들려고 고민을 해본 사람은 알겠지만, OV에는 이러한 고민에 대한 부분이 거의 다 수용되어 있다. 단지, UI가 너무 Old 하다는 것이 단점. 또 기능이 너무 많다 보니 쓰기가 어려워서 단점. 하지만 거의 다 필요한 기능들이다.) 

   

다시 장애 감지로 돌아오자.

이제 ip가 없는 interface의 경우를 살펴보자.

ip가 없는 interface라... 무엇이 있을까? 요새는 tcp/ip 환경으로 거의 대부분 구성되어 있지만, 아직도 WAN 구간에는 ATM이나 Flame relay 또는 광으로 된 연결 구간들이 있고, 대부분 ip가 없다. 또 장비의 카드 중에 장애가 나면 장비가 제대로 동작할 수 없는 것들도 있다.

이런 경우도 장애로 보아야 하기 때문에 난감한 일이 아닐 수 없다.

   

우리는 이러한 이유들 때문에 SNMP라는 프로토콜을 사용하여 네트워크 관리를 하게 된다.

SNMP를 지원하는 장비라면 MIB II에서 정의한 interface의 상태 ifoperstatus를 보고 장애인지 아닌지를 판별하는 것이다. 여기까지는 좋아보인다. 이론상으로도 그럴듯해 보인다.

   

그러나 네트워크 관리자는 머리가 복잡해 진다.

여기 인터페이스가 수십개 되는 장비가 있는데, 나는 그 중에 두 개의 상태만 알면 된다.

어떻게 해야 할까?

방법 1) 내가 원하는 인터페이스만 관리하도록 등록하고 이것들만 관리한다.

방법 2) 일일히 등록하기 어려우니, ifadminstatus와 ifoperstat가 다른 것만 체크해서 알려준다.

방법 3) 어쨌거나 up 상태였다가 down 상태이면 문제가 생긴 것이니 down이라고 알려주는 놈만 추려서 장애로 알려준다. 물론 내가 원하는 interface의 경우에만. trap을 쓰면 좋겠다.

   

제대로 된 NMS에서는 이런 것들을 관리자의 판단에 따라 설정할 수 있어야 한다.

그럼 설정하는 화면들이 많이 늘어난다. 고로 또 복잡해진다.

   

네트워크 관리자들은 복잡한 기능을 싫어한다.

그래서인지 nms가 인공지능처럼 동작하기를 원하는데...

프로그래은 인공지능이 아니다. 최소한 어떤 것이 중요한 인터페이스인지, 어떤 것을 장애로 볼 것인지는 알려주어야 한다. 아니면 default 값을 쓰게 되는데.. default 값을 쓰면서 nms가 틀렸다고 말해서는 조금 곤란하지 않겠냐는 거다.

   

또 요새 등장한 복병 중 하나가 보안 방화벽이다.

장비에서 snmp를 지원하는 것, snmp를 설정하는 것이 1차이고, 보안 정책도 확인해 보아야 한다.

snmp는 well-known port 이므로 보안 정책 상 허락하지 않는 경우도 있다. port를 바꿀 수도 있지만, manager와 agent가 모두 이 기능을 지원해야 한다. 이놈의 snmp는 simple network management protocol 이라는데 simple이 아니라 너무 어려워 보인다.

   

사실 더 어렵고 복잡한 뭐 CMIP이나 CORBA라는 것들이 존재하는데... 거의 시장에서 사라졌다.

사람들은 더 정확하고 잘정리된 표준 대신 간단한 표준을 선택하였다. 그래서 더 복잡해졌다.

   

어찌되었건 요약하자면 네트워크 관리자는 장애 관리를 하기 위해서 가장 많이 쓰는 icmp ping과 snmp 방식을 가지고 NMS를 구축할 수 있다.

   

이 때 필요한 것은 "좋은 NMS(쉬운것이 항상 좋지만은 않다)"와 "적절한 네트워크 관리 정책"이다.

------------------------------------------

앞에 두 개의 글에서 NMS의 중요한 기능 중에 하나는 장애를 자동으로 인지하고자 하는 것이고,

그러자면 장애를 판단하는 기준(정책)이 매우 중요하다 라는 것을 장황하게 설명해 보았다.

   

그렇다면 장애여부를 판단하는 기준을 어느 정도의 주기로 적용하면 좋을 것인지 살펴보자.

우리가 운영하는 네트워크에서는 icmp ping 또는 snmp polling 시 timeout을 1.0에 retry 3회 시에도 반응이 없으면 장애로 보기로 정책을 세웠다.

   

우리의 네트워크에는 장비가 10개 있다.

그럼 장비에 ping 또는 snmp request를 1분에 한번씩 보내보자.

10개를 죽 돌면서 ping을 해보고 상태를 반영하고 또 1분 후에 같은 일을 반복 수행한다.

별로 문제가 없어 보인다.

   

갑돌이네 네트워크에는 장비가 100개 있다.

역시 장비에 ping 또는 snmp request를 1분에 한번씩 보내보자.

이번에는 100개를 돌면서 같은 일을 한다. 근데 문제가 생겼다.

1분이 지났는데... 아직 100개의 장비 리스트의 끝까지 다 못갔다.

그럼 둘 중에 하나를 선택해야 한다.

1-뒤에 거는 무시한다.

2-걍 뒤에서 계속 진행하고 다 끝난다음 다시 시작하는 걸 생각해 본다.

조금 골치 아파진다.

프로그램을 수정하기는 어려우니 상태 확인 주기를 늘린다.

한 5분쯤으로 해보자. 잘 되는 거 같다.

   

을순이네 네트워크에는 장비가 1000개 있다.

역시 장비에 ping 또는 snmp request를 1분에 한번씩 보내보자.

이번에는 1000개를 돌면서 같은 일을 한다. 역시 같은 문제가 생겼다.

1분이 지났는데... 아직 100개 끝까지 다 못갔다.

그럼 둘 중에 하나를 선택해야 한다.

1-뒤에 거는 무시한다.

2-걍 뒤에서 계속 진행하고 다 끝난 다음 다시 시작하는 걸 생각해 본다.

조금 더 골치 아파진다. 반영주기를 10분으로 늘렸다.

같은 문제가 생긴다. 게다가 장애 반영이 너무 늦어진다.

장애가 나거나 복구된 것을 10분 주기로 알 수 있다.

결국 프로그램은 수정되어야 한다.

한 번에 리스트를 10개로 분할해서 돌린다.

1000개를 100개씩 나누어서 열심히 상태를 체크한다. 3분이면 된다. 다행이다.

   

병철이네 네트워크에는 장비가 10000개 있다.

위에서 문제를 해결한 프로그램이 있으니 10개로 나누어서 돌린다.

한번에 1000개씩 리스트를 나누어서 체크한다.

저런.. 잘 안된다. 반영주기를 10분으로 늘렸다.

같은 문제가 생긴다. 게다가 장애 반영이 너무 늦어진다.

프로그램은 또 수정되어야 한다.

한 번에 리스트를 100개로 분할해서 돌린다.

10000개를 100개씩 나누어서 열심히 상태를 체크한다. 3분이면 된다.

근데 프로세스가 한꺼번에 100개가 뜨고 시스템에 부하가 걸린다.

   

근데 10000대의 장비가 다 중요하지 않댄다.

그럼 중요한 거 100개는 1분으로 하고, 나머지는 걍 10분으로 했으면 좋겠다.

근데.. 아주 아주 중요한 장비 5개를 특별히 10초 정도로 관리 했으면 좋겠다.

물론 실시간이면 제일 좋겠지만 특별히 10초 정도도 괜찮겠다.

   

저런... 프로그램이 대폭 수정되어야 한다.

우리의 NMS는 특정 장비 또는 그룹 별로 상태 확인 주기를 다르게 줄 수 있어야 하고,

상태 확인 프로그램은 이 설정내용에 딸 가변적으로 동작해야 하며,

장비 갯수를 알아서 판단해서 10개로 쪼갤 것인지 1000개로 쪼갤 것인지를 결정해야 한다.

   

얼핏 보면 인공지능 프로그램 같다.

그러나 여기서도 반드시 인풋이 있다.

1. 내가 관리해야 하는 대상과 갯수가 정해져 있다.

2. 상태반영 주기를 정의해야 한다.

   

따라서 관리자는 이러한 정책을 정하고 NMS에 반영할 수 있어야 한다.

이러한 정책들을 입력하고 설정하는 화면이 프로그램에 추가된다.

   

네트워크가 커질수록 관리대상의 종류와 중요도가 달라질 수록 이러한 설정 메뉴들은 점점 추가되며,

프로그램은 점점 복잡해 질 것이다.

   

   

----------------------------------

네트워크 장애관리에서 가장 중요한 것은 관리정책과 좋은 NMS이다.

   

세번째 얘기에서는 ping response check와 snmp polling을 통한 장애 인지에 대해서 생각해 보았다. 전체 네트워크 장비에 대해 이렇게 일일히 체크를 한다는 것은 사실상 실시간 체크가 어렵다.  그렇다면 실시간으로 상태를 반영할 수 있는 방법이 무엇인가?

   

바로 SNMP Agent가 올려주는 상태에 대한 정보를 직접 받는 것이다.

이것이 잘 알려져 있는 SNMP Trap이라는 것이다. SNMP Trap은 장비가 중요한 장비 자체의 상태 변화를 SNMP Manager에게 알려주는 것인데, 그럼 어떤 경우에 상태를 알려줄 것인가?

   

표준에 의하면 여섯가지의 경우에 Trap을 발생시킨다.

SNMP Cold Start / SNMP Warm Start / SNMP Link Down / SNMP Link Up / SNMP Authentification Failure / SNMP EGP Down 이다.

   

문제는 이 여섯 가지의 경우를 통해서는 장비 CPU가 높아져서 죽기 직전인지, 장비 자체가 죽어버렸는지 등등 알 수 없는 것이 너무나 많다는 사실이다.

네트워크 관리자 입장에서는 알고 싶은 정보가 많기 때문에 업체에서는 Private MIB을 통해 추가적인 정보를 제공한다. Private MIB은 벤더별로 다르므로 벤더에서 제공한 MIB 파일과 문서들을 참조해야 하며, NMS는 이러한 Private MIB에서 제공하는 SNMP Trap 정보를 해석할 수 있는 능력을 가지고 있어야 한다.

   

모든 장비가 이러한 Private MIB을 충분히 제공할 것으로 기대해서는 안된다.

물론 이러한 MIB을 충분히 제공하는 장비들도 있다.

   

문제는 NMS에서 이러한 Private MIB을 어떻게 처리할 것인지 결정해야 하며,

역시 좋은 NMS는 이러한 기능들을 충실히 제공한다.

약간 좋은 NMS는 이러한 기능을 약간(잘 알려진 장비에 대해서만) 제공한다.

당연히 이러한 기능이 없는 NMS도 많이 있다.

여러 가지 기능을 충분히 지원하는 NMS는 가격이 비싸며, 사용하기 어렵다고 느껴진다.

   

여기에서 추가적으로 알아두면 좋은 것이 syslog이다.

대부분의 장비는 자체적으로 log를 메모리에 남기고 있는데,

대부분의 네트워크 관리자들은 이 log를 참조하여 장비 관리를 하고 있다.

그러나, 이 log들은 장비가 리부팅되면 없어져 버리며,

일일이 장비에 login 하여 확인해 보아야 하는 단점이 있다.

수십대의 라우터에 모두 로그인하여 log를 볼 수는 없기에,

대부분의 라우터, 스위치들은 syslog 프로토콜을 이용하여

이 log들을 syslog 서버로 보내는 기능을 제공한다.

   

syslog는 형식이 단순하게 종류, 시간, 장비명(서버명), 로그로 구성되어 있으므로

관리자가 쉽게 인식이 가능하며, 항상 장비에서 보던 형식이므로 친숙하다.

자연스럽게 네트워크 관리에 많이 이용되고 있다.

   

UNIX 시스템의 경우 syslogd라는 데몬이 기본 프로세스로 제공되므로,

장비들로부터 이 syslog들을 받아 로그들을 저장하며, NT는 기본 기능이 아니라 키위 등 syslog를 받아서 저장해 주는 상용 프로그램을 사용해야 한다.

SUN의 경우 /etc/syslog.conf 파일을 이용하여

받게 될 syslog 종류, 저장될 파일명 등에 대한 환경을 설정할 수 있다.

   

장비의 숫자가 많아지거나, debug 모드 등으로 syslog를 받게 되는 경우,

엄청난 log의 양 때문에 관리하기에 부담스러워 질 수 있으며,

특히 FWSM 같은 장비는 firewall log를 syslog로 발생시켜 주는데...

초당 몇백건의 syslog를 처리할 수 있는 프로그램이 별로 없기 때문에

이런 종류의 방화벽을 도입할 때는 관리 툴에 대해 고민을 해보는 것이 좋겠다.

   

============================================================================

   

약간의 여담을 달자면... 벤더들에 대한 불만이 많다. 

웬만하면 규약을 지켜서 만들고, Pravate 아래 구조를 함부로 바꾸지 말며, 문서를 잘 찾을 수 있도록 해 주었으면 좋겠다. 대체 홈페이지에 가도 어느 구석에 이 mib들이 박혀 있으며 뭐에 쓰는 건지 알 수가 없다. 버전이 올라간다고 공지도 없이 MIB Tree 구조를 바꿔버리는데 대책이 없다. 뭐 그나마 SNMP 라도 지원해 주면 고맙기는 하다.

------------------------------

 

앞서 네트워크에서 장애를 인지하는 방법에 대해 몇 가지 살펴 보았다.

   

1. ping 을 이용한다. => 제일 쉽다. 그러나 정책을 잘 세워야 한다.

   

2. snmp polling 을 이용한다.

 => 다소 쉽다. 표준 MIB이라 불리우는 mib II 정보들을 이용한다.

 => Private mib의 영역으로 가게 되면 난해해진다.

 => 역시 정책이 들어가게 되면 ping의 경우보다 10배는 어려워진다.

   

3. snmp trap을 이용한다.

 => 다소 쉬우나 장애 상황을 분리해 내는 것이 어렵다.

 => 이건 Private mib이 필수 사항이다.

 => 역시 정책도 필수 사항이다.

 => 이 trap은 syslog와는 달리 여러 개의 variable들로 나누어져 올라오므로

     관리자가 받아서 문장으로 만들어 주어야 한다. => 때문에 복잡해질 수 있다.

     이 variable의 갯수나 형식은 정해져 있지 않다.

   

4. syslog를 이용한다.

 => 다소 쉬우나 장애 상황을 분리해 내는 것이 어렵우며, log의 홍수에 빠질 염려가 있다.

 => 장비를 만지는 엔지니어들은 제일 선호하나, 관리자들은 좋아하지 않는다.

 => 그냥 로그다.

   

그러나...

네트워크에서 장애가 발생하는 것을 파악하는 것은 이렇듯 명확하지만은 않다.

최근들어 Application의 비중이 높아지고 장비의 사양이 올라가면서...

장비에 들어가는 OS들도 점점 복잡해졌고 자연히 장비 OS의 버그 때문에 발생하는 장애도 많이

발생하게 되었으니... 이런 것들은 장애라고 인식하기가 그리 쉽지만은 않다.

   

어찌되었건 "빠른 장애인지"라는 요구사항이 어느 정도 총족된다면,

관리자들은 다음 단계를 요구하게 된다.

바로 장애를 예고해 주는 시스템이다.

   

사실... 장애징후를 나타내는 것은 그리 많지 않다.

흔히 볼 수 있는 증상이 장비에서 Major 또는 Alert!이라고 정의되는 Log를 발생시킨다거나

장비 또는 카드, 회선의 불량에 의한 회선 에러(CRC, Collision 등)가 쌓이고 있다거나

장비가 죽기 직전 CPU 사용율이 치솟았다거나, 아니면 측정 성능 지표들이 높아졌다거나

L4나 L7 장비의 경우 Session에 흐르는 데이터가 전혀 없다거나 등등의 현상이 있을 수 있는데,

이러한 것들은 Log 쪽을 제외하고는 성능관리 쪽에 더 가깝다.

   

그러나 장애예보라는 면에서 보자면 장애관리에 포함되기도 하므로,

이것도 보는 시각에 따라 장애관리에 포함시키기도 한다.

   

이렇게 장비 성능이 일정 수치를 벗어나면 장애징후로 보는 방법은 크게 두 가지가 있다.

하나는 NMS에서 주기적으로 장비에서의 주요 성능 지표들을 체크하다가 정해진 값을 벗어나느 경우

경보를 올려주는 방법이고, 또 하나는 장비 자체가 스스로 특정 값 이상인 경우 SNMP Trap이나 syslog로 알려주는 경우이다.

전자는 장비가 해당 성능 지표에 대해 값만 제공해 준다면 NMS의 역량에 달려있지만,

Trap의 경우에는 해당 장비에서 그러한 기능을 제공해 주어야만 가능하다.

   

관리자의 입장에서 볼때는 두 가지 경우 모두 가능했으면 하는 경우가 많으므로,

단 두 가지 방법은 데이터를 얻게되는 경로가 다르기 때문에 

이 두 가지 정보를 하나로 통합해 주는 기능이 NMS에서 제공된다면 더욱 좋을 것이다.

   

추가적으로 네트워크 관리자들은 성능 지표가 임계치를 한번 초과한다고 바로 알려주는 것이 아니라 

최소 2회 이상 초과한 경우였으면 좋겠다. 지표에 따라 초과가 아니라 특정 값 미만인 경우,

혹은 특정값 사이를 벗어난 경우 등등 다양한 옵션을 요구하는 경우가 있다.

그리고 CPU인 경우에는 CPU라는 메세지를, 메모리인 경우에는

메모리라는 별도의 메세지를 요구하는 경우도 있다.

또 임계치 경보를 발생시켰더라도 해당 값 아래로 떨어지면 복구용 메세지를 발생시킨다거나,

아니면 한번만 경보를 발생하는 것이 아니라 특정 지표가 계속 임계치를 벗어나는 경우

재경보를 발생시키는 등의 다양한 기능들을 요구하는 경우도 있다.

   

따라서 장비의 사용 상태를 측정하여 경보로 알려주는 예보 시스템을 제대로 구축하기란

그리 쉬운 일이 아니다. 

 

---------------------------------------

지금까지 네트워크 관리에서 장애 판단 및 예보 기능에 대해 알아보았다.

   

이번에는 이 장애 판단 및 예보에 가장 흔하게 사용되는 LOG에 대해서 알아보기로 하자.

   

대부분의 장비들은 장비 자체에 장비의 운영에 관련된 LOG를 기록한다.

때문에 네트워크 관리자들은 장비에 접속하여 이 LOG들을 분석함으로써 장비의 현재 상태나

과거의 운영 상태들을 관리할 수 있다.

   

그러나 이 LOG들은 휘발성이므로 (장비에는 메모리가 있을 뿐 DISK가 없다.)

장비가 문제가 생겨 부팅하고 나면 모두 사라져 버린다.

   

대부분 장애 발생시에 장비를 껐다 켜는 경우가 많으므로 추후 LOG를 보고자 하면 이미 모두

사라져 버린 후라 장애의 원인을 파악하기란 쉽지가 않다.

   

따라서 대부분의 장비는 SNMP Trap 또는 Syslog의 형태로 LOG를 기록할 수 있는 다른 시스템에

이 LOG를 전송할 수 있는 기능을 제공한다.

   

가장 많이 사용되는 Cisco 등 대부분의 벤더는 SNMP 보다는 syslog 형태로 더욱 장비의 LOG 형식에

가깝게 LOG를 기록할 수 있도록 해 준다.

   

그렇다면 이 LOG들은 어떤 방식으로 남겨지는가?

   

Cisco의 경우 syslog를  Alert!, Critical, Error, Warning, Notification, Information, Debugging Mode 의 7가지 모드로 제공한다. syslog를 debugging mode로 설정하면 어느 정도의 log가 쌓이게 될까?

   

실제... 이 라우터에 이상이 있거나 이상 패킷이 많아 log가 매우 많이 발생하고 장비에 부하가 걸렸던 경우(였던 것으로 추정) debug mode 가 걸려있던 장비가 갑자기 CPU 사용율이 치솟으며 reboot 되는 경우를 본 적이 있었다. 75XX급 이상 대형 장비인 경우 이 debugging mode로 10대 정도만 log를 받아도 하루 100만건이 넘는 log들이 쌓이는 것을 볼 수 있는데 하루 백만건이면 NMS에서 관리하기에도 버거운 양의 데이터이다.

   

어쨌건 이 LOG들을 통합 저장하고 모니터링 할 수 있는 기능도 NMS의 필수 기능이다.

주요 기능은 LOG를 받아서 실시간으로 뿌려줄 수 있을 것.

그리고 모두 저장한 후 검색 조건으로 골라서 볼 수 있을 것.

그리고 가능하다면 통계를 내 줄 것.

   

이 짧은 세 줄에  LOG 관리 시스템의 모든 것이 담겨 있다.

-----------------------------------

 

LOG 관리에 대해 좀 더 자세히 알아보자.

   

사실 LOG 관리라는 것은 앞서 말한 것처럼 아래의 세 가지로 요약된다.

   

실시간 LOG 모니터링 => 문제 LOG 발생 시 경보

모든 필요한 LOG의 저장 => 가능하면 전부 다

저장된 LOG의 검색 => 통계 기능도 있으면 좋음

   

   

장비들의 LOG를 서버로 받기 위해서는 해당 장비들이 syslog 프로토콜을 지원하는지 확인하고

해당 장비의 syslog 기능을 enable 해주면 된다. 그리고 LOG의 등급(종류)을 설정해 준다.

여기서 필요한 것이 "관리 정책"이다.

altert이나 critical 만 설정하면... 실제 해당 네트워크에서는 중요한 LOG를 놓칠 수 있다.

때문에.. 실제 운영자나 엔지니어들은 debug 모드를 선호한다.

그러나 이것은 장비에 부하를 줄 수 있고, debug 모드로 올라오는 LOG들을 모니터링한다는 것은

별로 즐겁지 않은 일이므로, 관리자의 성향과 필요성에 따라 모드를 적절히 설정한다.

   

syslog 서버에서는 unix 시스템인 경우 디폴트로 제공하는 syslogd가 /var/log/아래에 파일로 쌓아준다.

수정하고 싶으면 /etc/syslog.conf 파일을 열어 적절히 수정하면 된다.

   

windows 서버의 경우 syslog가 기본으로 제공되지 않으므로,

syslog 데몬 프로그램을 구해서 설치해야 한다. kiwi 같은 것들이 많이 쓰이며 유료이다.

대부분 외산이며, 국산 프로그램은 단품보다는 로그 분석 솔루션에 가까운 것들이 몇 개 있다.

외산의 경우 기능은 매우 단순하다. syslog를 모아서 보여주고,  파일로 저장해 준다.

   

작은 네트워크에서는 이런 솔루션들이 매우 유용하게 쓰인다.

그러나 대형 네트워크에서는 얘기가 달라진다.

장비에서 올려주는 LOG들이 하루 몇십만건, 몇백만건이 이르게 되면,

이 LOG를 파일로 관리한다는 것이 얼마나 노가다 작업이 되는지 해본 사람은 알 것이다.

몇 기가나 되는 파일 덩어리에서 원하는 LOG들을 찾아내기가 얼마나 어려운가.

때문에 대량의 로그를 관리하기 위한 DB가 등장한다.

여기서 네트워크 관리자는 고민에 빠지게 된다.

DB가 등장하면 이제 이 S/W는 네트워크 관리자의 영역을 벗어나

개발의 범주로 넘어가 버리기 때문이다.

LOG를 저장하기 위한 DB 구축 비용과 이를 제대로 볼 수 있게 하기 위한 개발비는

네트워크 관리자에게 상당한 부담을 안겨 준다.

   

LOG를 관리하는 것이 얼마나 중요한가?

LOG 관리 시스템은 꼭 있어야 하는가??

------------------------------------------

 

LOG 관리 프로그램 사용에서 LOG 관리 시스템 구축으로의 개념 전환이란 그리 쉽지만은 않다. 이 시스템이라는 것은 H/W, S/W, 그리고 개발이 들어가야 하므로 돈이 어마어마하게(!) 들어가기 때문이다.

   

대부분의 경우 LOG 는 대용량 데이터이다.

대용량 데이터의 대한 처리와 투자 비용은 돈과 연관된 곳에서는 그리 크게 여져지지 않는다. 통신사에서의 콜 횟수나 문자에 대한 데이터 들 또는 카드사의 기록들, 그리고 은행 입출금 기록들이 그러하다. 이런 과금, 결제에 관련된 데이터들은 매우 중요하며 하나라도 유실될 경우 기업의 손실 또는 이익과 직결되므로 대용량일지라도 하나도 빠짐없이 매우 소중히 다루어지게 된다.

그리고 그 결과물도 매우 명확하다.

접속 기록 1회 20초 500원. 하나 놓치면 500원 손실.

투자비용 10억이면 100억 이익.

이 얼마나 명확하며 알기 쉬운가.

   

그러나 이 네트워크 관리에서 발생하는 LOG는 그렇지가 않다.

애시당초 snmp나 syslog 라는 프로토콜 자체가 udp라는 손실을 허용하는 것인데다가,

데이터가 유실된다고 해도 당장 눈에 보이는 손실이 발생하는 것이 아니기 때문이다.

게다가 그 결과물도 그리 명확하지 않다.

네트워크에 장애가 나서 원인이 뭐냐고 물으면 걸핏하면 log가 남아있는 게 없어

알 수 없다고 한다. 그래서 그럼 시스템을 구축하라고 하면 그것도 구축하려면 수억이 든단다.

그래서 그럼 근거를 가져와 봐라(ROI 분석) 하면 안 가져 온다.

어쨌건 장애가 하도 발생하니 수억을 들여 구축해 주었더니,

이번에 장애가 발생한 부분은 구축 범위에서 제외된 곳에서 발생한 것이란다.

구축범위 내라서 다행히 로그가 남아 있는 경우도 뭔가 명확한 게 없단다.

그래서 이유를 물었더니 디버깅 모드가 아니라서 자세하지 않단다.

대체 무슨 소린지 알 수가 없다.

 

이런 식이니 경영진이 보기에는 개념 자체도 명확하지 않은 이 LOG 관리 시스템이라는 것이

사기같다는 생각이 들 수 밖에 없다.

특히 구축할 때는 마치 만능이던 것처럼 떠들어대던 업체 말만 듣고 구축 했는데,

막상 구축하고 보니 이래서 안되고 저래서 안되고 한다.

업체가 사기를 쳤거나 네트워크 담당자들이 무능하거나 둘 중에 하나라고 생각할 수 밖에...

그래서 담당 부서에서 뭔가를 구축하려고 한다 해도 투자를 할 수가 없다.

그러니 점점 더 모르겠다.

그래서 뭔가 알 수 없는 문제가 발생하면 항상 네트워크 쪽을 의심할 수 밖에 없다.

---------------------------------

 

 

일반적인 장애 관리에서 사용하는 기법(폴링)는 장애가 난 후 그것을 빨리 알려줄 수는 있지만

장애가 왜 발생했는지는 알기는 어렵기 때문에 사실 네트워크의 장애 발생 시

제일 명확한 원인을 제공해 줄 수 있는 것은 어디엔가 남아 있는 LOG가 맞다.

그러나 LOG 관리 시스템은 구축하기에 비용이 많이 든다는 점과

비용대비 결과물이 그리 만족스럽지 못하다는 것(돈으로 환산되지 않는다는 점...),

그리고 시스템을 구축하고 유지 관리할 만한 전문가가 별로 없다는 것이다.

그렇더라도... 관리를 하지 않을 수는 없으니... 그것도 문제다.

   

어쨌거나.. 비용과 효율성에 대한 것은 일단 제쳐 두고

실제로 LOG 관리 시스템을 구축하는 절차에 대해 생각해 보자.

   

항상 그렇듯이 제일 처음 할 것은 관리 대상과 정책을 정하는 것이다.

   

1) 어떤 장비들의 로그를 관리할 것인가?

2) 장비들의 logging 레벨(혹은 trap level)을 어느 정도로 정할 것인가?

그리고 이 두 가지를 고려해 1일 평균 log 량을 산정한다.

이것은 도입할 시스템과 구비해야 할 DISK의 용량을 정하는데 백데이터가 된다.

   

하지만 이것들 보다 먼저 해야 하는 일이 있다.

그것은 무엇을 보고자 하는지 정하는 것이다.

보고자 하는 LOG가 무엇인지, 어떤 형태로 보기를 원하는지 결정하고 시작해야 한다.

   

이 부분은 아주 중요하지만 간과하고 진행하다가 최종 단계에서야

되니 안되니 하며 개발자와 발주자 사이에 큰 문제로 불거지게 되는 경우가 허다하다.

   

특히 장비가 로그를 어떤 형태로 남기는지 확인하는 것도 중요한 이슈 중에 하나인데

이에 따라 개발방법과 개발해야 하는 범위가 전혀 달라질 수 있기 때문이다.

   

시스템 도입 전에 관리하고자 하는 장비들이 로그를 전송하는 방식을 확인해야 한다.

대부분이 syslog 또는 trap을 지원하지만... 그렇지 않은 장비들도 많이 있기 때문이다.

   

다행히 별도의 포트를 통해 udp 또는 tcp 방식으로 로그를 전송해 준다면,

이를 받아 주는 프로그램을 개발해야 한다.

장비들의 EMS를 통해서 자체 프로토콜로 logging을 하는 장비라면

EMS로 부터 log를 가져오는 방법을 연구해 이를 프로그램 해 주어야 한다.

이런 식으로 각각의 장비 별로 log를 통합할 수 있는 방법을 찾는다.

아예 통합이 불가능한 장비라면, 다음 장비 교체 시기에 이에 대한 업그레이드나

교체도 고려해야 할 것이다.

   

이러한 절차들이 끝나야 어떤 시스템을 도입할 것인지 결정할 수 있게 된다.

   

그럼 log 관리 프로그램을 상용으로 할 것인지, 아니면 개발을 할 것인지 결정해 보자.

   

상용 로그 분석 시스템은 네트워크 관리 용도 보다는 web log 분석이나, 방화벽 로그 분석 등의

용도로 많이 쓰이기 때문에 네트워크 용으로 사용하려고 하다 보면 여러 가지로 수정해야 하는

경우가 많다. 따라서 처음부터 개발을 하는 것이 더 나을 수도 있다.

   

다음은 DB를 사용할 것인지 그냥 파일을 사용할 것인지를 고려한다.

DB를 사용하면 비용이 발생하기는 하나 안정적이며 로그 검색이나 통계에 훨씬 용이하다.

LOG를 사용하면 구축 비용이 적게 든다. 단, 검색이 매우 어렵다.

최근에는 디스크의 가격이 많이 하락했기 때문에 디스크 가격이 그리 중요하지는 않다.

저장하는 것이 문제가 아니라... 쌓여 있는 데이터를 어떻게 활용하느냐가 관건이기 때문이다.

일단적으로 시스템이라는 관점에서 볼 때, LOG 보다는 DB 사용을 권장하고 싶다.

   

다음은 어떤 DB를 사용할 것인가 이다.

상용 DB라면 오라클이나 MS SQL서버를 가장 많이 사용할 것이고,

비용이 문제라면 mysql을 선택하면 된다.

(무료였으나, 최근 들어 기업용으로 쓸 때는 약간의 가격을 지불하는 것으로 알고 있다.)

   

대부분의 장비들이 syslog를 사용한다면 unix 시스템을 사용하는 것이 편할 것이고,

이 때 가장 저렴하게 구축하는 방법은 PC 서버에 linux+mysql+syslod daemon 조합이다.

여기에 아파치 톰캣등의 웹서버를 이용하여 검색 및 통계 기능을 만들 수 있다.

개발비만 추가하면 된다.(제대로 된 개발자를 찾기 어렵다.)

   

조금 더 제대로 된 시스템을 만들자면...

PC 서버에 windows+mssql+개발프로그램(.net)에 iis 또는 .net 기반의 view를 제공해 주는

시스템을 구축하는 방법도 있을 것이다.

아마도 위의 시스템보다는 더 쉽게 개발자를 구할 있을 것이고

syslog 외에 다른 프로토콜도 쉽게 수용할 수 있을 것이다.

   

또 다른 방법은 mssql 대신 오라클을 사용하는 것이고...

PC 서버 대신 unix 서버(hp, sun, ibm 등)이나 정식 서버를 사용하는 것이다.

마찬가지로 unix 서버를 사용하는 경우에는 syslog daemon을 이용해도 크게 무리는 없지만,

db로 저장하는 부분에 대해서는 프로그램이 필요하다.

그러나 sqlldr 등을 활용하며 대용량 로그에 대한 db insert가 훨씬 용이하고 빠르기 때문에,

개발자 입장에서 볼 때 오라클을 이용하는 것이 훨씬 낫다.

   

실제로 하나씩 insert 하는 것보다...

sqlldr를 이용한 insert가 훨씬 낫다는 것을 테스트 해본 적이 있다.

프로그램으로 초당 수천건의 데이터를 처리해 DB에 저장하는 것은 그리 쉬운 일은 아니다.

   

물론 데이터의 안정성 등에 대해서도 가장 나은 편이다.

단점이야 항상 그렇듯이... 비용이 많이 든다는 것이겠지만...

   

어쨌거나...

쌓여있는 로그에 대한 검색 기능 또한 개발의 중요한 이슈이다.

   

때문에 어떤 검색 기능이나 통계 기능을 원하느냐가

처음에 DB를 설계할 때의 중요한 고려사항이 되기 때문에,

어떻게 보면... 이 부분이 가장 중요한 부분이다.

    

솔루션을 제공하는 업체는 제공할 수 있는 모든 기능을 나열하고,

솔루션을 도입하는 업체는 그 중에 원하는 기능을 골라 도입하지만,

나중에 알고 보면 그 기능은 특정 장비 또는 상황에 국한되어서만 제공할 수 있는 경우가 많다.

때문에 솔루션을 도입할 때는 현재의 운영중인 네트워크 환경에 적용할 수 있는지

확인을 거친 후 도입해야 한다. 쉽지만은 않은 일이다.

 

 

--------------------------

 

 

요약하자면 NMS 에서 장애 관리란

1. 장애 발견 -> 조치 -> 조치에 대한 정보 제공

2. 장애 후 원인발견 -> 로그 관리

3. 장애 예측 -> 장애 징후 -> 성능 또는 로그에 의한 경보

정도로 정리할 수 있다.

   

1번에서 요구되는 것은 장애발생 후 빠른 복구를 위한 조치방법에 대한 정보를 제공할 것인지

2번에서 요구되는 것은 로그에서 원인을 어떻게 찾아낼 것인지,

3번에서 요구되는 것은 성능 또는 로그에서 어떻게 장애징후를 알아낼 수 있는지...

이 세 가지를 충족시키는 것이 knowledge base 일 것이다.

   

knowledge base를 만드는 일은 매우 중요하지만 실제로 만들어내기는 어렵다.

유능한 네트워크 운영자는 NMS라는 시스템과 친하지 않고, 유능한 개발자는 네트워크 장비와 친하지 못한 채 고객의 변덕에 따라 UI 수정작업에 매달리기 때문일 것이다.

또한 자신의 노하우를 정리하여 지식화 하고 이를 제대로 사용하는 풍토가 정착되지 힘든 정서도 한 몫 하여 이러한 KB를 완벽히 제공하는 NMS는 아마도 영원한 숙제로 남게 되지 않을까 싶다.

----------------------------------------------

 

[성능관리]

NMS에서 성능관리라 함은 장애 징후 발견과 장비의 운영 추이를 분석하여

향후 네트워크 설계에 반영하기 위한 운영 데이터의 축적을 의미한다.

   

장애 징후의 발견은 평균 또는 정상 운영에서 발생하는 것 외의 이상 상태를 감지해 내는 것,

그리고 따라서 네트워크 장비를 증설하거나, 회선을 증속 또는 감속하거나, 과잉 투자에 대한 부분을 축소하기 위한 모든 의사결정을 위한 기초 자료 축적 및 자료 제공을 위한 시스템이 필요하다.

   

이 모든 일을 위해서는 일단 현재 운영되고 있는 장비들의 운영정보를 모두 저장하여 적절한 통계 자료를 추출할 수 있는 시스템이 필요할 것이다.

   

장비의 운영 지표 중 주로 요구되는 것은 회선의 증감속을 위한 네트워크 사용량 측정,

그리고 장비 업그레이드 또는 교체를 위한 장비 가용성 측정이다.

   

전자에서 주로 요구되는 것은 회선사용율인데, 회선사용율을 측정하는 방법은 SNMP에서 제공하는 ifinoctets 와 ifoutoctets에 8(byte) 곱한 후 이것을 ifspeed 값으로 나누는 것이다.

예전에 반이중 방식(half duplex)을 사용하던 시절에는 in과 out을 합쳐서 계산했지만,

최근에는 전이중방식(full duplex)을 사용하므로 in과 out를 각각 별도로 산출하는 것이 일반적이다.

   

장비의 가용성 부분은 대부분 cpu와 memory 사용율을 의미한다.

장비에서 처리해야 하는 패킷수와 이를 버퍼링할 수 있는 용량은

장비가 고급화 되어갈수록 점점 더 중요해 지고 있다.

문제는 이 CPU와 memory는 public mib의 영역이 아니라 private 영역이라는 것이다.

벤더마다 모두 다른 값을 다른 방식으로 제공한다.

   

어떤 장비는 cpu 사용율을 어떤 장비는 cpu idle 율을 어떤 장비는 cpu idle time을...

그리고 이러한 값이 아예 제공되지 않는 장비도 있다.

그리고 최근 장비의 진화에 따라 장비당 하나 있던 CPU가 장비당 2개 이상.. 그리고 장비 자체(샤시)외에 모듈에 cpu가 장착되기 때문에, 그리고 여러 개의 장비들이 모여 하나의 장비를 이루는 구조로 변경되는 추세이므로... 원하는 cpu 사용율을 찾아내려면 장비와 그 구조, 해당 모듈의 명칭과 역할 등 해당 벤더에서 제공하는 private mib 구조에 대해 잘 알아야 한다.

메모리도 마찬가지이다. buffer 또는 memory 라는 애매모호한 명칭들로 존재하는 수많은 mib value 중에 해당 장비의 실제 메모리 값을 찾아 적용시켜야 하며, 다시 이를 이를 일반 user가 이해하기 쉬운 사용율로 변환하여 보여 줄 수도 있어야 한다.

이 외에 장비의 특성에 다라 다른 private 항목들을 보는 경우도 있다. L4~ L7 장비의 경우에는 session count도 모니터링하고, 특히 정책에 따라 특정 session에 대한 정보만을 원하는 경우도 있다.

   

"이 장비에서는 어떤 값을 모니터링 해야 하고 그게 snmp에서는 어떤 mib 을 참조하면 됩니다. 

보세요. 장비에서 이 값과 snmp로 보는 이 값이 일치하지요?"

하고 적절한 값을 찾아내고 이를 매치시키고 확인을 해주는 것.

혹은 "이 장비는 유감스럽게도 이러이러한 항목에 대한 value는 snmp로 제공하지 않네요"

라고 확신을 줄 수 있는 사람이 네트워크 업계에 과연 얼마나 될까?

----------------------------

 

 

장애관리에서도 그러했듯이 제일 중요한 것은 무엇을 모니터링할 것인지 결정하는 것이다.

회선사용율, CPU 사용율, 메모리 사용율 이 세 가지를 모니터링하기로 결정했다고 보자.

   

먼저 회선사용율에 대해서 살펴보도록 하자.

앞서 말한 것처럼 회선사용율은 다음과 같은 공식으로 이루어진다.

   

                                                                          Δ(ifinoctets) * 8 *  100

회선송신사용율(output utilization on a interface) = ---------------------------

                                                                          Δ(seconds) * ifspeed 

   

                                                                          Δ(ifoutoctets) * 8 *  100

회선수신사용율(input utilization on a interface) = ---------------------------

                                                                          Δ(seconds) * ifspeed 

   

   

여기서 각각의 mib 정보는 아래와 같다.

   

.1.3.6.1.2.1.2.2.1.10

ifInOctets OBJECTTYPE

−− FROM RFC1213MIB, IFMIB

SYNTAX Counter

MAXACCESS readonly

STATUS Mandatory

DESCRIPTION "The total number of octets received on the interface, including framing characters."

::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib2(1) interfaces(2) ifTable(2) ifEntry(1) 10 }

   

.1.3.6.1.2.1.2.2.1.16

ifOutOctets OBJECTTYPE

−− FROM RFC1213MIB, IFMIB

SYNTAX Counter

MAXACCESS readonly

STATUS Mandatory

DESCRIPTION "The total number of octets transmitted out of the interface, including framing characters."

::= { ISO(1) org(3) DOD(6) Internet(1) mgmt(2) mib2(1) interfaces(2) ifTable(2) ifEntry(1) 16 }

   

.1.3.6.1.2.1.2.2.1.5

ifSpeed OBJECTTYPE

−− FROM RFC1213MIB, IFMIB

SYNTAX Gauge

MAXACCESS readonly

STATUS Mandatory

DESCRIPTION "An estimate of the interface's current bandwidth in bits per second. For interfaces which do not vary in bandwidth or for those where no accurate estimation can be made, this object should contain the nominal bandwidth."

::= { ISO(1) org(3) DOD(6) Internet(1) mgmt(2) mib2(1) interfaces(2) ifTable(2) ifEntry(1) 5 }

   

   

10G 이상의 ifspeed를 지원하는 interface를 측정하는 경우에는 interfaces(2) 아래의 기본 mib이 아니라

ifXObject(?) 아래의 mib들을 이용해야 한다.

   

간혹 ifspeed의 값이 잘못 셋팅되어 있는 경우 사용율이 100%를 훌쩍 넘어가는 경우가 많이 있다.

실제로 업무에 적용했을 대 180% 이상까지도 올라가는 경우도 종종 보았다.

원인은 거의 90% 이상 ifspeed 때문이다.

실제 회선속도(bandwidth)가 알고 있는 속도보다 높은 경우,

장비에 ifspeed가 잘못 셋팅되어 있는 경우 등인데...

전자라면 적은 돈으로 많은 대역을 사용하고 있는 것이니.. 그냥 사용하면 되겠고,

후자라면 장비의 셋팅 값을 바꾸어 주면 된다.

   

NMS 구축 시 이 100%를 넘어가는 값 때문에 운영자들이 NMS를 못믿겠다고 하는 경우가

많이 있었는데... 이는 NMS 문제가 아니라 실제 장비 또는 회선의 문제라고 보는 게 더 맞다고 본다.

또 이런 문제 때문에 100% 가 넘어가면 무조건 100%로 맞추어서 보여달라고 요청하는 관리자도

많이 있었는데... 역시 국내 다른 제품 중에 이렇게 되어 있는 것들을 본 적이 있었다.

   

개인적으로는 보여주기 위해 이렇게 숫자를 맞추는 것보다는...

알고 있는 것과 운영 상태가 다른 것으므로 정보를 수정하는 것이 더 나을 것이라고 생각하고,

그게 NMS의 도입 목적에 더 가깝지 않을까 생각한다.

   

NMS는 네트워크 운영 상태를 파악하고 이를 제대로 운영하기 위한 백데이터를 모아줄 수 있는

시스템이지, 보고서를 작성하기 위해 조작하는 대상이 아니다.

-----------------

 

네트워크의 성능에 대한 관리를 얘기할 때는 이상치에 대한 경고와 평상시의 사용량에 대한 추이 분석에 대한 정보 제공으로 나눌 수 있다. 이상치에 대한 경보 제보 기능은 장애 징후 예보와 밀접한 관계가 있어 보통은 혼동되어 장애 관리에서 사용되어지기도 한다.

   

어쨌거나 현재의 네트워크 상태가 평상시의 사용량과 다르다는 것을 증명하거나, 네트워크 장비들을 증설 혹은 감량을 해야 한다거나 회선을 증속 또는 감속하는 등의 네트워크 운영에 대한 정책을 세울 때 필요한 백데이터들이 바로 이 성능 관리를 위한 데이터들이다.

   

NMS 구축 시 난감한 부분 중 하나가 이 경보 기분을 얼마로 할 것인지, 증속 및 감속을 위한 기준치를 얼마로 할 것인지 결정하는 것이다. 프로젝트를 하다보면 다른 곳(경쟁사)에서는 어떻게 사용하고 있느냐 업체에서 자체적으로 사용하고 있는 기준치는 얼마냐 라는 질문을 받게 되는데 사실 답이 없다.

   

90년대에 네트워크 컨설팅 자료로 많이 쓰여졌다는 모 회사에서 만든 자료라고 하는 달랑 두 장짜리 파워포인트 문서에 보면 아래와 같이 씌여 있다.

(자료근거 : 美 Concord社 Network Health Traffic Guide 4-3 발췌)

=======================

 

 

네트워크 관리 시스템은 말 그대로 네트워크 관리를 위한 시스템이다.

네트워크 관리를 위한 표준 프로토콜이 바로 SNMP이라는 것인데,

1990년대 말까지는 CMIP과 SNMP가 공존하다가 2000에 들어오면서 SNMP의 승리로

귀결지어졌다. 사람들은 복잡한 것을 별로 좋아하지 않는다는 사실이 다시 증명된 셈이랄까..

   

SNMP는 말 그대로 Simple Network Manahement Protocol 이다.

그러나 이 Simple이라는 단어는 항상 상대적으로 라는 수식어가 생략되어 있다는 것을 알아야 한다.

원래 완벽하고 상세하게 설계하기로 했던 CMIP에 비해 상대적으로  Simple 하다는 것일 뿐...

결코 이 프로토콜이 Simple 하다는 것은 아니다...

오히려 구현자가 제멋대로 mib을 결정할 수 있기 때문에 구현자 입장에서는 별로 달갑지 않다.

   

암튼 기본적인 개념상으로 볼 때 이 프로토콜은 매우 Simple 하다.

GET-RESPONSE : 값을 물어본다. 대답한다.

SET : 값을 셋팅한다.

TRAP : 스스로 상태를 보고한다.

이 세 가지 동작을 통해 네트워크를 관리하기로 한 것이니... 매우 Simple 하긴 하다.

   

그럼 방법을 정했으니, 어떤 데이터를 주고 받을 것인가도 알아야 한다.

그 데이터를 정의해 놓은 사전이 MIB(Management information base)이다.

자고로 네트워크 관리자라면 MIB 하면 이게 Man in black이 아니라는 사실을 알아야 겠다.

그리고 이 데이터들을 어떤 식으로 나열해 놓을 것인가를 정의한 것이

SMI(Structure of management information)이다.

   

쉡게 생각해서 SNMP는 언어, MIB은 사전, SMI는 언어규칙이라고 생각하면 된다.

나와 철수가 한국어로 말하고자 한다면...

둘은 일단 한국어로 말할 수 있어야 하며...

상황에 맞는 적절한 단어를 선택하여 정해진 구조(주어+목적어+동사)로 말해야 한다는 것이다.

네트워크 관리 시스템과 네트워크 관리 대상인 장비는

이 SNMP라는 프로토콜로 대화를 하며

SMI에 기반한 MIB에 정의되어 있는 항목을 적절히 선택하여 대화하는 것이다. 

   

때문에 SNMP를 지원하는 장비라고 해서 모두 내가 원하는 대로 관리될 수 있을 것으로

기대해서는 안된다. 예를 들자면 24개월짜리 아가와 대화를 하려면...

분명 한국말로 대화중임에도 불구하고 많은 제약이 뒤따르지 않는가... (아기와의 대화라... --)

네트워크 장비도 이 아가 수준의 장비들이 많이 존재한다고 보면 된다.

   

어쨌건 시장에서는 보다 완벽하고 상세하며 모든 요구사항들을 충족시키는(고자 했던) 

CMIP  대신에 보다 단순하고 구현하기 쉬우며 만들기 쉬운 SNMP를 선택했고...

(벤더 입장에서는 당연히 둘 중 뭘로 할래? 하면.. 쉬운 거.. 로 갈 수 밖에 없다.

개발기간 = 인력 = 돈 = 원가 상승이지 않은가... 사용자측에서도 빨리 되는 제품을 원했고... )

현재는 CORBA니 뭐니 하는 별종이 등장하고 있지만...

   

결국에는 현재 NMS에 주로 사용되는 주요 프로토콜은 SNMP라는 사실이 중요하다.

   

여기에 SNMP의 한계를 극복하기 위해 추가적으로 등장한 것이

RMON(Remote network MONitoring)이라는 프로토콜이다.

이름만 봐서는 무슨 용도인지 참 상상하기 어려운 용어인데...

이름대로 풀어보자면 멀리서 네트워크의 사용량을 감시하기 위한 프로토콜이다. ^^;;

즉 SNMP로 커버하기 힘든 멀리 떨어져 있는 특정 로컬 네트워크 영역(segment)에서의

네트워크 사용량(구조)을 알아보고자 하는 의도에서 시작되었으며,

SNMP와 유사한 구조로 MIB이라는 것을 채택하였다.

따라서 RMON I, II에서 정의한 MIB들이 존재하게 되었으며, 

RMON Probe 들은 이 RMON MIB을 지원하고,

대부분의 SNMP Manager에서 이 RMON MIB을 이용하여 해석할 수 있는 구조이다.

   

그러나 이 RMON이라는 것이 참 문제가 많았다.

여기서 필요한 데이터라는 것이 관리자들이 궁금해 하는 것들을 많이도 제공해주기는 했는데,

결정적으로 이러한 데이터들은 대단히 양이 많았고, 처리하는데 시간이 많이 걸린다는 것이었다.

따라서 RMON 정보들을 처리하기 위한 프로브들은 대량의 데이터를 보관, 처리해야 했고,

당시 저용량의 네트워크 장비들은 이러한 것들을 수용하기 힘들 수 밖에 없었다.

2000대 초반 장비들의 스펙들을 보면 RMON 지원이라는 항목들을 많이 볼 수 있는데,

엔지니어들은 이를 올리는 것을 대단히 꺼려하였다.

장비가 부하를 견디지 못해 죽어버리는 일이 종종 발생했기 때문이다.

특히 네트워크가 TCP/IP로 바뀌고, 네트워크의 데이터량이 증가하고,

전송속도가 10/100에서 1G/10G로 가는 현 시점에서 장비가 이런 데이터들을 수용하고 처리하는 것은 거의 재난에 가까운 일이었다. 때문에 현재는 일부 RMON 프로브만 남고 대부분 시장에서 사라진 상태다.

   

그러나 네트워크에 흘러다니는 데이터의 정체를 알고 싶다는 꾸준한  요구가 있었고,

이런 이유로 인해 최근에(2000년도 초반) 등장한 것이 netflow로 잘 알려진 nFlow 라는 개념이다.

   

본래 이 라우터, 스위치 등 네트워크 장비란 놈이 패킷 기반으로 동작을 한다.

즉 송신자가 발송한 정해진 사이즈의 패킷을 정해진 경로를 통해 수신자에게 잘 보내면 되는 것이 네트워크 장비의 역할인데... 이 패킷은 어떤 어플리케이션의 조각 또는 데이터의 조각이므로 실제로는 하나의 업무 Flow가 원활하게 이 정해진 경로를 타고 수행되는 것이 궁극적인 목표가 된다는 데 촛점을 맞춘 개념이다.

   

따라서 패킷과 경로라는 컨셉 기반의 라우터들이... 이 Flow 컨셉을 차용하여 장비에 적용하면서

그 동안 RMON에서 관리자들이 가장 궁금해 하던 부분만 떼어내어 관리용으로 제공하기로 한 것이다.

   

이 flow 라는 표준은 7개의 장비 제조 벤더들이 모여서 만들었기 때문에 RFC 어쩌고 하는 문서들이 없다. 대신 업체들이 동의한 규약은 있다. 큰 그림만 만들고 구현은 벤더 나름대로 했기 때문에 내용도 조금씩 다르다는 말이다. 

   

어찌되었건 중요한 것은 이 flow 표준을 따르는 장비들은 flow에 대한 정보들 -  ip, port(어플리케이션 구분 가능), 수신지 ip, port, 패킷량 등을 제공한다는 것이다.

네트워크 사용자들이 많이 궁금해 하는 것 중에 하나가 90% 이상 꽉꽉 차서 흘러다니는 저 회선에 실제 돌아다니는 패킷의 정체가 무엇이냐? 인데... 바로 이것을 해결해 준 것이다.

   

CISCO에서 사용하는 용어가 netflow이며..  flow의 대명사처럼 사용된다.

업체에 따라 c-flow, s-flow 등의 이름을 붙이기도 한다.

   

물론 RMON이 그것을 제공해 주기는 했지만....

엄청난 데이터의 발생으로 인한 여러 가지 문제를 극복하지 못했으므로...

flow를 통해서 그것을 제공해 주기로 한 것은 획기적인 일이 아닐 수 없었다.

   

처음에는 rmon이 그러했듯이.. flow 기능에도 여러 가지 문제들이 많이 있었지만...

지금은 cisco를 필두로... 많이 개선되어... 이를 기반으로 한 nms 제품들이 많이 나와 있다.

   

물론 이것도 만능은 아니며, 여전히 대용량 데이터에 대한 처리부분이 한계로 남아 있다.

cisco는 이것을 독립모듈로 떼어내어 NAM이라는 모듈로 제공하고 있다.  


<http://blog.daum.net/_blog/hdn/ArticleContentsView.do?blogid=05LLi&articleno=6818685&looping=0&longOpen=>에서 삽입

Unix Domain Socket - UDP

윤 상배

dreamyun@yahoo.co.kr

   

   

1절. 소개

우리는 이미 이전에 Unix Domain Socket를 이용한 IPC 에서 Unix Domain Socket 에 대한 기본적인 내용을 다루었었다.

그때는 SOCK_STREAM 을 이용한 연결지향의 Socket 를 사용했었는데, internet 소켓과 마찬가지로 UDP 특성 Socket 를 사용할수도 있다. 이번 글 에서는 UDP 를 이용한 Unix Domain Socket 에 대해서 알아보도록 하겠다.

   

2절. Unix Domain Socket (UDP)

2.1절. 특징

internet socket 상에서 UDP 를 다룰때, 관심을 가지는 특성이 비연결지향성이며, 그런이유로 데이타를 유실할수도 있으며, 데이타의 순서가 바뀔수 있다. 그러므로 중요 데이타 통신을 위한 프로토콜로는 UDP 가 적합하지 않다. 라는 점이 될것이다.

그러나 Unix Domain 영역의 UDP 는 internet 영역과는 특성이 좀 다르다고 할수 있다. Unix Domain 에서의 UDP 는 일종의 PIPE 와 같은 형태로 다루어진다. 게다가 동일한 같은 시스템 영역에서의 데이타 교환이므로 패킷이 유실되거나, 순서가 뒤바뀌는 등의 문제는 전혀 발생하지 않을거라고 장담할수 있다.

   

2.2절. 메시지 전달 방식

internet socket 에 전달되는 패킷들이 헤더 + 바디 로 이루어지는 것과 마찬가지로, Domain 영역에서의 데이타도 헤더 + 바디 로 이루어진다. 그러나 헤더의 구성요소는 매우 다르다.

Domain 영역에서의 데이타 통신은 알겠지만 "지정된 파일" 을 통해서 이루어지게 된다. 이 파일로 데이타를 쓰고/읽는 작업을 하며, 이것은 마치 FIFO 와 같은 pipe 형태로 전달된다.

그러므로 헤더영역에는 다른 기타의 정보가 들어가는게 아닌 통신을 위한 파일정보 가 들어가게 된다. /usr/include/sys/un.h 의 sockaddr_un 구조체를 보면 확실히 이해가 가능할 것이다.

struct sockaddr_un
{
__SOCKADDR_COMMON (sun_);
char sun_path[108]; /* Path name. */
};
                        

위의 구조체를 보면, sockaddr_in 과는 달리 단지 파일의 위치 지정을 위한 108바이트 크기의 배열변수만 있는것을 알수 있다.

   

2.3절. 서버/클라이언트 구성방식

internet socket 을 이용한 서버/클라이언트 구성과는 달리 Domain 영역에서 udp 를 이용한 서버/클라이언트의 구성은 주의해야 될 몇가지 점이 있다.

가장 기본적인 문제는 Domain 영역에서의 udp 는 Internet 영역에서의 udp 와는 달리 경로를 지정 할수 없다는 단점을 가진다. 이것은 다중의 클라이언트를 받아들이는 서버의 경우 문제가 될수 있다.

다음은 Internet 영역의 udp 서버/클라이언트 모델의 경우이다.

+----------+
+------- | Client 1 | address 1
| +----------+
+------+ | +----------+
| 서버 |-+------- | Client 2 | address 2
+------+ | +----------+
| +----------+
+------- | Client 3 | address 3
+----------+
                        

Internet 영역에서의 서버는 단지 하나의 소켓지정번호(endpoint) 만을 가지고도 다중의 클라이언트와의 연결이 가능하다. 그 이유는 Internet 영역에서 통신을 할때 UDPIP 상위 프로토콜이므로 IP 프로토콜의 헤더를 통해서 해당 메시지가 어디에서 출발했는지 알수 있기 때문이다. 그러므로 굳이 select(2) 나 poll(2) 같은 작업없이 단지 하나의 소켓지정번호로 통신이 가능해진다.( UDP 프로그래밍의 기초를 참고하라.)

그러나 Unix Domain 영역의 udp 소켓이라면 이야기가 달라진다. 기본적으로 가질수 있는 정보가 "파일 경로" 뿐이므로 다중의 클라이 언트로 부터 메시지를 받았을때 어떤 클라이언트로 부터 메시지가 전달되었는지를 알수가 없는 것이다. 물론 이것은 데이타 영역에 클라이언트를 식별할수 있는 어떤 정보를 보냄으로써 해결할수 있긴 하겠지만, 설사 그렇다 하더라도 서버는 다중의 클라이언트중 원하는 클라이언트(client)로 메시지를 보낼방법이 없다. 만약 다중의 클라이언 트가 떠있는 상태에서 메시지를 보낸다면 누가 먼저 읽을지 예측할수가 없게된다.

이문제를 해결하기 위해서는 각 클라이언트 마다 통신을 위한 각각의 소켓지정파일 을 생성할수밖에 없다. 이것은 FIFO 에서 서버/다중클라이언트 를 구성하기 위한 방법과 마찬가지이다.

+----------+
+---| Client 1 |
+------+ | +----------+
| |-----+ +----------+
| 서버 |---------| Client 2 |
| |-----+ +----------+
+------+ | +----------+
+---| Client 3 |
+----------+
                        

결국에는 Domain 영역에서 udp 소켓을 사용하기 위해서는 select, poll 등을 써야만 한다는 결론에 도달한다.

여기에서 한가지 궁금한점이 문득 생길것이다. Domain 영역 UDP 소켓 에서의 다중클라이언트를 받아들이기 위한 서버의 제작을 위해서는 그럼 클라이언트의 숫자만큼 소켓파일을 생성시켜야한다는 뜻인데, 그렇다면 서버는 어떻게 클라이언트가 접근할줄 알고 클라이언트와 서버 모두가 알수 있는 소켓파일을 생성할것인가 ?

이문제의 해결방법은 여러가지가 될것이다. 마치 internet 의 TCP 소켓이 다중의 연결을 받아들이기 위해서 accept(2) 하는 하나의 endpoint 소켓을 두는 것처럼, Domain 영역에서도 하나의 endpoint 파일을 두는 것이다. 물론 이 endpoint 파일의 이름은 서버와 클라이언트간에 약속이 되어 있어야 할것이다.

그러먼 서버는 최초에 endpoint 를 위한 소켓파일을 하나 생성하고 이것을 통해서 클라이언트가 접근하면 적당한 이름으로 새로운 소켓파일을 만든다음에 이 파일이름을 클라이언트에게 전달해서 클라이언트가 전달받은 파일이름으로 쓰기를 하도록 하면 된다.

   

2.3.1절. 예상과는 달리 사용하는게 좀 번거롭군요 ?

예상과는 달리 다중의 클라이언트를 받아들이도록 Domain 영역 udp 소켓을 구성하는게 좀 까다롭다라는 생각이 들수도 있을 것이다.

그러나 어차피 내부 시스템에서의 통신용이라면 대부분의 경우 여러개의 클라이언트가 붙는다고 하더라도, 그 클라이언트가 정해져 있는 경우가 대부분이다. 그러므로 그냥 각 클라이언트 마다 어떤 파일을 통신에 쓰라고 아예 지정해주면 된다. 그러면 단지 select 나 poll 만을 돌림으로써, 간단하게 서버/클라이언트 프로그래밍이 가능하다.

또한 Domain 영역에서의 TCP 소켓과는 달리 다소 복잡한 연결과 연결대기를 위한 작업이 필요가 없으므로 코딩하기도 간편하다는 장점도 가지고 있다. 또한 패킷단위로 주고 받음으로 직관적으로 이해하기 쉬운 코드를 만들수 있다는 장점도 가진다.

   

2.4절. 예제 코드

그럼 예제 프로그램을 만들어 보도록 하겠다. UDP 프로그래밍의 기초 에서 다루었던 덧셈 프로그램인 sum_server.c 와 sum_client.c 를 Domain 영역에서 동작하도록 변경시킬 것이다. 위의 프로그램들을 참조하면서 코딩하도록 하자.

프로그램자체는 일반적인 Internet UDP 소켓 프로그램과 거의 동일함으로 이해하는데 이해가 없을것이다.

   

2.4.1절. 서버프로그램

예제 : sum_server.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

struct data
{
int a;
int b;
int sum;
};
int main(int argc, char **argv)
{
int sockfd;
int clilen;
struct data mydata;
struct sockaddr_un clientaddr, serveraddr;

sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket error : ");
exit(0);
}
unlink(argv[1]);

bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, argv[1]);

if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind error : ");
exit(0);
}
clilen = sizeof(clientaddr);

while(1)
{
recvfrom(sockfd, (void *)&mydata, sizeof(mydata), 0, (struct sockaddr *)&clientaddr, &clilen);
printf("%d + %d = %d\n", mydata.a, mydata.b, mydata.a + mydata.b);
sendto(sockfd, (void *)&mydata, sizeof(mydata), 0, (struct sockaddr *)&clientaddr, clilen);
}
close(sockfd);
exit(0);
}
                                

   

2.4.2절. 클라이언트 프로그램

예제 : sum_client.c


// 클라이언트 아래와 같이 하면 안됩니다.
// 서버에서 보낼 때, 클라이언트가 바인드해야 정보를 받을 수 있습니다.
// 이 글을 보시는 분은 적절한 코드로 수정해 주시기 바랍니다.
// 그외 기타 간단한 오타 및 타입 오류는 제가 수정하고 갑니다. - 용운

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

struct data
{
int a;
int b;
int sum;
};
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_un serveraddr;
int clilen;
struct data mydata;

sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("exit : ");
exit(0);
}

bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, argv[1]);
clilen = sizeof(serveraddr);

mydata.a = atoi(argv[2]);
mydata.b = atoi(argv[3]);
mydata.sum =0;

if (sendto(sockfd, (void *)&mydata, sizeof(mydata), 0,
(struct sockaddr *)&serveraddr, clilen) < 0)
{
perror("send error : ");
exit(0);
}
if (recvfrom(sockfd, (void *)&mydata, sizeof(mydata), 0,
(struct sockaddr *)&serveraddr, (socklen_t *)&clilen) < 0)
{
perror("recv error : ");
exit(0);
}
printf("result is : %d\n", mydata.sum);

close(sockfd);
exit(0);
}
                                

   

2.4.3절. 테스트

먼저 서버를 띄운다음에, 클라이언트를 통해서 더하고 싶은 2개의 숫자를 인자를 통해서 넘기면 된다.

[root@localhost src]# ./unix_domain_udp_server /tmp/test_udp
5 + 6 = 11
7 + 1024 = 1031
...
                                

[root@localhost src]# ./unix_domain_udp_client /tmp/test_udp 5 6
[root@localhost src]# ./unix_domain_udp_client /tmp/test_udp 7 1024
                                

   

3절. 결론

다른 Domain 영역 소켓과 마찬가지로, IPC 대용으로 사용가능하다. TCP 소켓이 IPC 대용으로 사용하기가 비교적 복잡하다는 단점과, 오늘 알아본 UDP 도메인 소켓과 아주 비슷한 FIFO 가 범용성이 좀더 떨어지는 단점을 보완한 적당하고 편리하게 사용가능한 IPC 로써의 용도를 제공해 줄것이다.

   [출처]<http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/IPC/Unix_Domain_Socket_UDP>에서 삽입

+ Recent posts