336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
지금까지의 글에서 검증시점을 앞당김으로 인해 발생하는 이익에 대해서 소개했고 이어 구체적으로 사용할 수 있는 여러 가지 방법에 대해 소개했습니다. 하지만 글의 흐름상 언급하지 못한 부분이 있어 여기서 소개합니다. 지금까지 했던 얘기해서 크게 벗어나는 얘기는 아니고 동일한 맥락을 가지고 있기 때문에 참고하면 좋을 것 같습니다. 아래는 오류의 원인을 찾고 있는 한 개발자의 가상사례입니다.

어느 날 한 개발자가 웹 애플리케이션의 오류로그를 살펴봅니다. 그런데 데이터베이스에 나이를 저장하는 쿼리 부분에서 제약조건위배 오류가 발생하고 있습니다. 오류에 대해 자세히 살펴보니 나이 필드에 NOT NULL 제약이 걸려있음에도 NULL 값이 입력되고 있다는 내용입니다. 그런데 오류를 자세히 보니 실행경로를 보여주는 Stacktrace 정보가 없습니다. 코드를 보니 누군가가 Exception을 잡아서 그냥 한 줄 로그만 출력하게 해놓았습니다. 이런! 열악한 상황이지만 어쨌든 문제는 찾아야 하기 때문에 쿼리 부분에 문제가 있나 라는 생각을 해봅니다. 쿼리에 값을 넣어주는(Binding) 부분을 자세히 살펴봅니다. 그런데 큰 문제가 없어 보입니다. 그 다음으로는 자연스레 서비스 레이어(Service Layer)를 살펴보게 됩니다. 혹시 나이 부분에 대해 뭔가 다루는 부분이 있나 자세히 살펴봅니다. 하지만 특별한 것을 발견하지 못합니다. 마지막으로 프리젠테이션 레이어(Presentation Layer)를 살펴봅니다. 그리고 프리젠테이션 레이어에서 나이 값이 잘 들어왔는지에 대한 검사를 하고 있지 않다는 것을 발견합니다. 거의 이 부분이 원인일 것이라 생각하지만 확신할 수는 없습니다. 왜냐하면 프로그래밍에는 너무 다양한 상황이 있다는 것을 알고 있기 때문입니다. 

위의 예를 통해 저는 두 가지 문제점을 봅니다. 첫째는 개발자가 원인을 조사하기 위해 여러 파일들을 살펴보아야 했다는 점입니다. 두 번째는 시간을 들여 여러 파일을 살펴보았음에도 불구하고 명확한 결론이 아닌 거의 확실한 추정 정도의 수준에서 조사를 끝낼 수 밖에 없다는 것입니다. 여기서 위 사례에 한 가지 가정을 더해봅시다. 마지막에 개발자가 추정한 것이 실제원인이었다는 가정입니다. 이 가정 하에서 보면 위와 같이 일을 어렵게 만든 원인을 알 수 있습니다. 바로 '오류 희석'입니다.

널리 사용되거나 공식적인 용어는 아니지만 오류 희석은 시간 혹은 공간을 지남에 따라 오류가 본래의 모습을 점점 잃어버리는 것을 뜻합니다. 위 사례의 경우 근본 원인은 사용자가 나이를 입력하지 않았다는 것입니다. 하지만 문제는 프리젠테이션 레이어와 서비스 레이어를 지나 데이터베이스에 질의하는 부분에서 전혀 다른 모습으로 발생하였습니다. 그 결과로 개발자는 문제를 찾기 위해 문제가 발생한 지점까지 도달할 수 있는 모든 경로를 역추적해야 했습니다. 

그렇다면 해결책은 무엇인가요? 해결책은 무척 간단합니다. 바로 프리젠테이션 레이어에서 나이가 정확히 들어오는지를 검사하고 만약 나이가 정상적으로 들어오지 않는다면 엄격하게 예외처리를 해주면 됩니다. 사용자에게 '나이를 입력해주세요.'라는 문구를 보여줄 수도 있고, 바로 에러를 발생시켜 처리를 중지할 수도 있습니다. 이렇게 처리한다면 문제가 발생했을 때 사용자든 개발자든 문제를 정확히 알 수 있습니다. 특히 개발자가 에러로그를 보았을 경우 개발자는 소스 파일을 탐색하거나 추정을 할 필요가 없습니다. 왜냐하면 에러로그 그 자체만으로도 무슨 문제인지 너무나도 명확하게 알 수 있기 때문입니다.

위에서 얘기한 것은 빠른 실패(Fail-Fast)의 대표적인 예입니다. 빠른 실패(Fail-Fast)는 이전에 언급했던 Fedex의 1-10-100 원칙과 유사점을 가집니다. 빠른 실패의 취지는 이왕 실패할거면 빨리 실패하자는 것입니다. 왜냐하면 위의 예대로 잘못된 부분이 있음에도 실패하지 않고 시간이 지나다 보면 오류희석으로 인해 잘못된 부분을 점점 탐지하기 어려워지고 실패에 대한 처리 또한 어려워지기 때문입니다. 그래서 앞서 얘기했던 검증시점을 앞당기려면 보다 빠르게 실패하는 것이 좋습니다.

하지만 주의해야 할 점은 모든 곳에서 빠른 실패가 필요하지는 않다는 점입니다. 때로 문제나 결함을 허용하는 것이 매우 중요한 일인 경우가 있습니다. 예를 들어 포털의 메인화면을 생각해볼 수 있습니다. 포털의 메인화면은 매우 다양한 구성요소로 이루어져 있습니다. 그런데 그 중 우측 하단 쇼핑 정보를 가져오는 부분에 문제가 생겼다고 가정을 해봅시다. 이 경우 화면을 보여주기 위한 모든 처리를 중지한 후 화면을 표시하지 않는 것 보다는 그 부분을 제외하고 다른 부분은 정상적으로 보여주는 것이 현명한 판단일 것입니다.


WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
최근 진행했던 두 번의 프로젝트는 내게 무척 새로운 프로젝트였습니다. 왜냐하면 프로젝트의 목적이 특정 기능의 개발이 아닌 기존 코드의 리팩토링이었기 때문입니다. 첫 프로젝트를 진행할 때 저의 최초 관심은 '개선'이었습니다. 어떻게 하면 소스를 좀 더 유지보수하기 좋게 만들 수 있을까? 하지만 실제로 프로젝트를 시작하고 전반적인 작업의 진행을 시작하자 저의 관심은 개선에서 점차 '검증'쪽으로 향하게 되었습니다. 왜냐하면 개선을 하며 자연스레 발생하는 영향력이 어마어마하다는 것을 깨달았기 때문입니다. 좋은 예로써 핵심 클래스의 인터페이스를 수정해야 하는 경우가 있었습니다. 그런데 그 수정으로 인해 영향 받는 부분을 살펴보자 영향 받는 하위 프로젝트만도 10개[1]가 넘었습니다. 따라서 개선도 개선이지만 검증을 성공적으로 하는 것이 매우 중요하게 느껴졌습니다.

어떻게 하면 검증을 성공적으로 할 수 있을까? 가장 먼저 생각난 것은 QA(Quality Assurance)였습니다. 제가 일하는 환경에는 능력이 매우 뛰어난 QA부서가 있었고, 사내 표준 프로세스상 배포해야 하는 모든 제품은 반드시 QA를 거쳐야 했습니다. 따라서 열심히 리팩토링을 한 후 QA에게 검증을 요구하는 것은 매우 자연스러운 일이었습니다. 하지만 곰곰이 생각해볼 때 몇 가지 면에서 문제를 느꼈습니다.

첫째는 위에서 얘기했던 것처럼 영향 받는 범위가 매우 크다는 점이었습니다. 제가 일하는 환경의 QA는 보통 블랙박스 관점으로 기능 중심의 검증을 수행했습니다. 따라서 보통의 경우 개발자가 특정 부분을 수정하면 수정한 부분으로 인해 영향 받는 기능을 QA에게 이야기 했습니다. 이 경우 QA는 매우 기본적이며 핵심적인 주요 기능에 대한 검증을 진행하는 것과 더불어 수정으로 인해 영향 받은 기능을 추가적으로 검증했습니다. 하지만 제가 진행했던 리팩토링의 경우 위와 같은 방법으로 수정범위를 얘기하려고 하면 거의 모든 기능을 검증 해달라고 말해야 했습니다. 왜냐하면 위에서 얘기했듯이 영향력이 어마어마했기 때문입니다. 더욱이 당시 QA 자원이 많이 부족한 상태였는데 거의 모든 기능에 대해 검증해달라고 말하는 것은 바람직하지 못해 보였습니다.

둘째는 문제 발견 시점에 따른 비용증가 때문이었습니다. FEDEX에는 1-1-100원칙이 있습니다. 이 원칙은 제품을 출고하기 전에 문제를 발견하면 비용이 1만 필요하지만 출고 후에는 10의 비용이 필요하며 고객에게 항의가 들어오면 100의 비용이 필요하다는 원칙입니다. 이 원칙은 소프트웨어에도 그대로 적용된다고 봅니다. 아래 표는 실제 내가 일하는 환경에서 발생하는 현상을 바탕으로 작성했습니다.

 문제 발견 시점  관련 자원(문제 처리 비용)
 개발자가 개발 중  담당 개발자
 QA 중  BTS(Bug Tracking System)
 외부와 의사소통 담당하는 개발자
 담당 개발자
 배포 후 서비스 중
 고객
 문제/장애 알림 시스템
 서비스 기획자
 서비스 운영 책임 개발자
 BTS(Bug Tracking System)
 담당 개발자
 QA
 배포 담당자(재배포가 필요하기 때문에)

각 환경에 따라 다소 차이는 있겠지만 큰 맥락에서 위 표와 크게 다르지는 않을 것이라 생각합니다. 위 표를 보면 FEDEX 원칙과 유사하게 문제가 늦게 발견되면 될수록 처리하는 데 필요한 관련 자원이 증가함을 볼 수 있습니다. 따라서 특수한 환경이 아니라면 QA 단계에서 문제를 발견하는 것 보다는 개발자가 문제를 발견하는 것이 조직 전체 비용 관점에서는 유리합니다.

마지막으로 QA가 탐지하기 어려운 영향력이 있다는 점 때문입니다. 위에서 잠시 애기했듯이 QA는 블랙박스 관점으로 기능중심의 검증[2]을 수행합니다. 이 경우 화면으로 즉시 보여지는 부분에 대해서는 매우 높은 수준의 검증이 가능합니다. 예를 들어 화면상의 특정 부분이 일그러져 보이거나, 확연히 구분할 수 있게 문자 등으로 오류가 보이는 등의 문제점입니다. 하지만 월말이 되어 통계 화면에서 보여지는 데이터의 입력이 누락되거나 하는 문제는 발견하기 어렵습니다. 이러한 문제는 외부로 즉시 드러나지 않기 때문입니다.

따라서 저는 QA에게 모든 검증을 의존하는 것은 좋지 못한 선택이라고 생각합니다. 그것보다는 개발자가 최전방에서 적극적으로 보다 많은 검증을 수행해야 한다고 봅니다. 물론 QA를 배제할 생각은 없습니다. 다만 일차적으로 개발자가 나름의 방법으로 검증을 먼저 진행한 후 이차로 QA가 검증하는 이중검증이 더 좋은 결과를 만들 것이라 생각합니다. 이중검증은 동일한 문제를 전혀 다른 방법으로 검증하여 검증의 정확도를 더욱 높이는 방법입니다. 일반적으로 개발자와 QA의 시각은 많이 다른 편이기 때문에 각자가 생각하는 최선의 방법으로 이중검증[3]을 하면 분명히 긍정적 효과가 있으리라 봅니다.

참고 설명

[1] 제가 리팩토링을 진행했던 프로젝트는 공통 라이브러리 성격의 프로젝트였습니다.
[2] 제가 일하는 환경에는 QA가 블랙박스 테스트만 하지만, 개발자 출신의 QA가 코드검토와 같은 화이트박스 테스트를 진행하는 곳도 있다고 합니다.
[3] 켄트벡의 익스트림 프로그래밍이라는 책에 보면 재확인(Double Checking) 원칙이 소개됩니다. 이 원칙은 문제를 해결할 때 전혀 다른 방법 두 가지로 각각 문제를 해결한 후에 결과를 비교해 보아 결과의 정확성을 보장하는 방법입니다. 마찬가지로 개발자는 개발자의 관점에서 QA는 QA의 관점에서 각기 다르게 검증을 수행한다면 좀더 정확한 검증을 할 수 있을 것이라 생각합니다.

수정 이력
2010/05/07 : 이 주제가 여러 편에 걸쳐 게시되었기 때문에 내용이 중복되지 않고 읽는이가 부드러운 흐름을 타게하기 위해 내용을 다소 수정합니다.

WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
최근 리팩토링 경험담이라는 시리즈 글을 쓰고 있습니다. 해당 시리즈 글의 흐름상 이 글의 내용이 부분적으로 들어가게 되어 아래 글을 해당 문백에 맞도록 약간의 수정을 하고 이동시키게 되었습니다. 원래 글의 내용은 취소선을 그어 남겨놓았으며, 내용은 거의 유사하오니 가능하면 아래 링크를 통해 해당 글과 관련 글을 읽어보시기를 추천드립니다. 불편을 드려 죄송합니다.

이동한 주소 리팩토링 경험담 #8 - 검증시점을 앞당기기 위한 빠른 실패

올해 초 저는 서버에서 발생하는 NullPointerException를 수정하는 업무를 하게 되었습니다. 로그를 보니 다양한 상황에서 다양한 형태로 NullPointerException이 발생하고 있었습니다. 그런데 업무을 진행하며 문제를 분석하다보니 그동안 어렴풋이 생각하던 부분이 좀더 명확해졌고 저는 이번 글에서 당시 했던 생각을 나눠보고자 합니다.

아래는 오류의 원인을 찾고있는 한 개발자의 가상사례입니다.
어느날 한 개발자가 웹 애플리케이션의 오류로그를 살펴봅니다. 그런데 데이터베이스에 나이를 저장하는 쿼리 부분에서 제약조건위배 오류가 발생하고 있습니다. 오류에 대해 자세히 살펴보니 나이 필드에 NOT NULL 제약이 걸려있음에도 Null 값이 입력되고 있다는 내용입니다. 곧바로 쿼리 부분에 문제가 있나라는 생각이 머리에 스칩니다. 소스를 재빨리 찾아 쿼리에 값을 넣어주는(Binding) 부분을 자세히 살펴봅니다. 그런데 큰 문제가 없어보입니다. 자연스럽게 비즈니스 레이어(Business Layer)를 살펴보게 됩니다. 혹시 나이 부분에 대해 뭔가 다루는 부분이 있나 자세히 살펴봅니다. 하지만 특별한 것을 발견하지 못합니다. 마지막으로 프리젠테이션 레이어(Presentation Layer)를 살펴봅니다. 그리고 프리젠테이션 레이어에서 나이 값이 잘 들어왔는지에 대한 검사를 하고 있지 않다는 것을 발견합니다. 거의 이 부분이 원인일 것이라 생각하지만 확신할 수는 없습니다. 왜냐하면 프로그래밍에는 너무 다양한 상황이 있다는 것을 알고 있기 때문입니다. 

2010/02/18 추가 
위의 경우는 오류로그가 Stacktrace를 포함하지 않는 경우에만 유효한 이야기입니다. 왜냐하면 Stacktrace를 볼 수 있다면 원인을 금방 알아낼 수 있기 때문입니다. 따라서 좀 억지스럽지만 Stacktrace를 찍지 않았다고 가정한 경우로 생각하시고 본래 전달하고자 하는 의미에 집중해주시면 좋을 것 같습니다.

위의 예를 통해 저는 두 가지 문제점을 봅니다. 첫 번째는 개발자가 원인을 조사하기 위해 여러 파일들을 살펴보아야 했다는 점입니다. 두 번째는 시간을 들여 여러 파일을 살펴보았음에도 불구하고 명확한 결론이 아닌 거의 확실한 추정 정도의 수준에서 조사를 끝낼 수 밖에 없다는 것입니다.  

여기서 위 사례에 한 가지 가정을 더해보겠습니다. 마지막에 개발자가 추정한 것이 실제원인이였다는 가정입니다. 이 가정 하에서 보면 위와 같이 일을 어렵게 만든 원인을 알 수 있습니다. 바로 '오류 희석'입니다.

널리 사용되거나 공식적인 용어는 아니지만 오류 희석은 시간 혹은 공간을 지남에 따라 오류가 본래의 모습을 점점 잃어버리는 것을 뜻합니다. 위 사례의 경우 근본 원인은 사용자가 나이를 입력하지 않았다는 것입니다. 하지만 실제적으로 문제는 프리젠테이션 레이어와 비즈니스 레이어를 지나 데이터베이스에 질의하는 부분에서 전혀 다른 모습으로 발생하였습니다. 그 결과로 개발자는 문제를 찾기위해 문제가 발생한 지점 까지 도달할 수 있는 모든 경로를 역추적해야 했습니다. 

그렇다면 해결책은 무엇인가요? 해결책은 무척 간단합니다. 바로 프리젠테이션 레이어에서 나이가 정확히 들어오는지를 검사하고 만약 나이가 정상적으로 들어오지 않는다면 엄격하게 예외처리를 해주면 됩니다. 사용자에게 '나이를 입력해주세요.'라는 문구를 보여줄 수도 있고, 바로 에러를 발생시켜 처리를 중지할 수도 있습니다. 이렇게 처리한다면 문제가 발생했을 때 사용자든 개발자든 문제를 정확히 알 수 있습니다. 특히 개발자가 에러로그를 보았을 경우 개발자는 소스 파일을 탐색하거나 추정을 할 필요가 없습니다. 왜냐하면 에러로그 그 자체만으로도 무슨 문제인지 너무나도 명확하게 알 수 있기 때문입니다.

Fedex에는 1-10-100 원칙이라는 것이 있다고 합니다. 간단히 설명하자면 문제를 조기에 처리하지 않으면 처리비용은 점점 증가한다는 것입니다. 저는 소프트웨어 개발의 많은 부분에서도 동일한 원칙이 적용된다고 봅니다. 문제가 발생했을 때 그 문제가 시간 혹은 공간을 지나기 전에 가능한 빨리 인지하고 처리하면 보다 낮은 비용으로 처리가 가능하지만, 그렇지 못했을 경우에는 위 가상사례와 같이 더 많은 비용이 필요하게 되는 것입니다. 특히 S/W분야에서는 추구하는 방향 관점에서 보았을 때 빠른 실패(Fail-Fast)가 Fedex의 1-10-100 원칙과 유사점을 가집니다. 좌측 링크가 걸린 위키피디아 내용에서 직접적으로 언급되지 않았습니다만, 필요한 곳에서 적절히 사용된 빠른 실패는 많은 비용을 줄일 수 있을 것입니다.

하지만 주의해야 할 점은 모든 곳에서 빠른 실패가 필요하지는 않다는 점입니다. 때로는 문제 혹은 결함을 허용하는 것이 매우 중요한 일인 경우가 있습니다. 예를 들어 포털의 메인화면을 생각해볼 수 있습니다. 포털의 메인화면은 매우 다양한 구성요소로 이루어져 있습니다. 그런데 그 중 우측 하단 쇼핑 정보를 가져오는 부분에 문제가 생겼다고 가정을 해봅시다. 이 경우 화면을 보여주기 위한 모든 처리를 중지한 후 화면을 표시하지 않는 것 보다는 그 부분을 제외하고 다른 부분은 정상적으로 보여주는 것이 현명한 판단일 것입니다. 

2009/05/06 ~ 2009/12/02




'

WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

,