튜닝이론

JAVA/framework 2008. 4. 8. 18:12
성능 튜닝에 관한 글을 요청받고 어떤 글을 쓸까, 과연 글을 쓸 만한 기술이 있을까, 쓴다면 독자들에게 어떤 이야기를 들려줄 것인가를 생각하게 되었다. 엔지니어적 관점에서 성능이라는 주제는 고도의 기술과 논리적 사고를 요하는 흥미로운 분야이지만, 한편으로는 방대한 배경 지식을 요하는 분야이고 체계적인 방법으로 접근하고 논하기에도 힘든 분야이다.

물론 성능 튜닝 분야에서도 IT 엔지니어의 양적인 팽창과 인터넷의 혁명으로 특정 솔루션 튜닝 기법과 실무 사례들은 주위에서 쉽게 구할 수 있다. 그럼에도 불구하고 끊임없이 성능상의 문제가 발생하는 이유는 무엇인가? 기본적인 솔루션의 튜닝 지식에도 불구하고 실제 튜닝을 할 수 없는 이유는 무엇인가?

필자의 경험으로는 성능에 관한 이해 부족과 문제를 체계적으로 해결할 수 있는 방법론의 부재라고 생각한다.

필자는 또 한번 고민에 부딪혔다. 바로 방법론과 기본 지식 중 어떤 분야를 이 글에서 이야기할 것인가를 고민했고, 결과는 기본 지식을 이야기하기로 결정했다.

그 이유는 “테스팅은 방법론적 접근이 가능하지만 튜닝은 예술”이라는 격언과(섣부른 접근보다는 기회가 주어진다면 진지한 접근을 하고 싶다. 책 한권 분량은 되지 않을까?) 기본 지식에 관해 다시 한번 음미하는 기회를 가지는 것이 ‘왜 튜닝을 하는가?’란 이 글의 화두와도 어울린다고 생각했으며, 무엇보다 중요하다고 생각하기 때문이다.

필자가 튜닝에 관해 조금 안다고 자부하던 시절, 다음과 같은 충격적인 질문을 받았다. “시스템을 모니터링할 때 왜 CPU 사용량이 70~80%일 때 CPU 병목이라고 하나요? 50%도 아니고 60도 아니고 70~80%인 이유는 무엇인가요?” 이러한 질문에 필자는 그 당시 어물쩡 넘어갔지만, 한 동안 “내가 성능을 정말 이해하고 있는 게 맞는 것일까”하는 자괴감을 안겨 주었다.

필자가 즐겨보는 ‘CEO 익스체인지’라는 텔레비전 프로그램에서 헤드헌팅 회사의 CEO는 다음과 같은 질문을 헤드헌팅 대상자에게 주로 건넨다. “당신이 자기 자신에게 가장 큰 오해를 하고 있는 것은 무엇인가?” 이제 우리가 이러한 질문을 자신에게 물어봐야 할 시점이 된 것 같다. “당신이 성능에 관해 가장 큰 오해를 하고 있는 것은 무엇인가?”

에피소드 1. CPU 사용량 80%의 함정
왜 80인가에 관한 의문을 풀기 위해서는 다소 딱딱한 그렇지만 재미있을 수도 있는 큐잉 이론(Queueing theory)이라 불리는 수학적인 이야기를 하기로 하자.


<그림 1> 큐잉 이론

<그림 1>은 시스템의 상태(state)를 서비스 요청(request)의 개수로 그린 그림이다. 서비스 요청 개수의 예로는 CPU 자원인 경우 CPU 할당을 기다리고 있는 프로세스의 개수이며, 웹서버의 경우 사용자로부터 요청된 URL의 개수라고 할 수 있다. 원으로 표시된 상태는 서비스 요청이 K일 경우 시스템의 상태를 표시한다. λ는 새로이 발생되는 요청 개수이며, μ는 처리된 요청 개수로서 단위는 request/sec이다.

새로 발생되는 서비스 요청과 처리된 요청에 따라 시스템의 상태는 변화하게 된다. 바운더리로 표시된 영역은 새로이 발생된 요청의 개수와 처리된 요청의 개수가 균형을 이루는 경계들을 표현하고 있으며, 이러한 상태는 ‘operational equilibrium’이라 한다.

‘operational equilibrium’에 관심을 가지는 이유는 옆의 그림과 같이 설명될 수 있다. 만약 flow-in이 flow-out보다 지속적으로 많은 불안정한 관계가 지속될 경우 댐은 붕괴된다(컴퓨터 시스템의 경우 크래시 또는 다운될 것이다).

우리는 댐이 붕괴되는 시점을 모델링하고 싶은 것은 아니므로, 특정한 시점에서 flow-in과 flow-out이 균형을 이룬다고 가정할 경우 시스템의 상태는 다음과 같다(몇 가지 가정이 더 있지만 이 글에서는 생략한다. 더 자세히 알고 싶은 독자는 큐잉 이론을 참고하기 바란다).

P0는 시스템이 서비스를 하고 있지 않는 상태를 의미하므로 시스템의 사용량은 다음과 같다.
시스템 상에 존재하는 요구(requests) 개수의 평균 값은 다음과 같다.

시스템의 평균 응답시간을 사용률과 서비스 시간으로 표현하면 다음과 같다.
T는 단위시간당 처리량(troughput)을 의미한다. Little‘s law에 따라 N=TR로 표시할 수 있는데 그 의미는 단위 시간당 시스템에 존재하는 평균적인 요청의 개수는 단위 시간당 처리량과 서비스 시간의 곱과 같다는 것이다. 단일 요청의 평균 서비스 시간을 S=1/μ이라 가정한다. 즉, 1초에 2개의 요구가 처리되면, 평균적인 서비스 시간은 0.5초라고 가정할 수 있다. S는 다음 그래프에서 실제 상수로서 작용하게 된다.


<그림 2> 사용량과 서비스 시간의 상관관계

<그림 2>에서 볼 수 있듯이 응답 시간은 사용량(utilization)의 임계값을 지나게 될 때 급격히 증가하게 된다. 사용량의 임계값은 이론적으로는 80% 내외에서 형성이 된다(실제 시스템에서 임계값은 여러 가지 복합적인 요인이 작용하게 된다). 따라서 CPU 사용량이 80%를 초과하면 CPU로 인한 반응 시간(response time)이 발생될 수 있다.

복잡한 공식을 살펴봤으니, 한 가지만 더 생각해 보기로 하자. 흔히 튜닝과 관련된 책을 읽어 보면 CPU 부분에서 큐(queue)에 있는 프로세스의 개수가 CPU당 약 4개 이상일 경우 CPU 병목이라고 한다. 그 이유에 관해 생각해 보라(물론 대부분의 퀴즈가 그렇듯 과도한 힌트을 주기로 한다. 공식을 음미해 보라). 그런데 CPU 사용량이 80% 이상이거나 CPU 큐에 대기하고 있는 프로세스의 수가 4개 이상일 경우 CPU로 인해 성능 저하가 발생되었다라고 말할 수 있는가?

우리가 CPU 사용량이 80%이거나 CPU 큐에 있는 프로세스의 수가 4개 이상일 경우 병목이라고 판단한 근거는 무엇인가? 바로 응답 시간의 급격한 저하이다. 그런데 실제 시스템에서는 응답 시간의 급격한 증가는 시스템에 가해지는 부하의 특징 및 각 요청을 처리하기 위한 리소스들(CPU, 메모리, 디스크…)의 사용량의 차이 등에 따라 병목을 나타내는 임계점은 크게 변하게 된다.

예를 들어 하나의 요구를 처리하기 위해서『1/100초의 CPU 사용 → 1/50초의 디스크 사용 → 1/100초의 CPU 사용』을 필요로 한다고 하자(편의상, context switch 시간은 0이라고 가정한다). 단위 시간당 50개의 요청이 발생한다고 가정할 경우 CPU 사용량은 100을 유지하고, 대기하고 있는 프로세스의 개수는 49개를 유지하지만 요청의 수행시간은 저하되지 않는다.

실제로 CPU 사용량이 90% 이상에서 10개 이상의 프로세스가 대기하고 있어도 웹서버의 로그를 분석해 보면 응답 시간이 크지 않은 경우가 많이 발생한다. 따라서 다음과 같은 접근 방법이 올바르다고 할 수 있다.

시스템에 접수된 서비스 요청들의 수행 시간이 고객이 요구한 시간보다 과도하게 길어진 상황이 발생해 시스템 상황을 모니터링해 보니 다른 리소스(메모리, 디스크, …)들은 정상적으로 작동되는데 CPU의 사용량이나 큐에서 대기하는 프로세스의 개수가 과도하게 커서(통상적인 임계값은 무의미할 수 있다) CPU를 증설하였더니 문제가 해결되었다. 그러므로 CPU 병목으로 인한 시스템의 병목이 발생되었다.

성능 관점에서 리소스의 사용량과 반응 시간의 관계에서는 반응 시간이 우선한다. 다음과 같은 추가 질문으로 시스템의 모니터링 값을 볼 경우를 생각해 보자(역시 성능에 관한 진지한 이해가 우선 선행되어야 한다는 것을 강조한다).

“시스템 성능의 기준이 응답시간이 아닌 처리량이라면 임계값과 성능과의 상관관계는 어떻게 될 것인가?”, “Context time이 10,000 이상일 경우 성능 저하가 발생된다고 알려져 있다. 그 근거는 무엇일까?”

에피소드 2. 모니터링을 통해 시스템을 이해할 수 있다?
이제 시스템 모니터링시 보여지는 값들에 관해 생각해 보기로 하자. 다음과 같은 질문을 받았다고 가정하자. “CPU 사용량은 크지 않는데 CPU 사용을 대기하고 있는 프로세스의 개수는 많은 현상이 발생되고 있다. 그 원인은 무엇인가?”

상식적으로 생각해 볼 때 CPU 사용을 대기하고 있는 프로세스의 개수가(lock이 없다고 가정한다면) 1개 이상이면 CPU 사용은 100% 이상이어야 할 것이다. 이 질문에 답하기 위해서 우리는 성능을 모니터링하기 위해 사용하는 명령어가 어떻게 만들어져 있는지 생각할 필요가 있다.

운영체제(OS)는 주기적으로(보통 1/100초마다) 시스템의 상황을 체크해 성능 관련 정보를 저장한다. 우리가 사용하는 iostat, vmstat, sar와 같은 명령어는 OS상의 성능 관련 데이터에 접근해 해당하는 정보를 읽어와 적절히 가공한 후 사용자에게 보여준다.

vmstat을 사용해 CPU 사용량을 모니터링할 경우 CPU 관련 큐에 관련된 정보는 /usr/include/sys/sysinfo.h에 정의되어 있는 sysinfo 구조체를 사용해 OS에 저장된 CPU 사용 관련 정보를 읽어 온다.

typedef struct sysinfo { /* (update freq) update action */
ulong updates; /* (1 sec) ++ */
ulong runque; /* (1 sec) += num runnable procs */
ulong runocc; /* (1 sec) ++ if num runnable procs > 0 */
ulong swpque; /* (1 sec) += num swapped procs */
ulong swpocc; /* (1 sec) ++ if num swapped procs > 0 */
ulong waiting; /* (1 sec) += jobs waiting for I/O */
} sysinfo_t;

앞에서 보이는 CPU 큐에 관련된 정보는 1초에 한번씩 업데이트가 된다. 솔라리스의 경우 CPU 사용률(user, sys, idle)에 관련된 정보는 kstat이라는 구조체를 이용해 가져오는데, 관련 정보는 OS가 주기적으로(보통 1/100으로 설정되어 있다.

1초 단위로 계산한다면 우리가 표시하는 %와 일치하는 사용률을 보이게 된다) 검사해 CPU를 점유하고, 사용되는 프로세스가 존재하면 커널과 사용자 프로세스로 구분해 해당 CPU 사용량을 1 증가하고 프로세스가 존재하지 않는다면 변경하지 않는다. vmstat을 사용해 5초마다 CPU 사용량을 본다면 kstat의 CPU 사용량을 5로 나누어 화면에 표시하게 된다.

정리하면 vmstat에서 표시되는 CPU 사용량은 1/100초로 샘플링이 되는 값을 사용하고, CPU 큐에 관련된 정보는 1초마다 업데이트 되는 정보를 사용한다. 다음과 같은 경우를 생각하자.

0초에 CPU 큐에 대기하는 프로세스의 수를 10개라고 하고 각 프로세스는 1/100초 후 종료된다고 가정하자. vmstat을 사용해 1초 간격으로 모니터링을 한다면 결과는 CPU 큐에 대기하는 프로세스의 개수는 10으로 CPU 사용량은 10%로 나타날 것이다.

이번에는 1/100초에 CPU 큐에 대기하는 프로세스의 수를 10개라고 하고 각 프로세스는 1/100초 후 종료된다고 가정하자. vmstat을 사용해 1초 간격으로 모니터링을 한다면 결과는 CPU 큐에 대기하는 프로세스의 개수는 0으로 나타날 것이며 CPU 사용량은 10%로 나타날 것이다.

실제로 시스템 모니터링은 CPU, 캐시, 메모리, 디스크, 네트워크 부분에서 광범위하게 이루어지며, 사용자의 요청들의 합인 워크로드의 성격 또한 다양하므로 모니터링 값을 정확히 이해하는 것은 생각보다 난해한 일이 될 수 있다.

앞의 예와 같이 모니터링 명령어를 통한 값을 통해 시스템의 상태를 파악하기 위해서는 모니터링 명령어의 작동 방법에 관한 정확한 이해와 시스템에 가해지는 부하의 특징(workload)에 관한 이해가 필수적이다.

에피소드 3. 만병통치 쓰레드?
필자는 몇 년 전 다음과 같이 말하는 업체 관계자를 만난 적이 있다. “본사의 웹서버 제품인 X는 쓰레드 방식으로 작동되므로, 프로세스 방식으로 작동되는 아파치보다 뛰어난 성능을 보인다. X 웹서버는 대용량에서 더욱 뛰어난 성능을 보여준다. <그림 3>는 그것을 증명하는 벤치마킹 결과이다.”


<그림 3>벤치마킹 결과

<그림 3>에서 사용자가 600명인 구간에서 아파치의 성능이 급격히 저하됨을 보여주고 있다. 그 원인은 무엇일까?

일반적으로 쓰레드가 프로세스에 비해 성능상의 우위를 가지는 데, 그 이유는 context switch시 교체되어야 될 정보가 적기 때문이다. 벤치마킹의 결과를 볼 때 대용량의 부하에서 과도한 context switch로 인해 웹서버 X의 성능이 우수한 것으로 보여진다(물론 이렇게 단순하다면 필자가 쓰지 않았을 것이다). 진실은 무엇일까?

진실은 벤치마킹 대상 서버가 메모리 250MB의 워크스테이션이라는 것에서 출발한다. 아파치 프로세스의 크기를 0.5MB라고 하자. 접속하는 클라이언트가 증가함에 따라 아파치는 새로운 프로세스를 생성해 서비스를 하게 된다.
<그림 4>에서 성능이 급격히 저하되는 클라이언트 600의 환경에서 프로세스가 300개 정도 만들어 졌다고 가정하면, 150MB의 메모리가 필요할 것이다. 기타 프로그램이 사용하는 메모리의 양을 100MB 정도라고 한다면, 전체 메모리의 사용량은 250MB 정도가 될 것이고, 프로세스가 추가 생성됨에 따라 paging fault나 swapping이 일어남을 예측할 수 있다.


<그림 4>프로세스 vs. 쓰레드

현재 아파치가 운영되는 환경의 메모리는 대부분의 경우 2GB 이상의 메모리를 가지고 있으므로 이러한 상황은 발생되지 않을 것이며, 실제 운영시에도 웹서버 X와 아파치의 성능상의 차이는 크지 않을 것으로 예상할 수 있다.

자, 이제 조금만 더 생각해 보기로 하자. 쓰레드와 프로세스는 과연 성능상의 큰 차이가 나지 않는 것일까? 일반적으로 한 개의 서버에는 여러 솔루션이 설치된다. 이 경우 메모리는 아껴 써야만 하는 자원이 될 수가 있다. 또한 웹서버에 php, Perl과 같은 CGI 서비스나 웹 애플리케이션 서버(WAS)와의 연결을 위한 모듈이 추가될 경우 프로세스의 크기가 1MB 가까이 되는 경우가 있다.

이러한 상황은 메모리 부족이 발생될 수 있으며, 쓰레드 방식의 웹서버를 사용했다면 발생되지 않았을 성능상의 문제가 아파치에서는 발생될 수 있다. 물론 메모리를 증가시켜주면 대부분의 문제는 해결될 것이다.

이번에는 반대로 아파치에서는 발생되지 않았던 문제가 쓰레드 방식의 웹서버에서 발생된 경우를 생각해 보자. 필자가 수행한 SWAT 활동 중 아파치에서 쓰레드 방식의 웹서버로 교체한 후 클라이언트로부터의 요청이 증가함에 따라 웹서버가 다운되는 문제가 발생한 적이 있다. 우선적으로 시스템 설정을 조사했는데 별다른 문제점은 없었다. 웹서버의 로그를 조사한 결과 소켓이 열리지 않아 시스템이 다운되는 현상이 보였다.

바로 웹서버는 클라이언트 및 기타 솔루션과 통신하기 위해 소켓을 주로 사용하는데 유닉스에서 소켓은 파일로 인식됨으로 소켓이 열리지 않는다는 것은 프로세스가 열 수 있는 파일의 최대 개수와 관련된 설정에 문제가 있다고 추측할 수 있었다.

그런데 시스템 설정을 조사할 경우 해당 환경 변수가 적절히 설정되어 있었다. 혹시나 하는 마음에 운영자에게 환경 변수가 설정된 후 시스템을 재부팅한 적이 있느냐고 물어 보았더니 없다고 하였다. 바로 해당 환경 변수는 재부팅이 되었어야만 적용이 되는 변수였던 것이었다.

그럼 아파치에서는 왜 동일한 문제가 발생되지 않았던 것일까? 그 이유는 프로세스 방식에서는 각각의 프로세스가 각자 file descriptor를 관리하는데 반해 쓰레드 방식에서는 file descriptor를 공유하기 때문이었다. 즉 n개의 file descriptor를 m개의 쓰레드가 공유함으로 열 수 있는 파일의 개수가 실질적으로 감소하기 때문이다.

에피소드 4. 성능 튜닝 툴, 어디에 쓰는 물건인고?
솔루션의 성숙과 더불어 각종 툴의 도움으로 쉽게 시스템의 상황을 파악할 수 있게 되었다. 실제 WAS의 경우 관리와 성능 분석 도구가 주요 상품화되고 있으며, 오라클 DB의 경우 써드 벤더 도구들의 기능을 오라클 DB가 내장하는 수준으로 발전하고 있다.

엔지니어 특유의 고집으로 인한 모니터링 도구의 거부감에도 불구하고 실제 성능 관련 도구 사용의 작업 효율을 크게 향상시킬 수 있다. 이제 성능 관련 엔지니어에게 더욱 중요한 내용은 논리적인 사고 기반 위에 적절한 명령어와 성능 관련 도구를 이용해 시스템 성능을 분석하는 일일 것이다. 이제 각종 툴을 이용해 어떠한 방식으로 성능을 이해할 것인지에 대해 고민해보자.

전체 시스템의 성능을 분석하기 위해서는 시스템을 구성하는 각 컴포넌트(예 : OS, 웹서버, WAS, DB 등)들의 로그에 관한 이해는 필수이다. 로그에서 중요한 것은 에러, 요구량, 처리량, 그리고 각 요구를 처리하는데 걸린 수행시간이다. 이러한 정보를 이용해 전체 시스템을 구성하는 컴포넌트들 중 성능상의 문제를 유발한 컴포넌트를 발견할 수 있다. 필자가 참여하지는 않았지만 다음과 같은 경우가 있었다.

웹서버, WAS, DB로 이루어진 비교적 간단한 웹서버 구조였는데 성능 상의 문제로 시스템 오픈시 다운되었다. SWAT팀이 출동해 상황을 분석하고 각 솔루션별 튜닝을 마쳤지만 성능은 만족스럽게 향상되지 않았다. 단순한 HTML 파일을 이용해 웹서버에는 문제가 없다는 결론을 내렸고 DB를 이용하지 않는 애플리케이션을 이용해 WAS에도 문제가 없다는 것을 확인했다. 또한 DB를 이용하는 애플리케이션을 이용해 성능 저하가 발생됨을 확인했다.

그런데 DBA에게 문의한 결과 DB상의 로그에는 성능상의 저하가 발생됐다는 증거가 나타나지 않았다는 것이었다. 이제 DBA는 DB에는 문제가 없다고 주장하고 WAS 엔지니어는 WAS에는 문제가 없다고 하고 OS 전문가는 OS에는 문제가 없다고 주장하는 상황이 발생되었다. 그럼 문제는 어디에서 발생했을까?

문제는 해당 WAS의 JDBC 드라이버가 512Bytes로 데이터를 전송하는 것이었다. 이 경우 각 패킷의 헤더 정보의 비중이 과도하게 커져 네트워크 병목을 유발할 수 있다. 각 네트워크 노드마다 MSS(Maximim Segment Size)라 불리는 전송 가능한 최소 패킷 사이즈가 있는데, 네트워크 통신 초기에 auto-negotiation으로 단말 노드 간에 MSS가 설정된다.

문제는 단말 노드 사이의 네트워크 장비가 auto-negotiation을 지원하지 않는 경우 네트워크 장비는 이동시켜야 할 패킷이 자기가 처리할 수 없는 크기이면 패킷을 조각내고 합치는 작업을 해야 한다는 것이며 이는 성능 저하로 유발된다(조각내고 합치는 것도 불가능하다면 패킷을 손실될 것이다).

512bytes는 원시시대부터 지원된 가장 작은 패킷 사이즈이며 모든 네트워크 장비가 지원하고 있다. 친절하게도 JDBC는 모든 장비가 지원하는 512bytes로 데이터를 전송했지만, 현재 네트워크 장비를 고려할 때 512bytes는 헤더로 인해 너무나 낭비가 심한 크기의 패킷이다. 실제 이런 부분은 대단히 발견하기가 힘든 튜닝 사항이다. 역시 문제의 원인이 되는 컴포넌트 발견시에도 전산 환경에 대한 깊은 이해가 필요한 것 같다.

그럼 여기서 추가 질문. 웹서버상의 로그를 보면 전송된 데이터의 크기를 볼 수 있다. 웹서버 로그에 index.html이 1KB라고 기록됐다면 이는 실제 index.html 파일의 크기일까 또는 네트워크를 실제 사용한 크기일까? 만약 웹서버상의 index.html 파일이 1KB라면 네트워크를 점유하는 데이터의 크기는 얼마일까? 100Mbps의 네트워크를 사용한다면 1초동안 전송 가능한 최대 index.html은 몇 개가 될까?

유닉스 또는 다른 OS에서 제공하는 기본적인 기능 외에 사용자 편의를 위한 다양한 명령어를 ‘유틸리티’라고 한다. 성능과 관련되어 다양한 명령어가 있지만 앞에서도 언급했듯이 명령어에 관한 정확한 이해는 필수이다.

turss를 이용해 유닉스상에서 프로세스가 호출하는 시스템 콜을 이해할 수 있지만 이는 과연 튜닝에 얼마나 도움을 줄까(필자의 경험으로는 한번 뿐이었는데, OS상에서 환경 변수 설정은 정상으로 되었지만 패키지 형태의 솔루션이 시작되면서 setsockopt() 시스템 콜을 사용해 환경 변수를 변경함으로써 패키지가 정상적으로 작동되지 않는 경우였다).

crash를 통해 얻을 수 있는 정보는 무엇인가? Profiler를 통해 얻을 수 있는 정보는 과연 소스에 코드를 넣어 로그를 남기는 방법보다 좋다고 말할 수 있을까(필자의 경험으로는 소스에 로그 코드를 추가하는 방법이 효과적인 경우가 더 많았던 것 같다)? 유틸리티와 성능 관련 도구를 통해 우리가 얻을 수 있는 정보에 관한 정확한 이해는 성능 튜닝 작업을 위한 필수 지식이라고 할 수 있겠다.

필자는 개발자와 작업을 하면서(필자가 개발자이기도 하다) 각자가 작성한 코드를 서버에 설치하도록 하고 간단한 부하 도구를 이용해 성능을 분석하도록 한 적이 있다. 결과는 대 성공이었다. 부하 도구는 개발자가 사용하기에 어려움이 없었고 측정해야 할 요소(Max TPS)는 쉽게 이해할 수 있는 수준이었으며 개발자는 자기 자신의 소스 코드에 대해 성능 관점에서 진지하게 접근했다.

그리하여 필자가 생각하게 된 것은 성능 관련 툴의 발전을 개발 방법론상에 어떻게 접목시킬 것인가 하는 것이었다. clean room project나 XP와 같이 철저한 테스팅 수준으로 가지는 않더라도 개발자들이 자기 자신의 코딩에 관한 간단한 성능 검증을 직접 함으로써 얻을 수 있는 이익은 어떤 튜닝보다 효과적일 수 있다. SWAT가 코드를 직접 분석하기에는 시간이 너무나 걸리고 개발자들이 SWAT에 협조하기에 그들은 너무 바쁘다.

성능 튜닝의 현재와 미래
필자는 오라클, DB2, 그리고 이제는 너무나 일반화가 되어버린 WAS의 엔지니어를 만나면 농담 반 진담 반으로 “이제 성능 튜닝도 솔루션 자체가 스스로 하는데, 엔지니어도 몇 년 후에는 굶어죽겠군”이라는 이야기를 하게 된다.

이러한 이야기를 하게 되는 배경에는 무엇보다도 2000년대를 대표할 전산 환경으로 기억될 웹 기반 시스템의 각 솔루션(웹서버, WAS, DB)이 성숙기를 지남에 따라 기능이 안정화되고, 그에 따라 성능 부분에서도 일정 부분은 스스로 최적화가 되거나 별도의 튜닝이 없어도 웬만큼 버티는(?) 단계로 접어들었기 때문이라고 생각된다. 또한 해당 솔루션이 대중화됨에 따라 초·중급 수준의 엔지니어는 포화 상태를 이루고 있기 때문이다. 그러면 성능과 관련된 제품의 성숙도와 주요 업체들의 향후 방향성은 무엇일까?


<그림 5> 리얼타임 인프라스트럭처 기술의 Hype 사이클(출처:가트너 그룹)

<그림 5>의 Hype 사이클에서 세로축은 사람들의 기대치를 나타내며 가로축은 성숙도를 나타낸다. 기술이 시장에 처음 소개될 때 기대치는 실제 성숙도 이상으로 상승하게 되어 거품을 이루게 된다. 특히 서버 리소스 매니지먼트(server resource management)/워크로드(workload) 관리가 거품의 정점에 있다고 할 수 있다. 이후 사람들이 현실을 깨달음에 따라 기대치는 급속도로 냉각하게 되며, 제품(기술)이 시장에서 살아남는다면 기대치의 완만한 상승을 성숙도가 만족시키면서 안정화 단계를 이루게 된다.

현 IT 시장에서의 화두는(적어도 업체 입장에서는) 리얼 타임이라고 할 수 있는데, 업체들의 사업 방향과 역량에 따라 e비즈니스 온디맨드(on-demand, IBM), 어댑티브 컴퓨팅(Adaptive computing, HP), N1(썬)이라는 용어로 표현되기도 한다(각각의 내용은 사실상 조금씩의 차이가 존재하지만 공통된 목적은 동일하다).

리얼 타임이라는 용어는 가트너에서 주창한 용어인데, “기업이 원하는 전산 환경을 즉시즉시 제공해 준다”라는 의미이다. 물론 제공할 대상은 컨설팅을 포함한 광범위한 분야인데, 이 글에서 관심을 가지고 있는 성능과 관련된 인프라스트럭처 분야는 리얼 타임 인프라스트럭처(Real time infrastructure)라는 용어로 표현된다.


<그림 6> 자율적 컴퓨팅(Autonomous computing, 출처 : IBM)

인프라스트럭처 분야로 한정될 경우 리얼 타임의 의미는 기업이 원하는 “전산 환경의 리소스를 즉시즉시 제공해 준다”는 의미를 지니고 있는데, 이는 대부분의 설정이 자동화되고 문제 발생시 솔루션이 직접 해결하며, 스스로 최적화되고 보안이나 기타 외부의 이상 환경으로부터 스스로를 보호한다는 것을 나타낸다. 바꾸어 말하면 문제 발생시 엔지니어를 부르기 위해 며칠이 소비되고 해결하는 데 며칠이 걸린다면 리얼 타임이라 부를 수 없으며 이는 기업 운영에 치명적으로 작용할 수 있다는 것이다.

물론 과거의 많은 경험들로 미루어 볼 때 관련 업체들의 미사여구가 나열된 선언적 부분이 상당히 있겠지만, 가트너의 Hype 사이클을 보면 관련 기술의 대부분이 5년 이내에 성숙될 것으로 예측됨을 알 수 있다. 실제 이는 기본적인 전산 상식으로 유추할 수 있는 내용인데, 각 솔루션의 전문가들은 이미 시장에 존재하며, 인공지능 분야 중 전문가 시스템을 이용해 전문가들의 문제 해결 능력은 모델링 되어 솔루션에 추가될 수 있다.

물론 최고급 전문가들의 최고급 기술이 솔루션에 탑재되기는 힘들다. 그러나 전산 시스템을 운영하는 기업 입장에서는 자동으로 작동되는 솔루션과 향상된 컴퓨팅 파워 환경에서 초·중급 엔지니어의 고용에 심각한 회의를 하는 시점이 도래할 것으로 예상된다(물론 현재 부분적으로 일어나고 있는 상황이기도 하다. 유닉스와 비교할 때 윈도우 운영시 전문 엔지니어의 필요성이 감소되는 것은 엄연한 사실이 아닌가).

이와 같은 긍정적인(?) 방향에도 불구하고 시스템 오픈시 성능 문제로 인해 다운이 되는 현상이 반복되는 이유는 무엇일까? 여러 가지 해석이 가능하겠지만 필자의 견해로는 실제 성능은 개별 솔루션의 성능 튜닝 이상을 의미하는 상황에서 전체 시스템의 복잡도가 증가되기 때문이라고 생각된다.

성능 관점에서 볼 때 웹 환경만 하더라도 단순한 구성(웹서버 - WAS- DB)에서 여러 가지 솔루션(LDAP, 인증서, SSL, 방화벽, 바이러스 백신 등)이 혼재된 형태로 발전되고 있다. 클러스터링을 통해 데이터베이스의 성능은 높아졌지만 클러스터링된 노드간의 간섭을 줄이기 위하여 파티셔닝을 하기 위한 디자인 능력은 더욱 요구되고 있다.

응용 프로그램 개발시 컴포넌트나 프레임워크를 이용한 표준화를 통해 성능 관련된 많은 부분들이 미연에 방지되고는 있지만, 수준 있는 애플리케이션 아키텍처는 여전히 부족할 뿐만 아니라 시스템이 복잡해짐에 따라 표준화할 수 없는 부분이 증가되고, 여전히 개발 기간은 부족하고 방법론은 체계적으로 적용되고 있지 못하다.

요약하면 솔루션의 진화와 컴퓨팅 파워의 향상으로 개별 솔루션의 예술가적 튜닝 요구는 줄어들겠지만, 아키텍트적인 관점에서 전체 시스템의 디자인과 성능과 관련된 프로젝트 관리상의 요구는 증가될 것으로 예상된다. 엔지니어 입장에서는 높은 곳에서 전체 시스템을 전망할 수 있는 능력을 더욱 요구받게 된 것이다. 높은 곳으로 가기위해서는 체력과(기본 지식) 올바른 길(문제 해결을 위한 최선의 방법)이 필수적으로 필요함을 다시 한번 이야기 해 두고 싶다.

존재의 이유
필자가 접하게 된 최근 IT 환경의 가장 큰 변화는 고객이 무척 똑똑해졌다는 것이다. 그들은 단순히 서버를 증설해야 한다는 엔지니어 주장을 믿지 않을뿐더러(옛날에도 믿지 않았지만), 이론적 설명을 요구하기도 한다. 이러한 변화의 가장 큰 이유는 IT에 관한 ‘묻지마 투자’에서 ROI(Return Of Investment) 관점에서의 철저한 분석이 선행된 투자를 하도록 기업 환경의 경쟁이 심화되고 있다는 것이다.

필자가 만난 모 기업의 전산 담당자는 다음과 같은 말했다. “서버 증설을 위해 임원진에게 건의를 했더니 임원이 서버 증설을 해야 하는 이유를 논리적이거나 수학적으로 증명을 해달라고 한다. 나도 답답하다. 임원에게 CPU 사용량이 90%이므로 증설해야 한다고 해도 받아 들여지지 않는다. 전산 투자를 해야하는데 우리도 답답하다.” 결국 기존의 로그를 분석해 사용량의 증가를 예측하고, 시스템을 증설하지 않을 경우 예상되는 손실을 계산하고 이를 증설될 서버의 가격과 비교하였다.

물론 엔지니어 각자의 임무와 취향에 따라 앞의 상황에 대한 해석이 틀려지겠지만, 성능 관련 엔지니어에게도 단순한 파라미터 조작을 통한 솔루션 튜닝 이상의 무엇을 통해 각자의 존재 이유를 증명해야 될 시대가 도래하고 있는 것은 틀림없는 것 같다.

이 글의 결말을 어떻게 낼까 고민하다 다음과 같은 말이면 어떨까 생각하게 되었다. “제임스 고슬링이 자바를 개발했다고 하는데 설마 제임스 고슬링이 날 코딩했겠냐(물론 코딩을 못한다는 얘기가 아니다). 그가 자바를 개발하면서 무슨 일을 했을까를 생각해 봐야 한다. 그것을 통해 우리가 생각하는 엔지니어의 미래를 고민해 보자.”@

* 이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용입니다.

글 보관함

카운터

Total : / Today : / Yesterday :
get rsstistory!