본문으로 바로가기

이정표(사진 @Pixabay)



오래된 이야기다.

이 이야기를 꺼낸 이유는 이제는 빛이 바래져서 다칠 사람이 없기 때문이다.

하지만 "서버개발자"가 생각해볼 교훈은 아직 많다.


이 글은 SI프로젝트만 뛰다가 스타트업에 처음 들어가는 사람들 이야기다.

또는 신규구축만 하던 사람들이 개발운영의 세계에 첫발을 내디딜 때 이야기다.

아름다운 세상에 있다가, 예외투성이인 현실세계와 처음 맞딱뜨렸을 때의 이야기다.


신규구축은 "훌륭한 건축가"가 필요하지만, 유지관리는 "훌륭한 해결사"가 있어야 한다.

규제세상은 Rule로 옮길 수 있지만 정글은 그렇지 않다. 온통 지맘대로다.


자사매입의 법칙

자사매입이란, 판매자가 자기 상품을 되사는 것을 말한다.

도매가격이 아니라 소매가격으로 다시 산다.

그래서 유통비용은 돌려 받을 수 없다. 손해를 보는 것이다.

왜 이런 일을 할까?


KPI (Key Performance Indicator) 때문이다.

회사는 매년 매출이 조금씩 늘어야 한다.

그래서 매년 매출목표를 높게 잡는다.

길게 이야기하기 어려우니 우선 넘어가자.


연간 매출목표를 세우고 파트별로 목표를 나눈다.

그리고, 또 월별로 나눈다.


만일 10 개의 영업부서가 1,000 억을 벌어야 한다면,

각 부서는 한 달에 8.3억 정도 매출목표를 할당 받는다.


목표를 채우면 높은 고과를 받고 못 채우면 반대가 된다.

낮은 고과를 오래 받으면 해고 확률은 높아진다.



회사별로 차이가 있겠지만, 이 방법은 대부분의 회사들이 사용하고 있는 전통적인 영업방식이다.


오래전 이통사는 자사폰에서 폐쇄형 포탈 Walled Garden을 운용했다.

벨소리 배경화면 등, 각 카테고리별로 담당자가 매출목표를 할당받았다.

하지만, 각 담당자가 이 목표를 보장할 수 없다.

소비자가 얼마나 살지 알 수 없기 때문이다.


위험의 전가


그래서, 입점 상위업체를 불러 숙제를 나눈다.

예를 들어 월 10억 정도의 목표를 받으면 상위 10개 업체를 불러,

각 업체가 월 1억원씩 매출목표를 나누어 간다.

만일 매출을 채우지 못하면 … 생략한다.



잘 팔리면 문제가 없지만, 대부분 그렇지 않다.

소비량이 월별로 차이나기도 하지만, 목표치가 매년 높아지기 때문이다.


몇 가지 방법이 있다.

할인 이벤트를 벌여 대대적으로 홍보를 한다.

아니면, 소정의 대가를 주고 알바들에게 다운받게 한다.


컨텐츠 요금+알바 요금이 들어간다.


아니면, 그냥 깔끔하게 다운 받는 프로그램을 만든다.

제일 간단하다. 일을 크게 벌일 필요도 없다.

문제는 여기서 발생한다.

대부분 부족분이 어느정도 확인되는 월말에 프로그램을 돌리기 때문이다.


기술문제의 대두


그래서, 여러 업체가 API를 부르다 보니 호출패턴이 DDOS 공격처럼 나타난다.

매월 말이나 주말이 되면 서버가 죽는다.

이 문제는 기술적으로 이렇기 때문에 일어난다.



장애. 트래픽 폭주로 서버 다운


기술적으로는 트래픽의 인입속도가 처리속도보다 빠르기 때문에 생긴다. 

트래픽이 들어오면 서버프로그램은 이를 처리하기 위해 메모리 등을 할당하는데,

처리속도가 느려서 서버자원이 Full 이 차는 것이다. 


물론 폭발적인 인기 때문에 서버다운이 일어날 수도 있다. 

그런 거라면 환영할만한 일이다. 장사가 잘되는 거니까. 

그러나, 특정업체 때문에 다운되는 건 아니다. 

매출을 일으킬 정상 사용자들을 괴롭히는 것이다.



1차대응. 하드웨어 움직임을 관찰.


이 문제를 해결하기 위해 몇가지를 살펴보아야 한다.



- CPU, Memory는 놀고 있는데 Disk 가 바빠서 처리속도가 늦는가?

- CPU, Disk 는 놀고 있는데 Memory 가 바빠서 처리를 못하는 건가?

- Disk 와 Memory는 놀고 있는데, CPU가 바쁜 건가?



하드웨어를 관찰하는 것은 소프트웨어가 어떻게 움직이는지 살펴보기 위한 것이다. 

참고로, Java 는 JVM 내에서 연산을 처리하기 때문에 OS 의 CPU는 놀고 있는 것처럼 보일 수도 있다. 

그래서 이건 전문 툴로 찍어봐야 한다.



Disk 가 바쁜 것은 HDD의 속도나 I/O 카드의 전송속도 문제일 수 있다.


CPU가 바쁜 것은 불필요한 반복 연산(For Loop)이 많다는 뜻이다. 

메시징 기반으로 바꾸면 좀 나아지긴 하는데, 

메시징 기반은 Queue 설계가 복잡하게 들어가기 때문에 난이도가 많이 높아진다.



이런 걸 살핀 후에는 “소스코드”를 뜯어보게 된다. 

왜냐하면, 하드웨어는 뭐 손댈만한 부분이 없기 때문이다. 

그래서 서버 프로그램을 트래픽 패턴이나 물리적 하드웨어 성능을 감안해서 튜닝해야 한다.



2차대응. 튜닝 포인트 진단 및 도출


(1) 트랜잭션이 너무 무겁다.


트랜잭션이 DB나 유관 시스템을 많이 다녀온다면, 아무래도 응답시간을 0.1초 이내로 줄이기 힘들다. 

그래서 호출 유입이 0.1 초 이내로 몰리면 응답이 밀릴 수 밖에 없다.



자연적인 트래픽이라면 자연스러운 짬들이 곳곳에 생긴다. 

하지만, 인위적 트래픽이라면 안 그렇다. 

보통 쉬지 않고 트래픽이 발생된다. 

그러면 Queue Memory가 Full 이 되면서 무한 연결 대기 현상이 일어난다.



트래픽이 무겁다는 것은 하드 디스크의 기록 작업이 많다는 뜻이다. 

하지만, 잘못 짠 게 아니라면 이 문제는 쉽게 개선되기 힘들다. 

쓸 걸 안 쓸 수가 없기 때문이다.


"과금 트랜잭션"들은 이 업보를 벗어나기 힘들다.


(2) Queue Memory 가 너무 작다.


서버 시스템을 설계할 때 Queue는 필수이다. 

그런데, Queue Memory가 작게 할당되어 있을 수 있다. 

C 라면 소스만 보면 되지만, Java 는 JVM 까지 살펴 봐야 한다.

JVM 이 가상 머쉰이라 메모리 할당 한계가 있기 때문이다. 

C 라면 OS 변수들을 들여다 볼 경우도 생긴다.


하지만, Queue Memory를 늘려도 이 문제해결이 안된다. 

업체는 신나서 더 가혹하게 프로그램을 돌리기 때문이다. 

단지 장애시작 시간을 조금 늦추어줄 뿐이다. 

하지만, 자연 트래픽이라면 괜찮다. 

대부분 늘었다 줄었다 하기 때문이다.



(3) 같은 서버를 쓰고 있다.


문제는 업체 트래픽 때문에 일반 사용자가 접속장애를 겪는 것이다. 

그렇다면 업체전용으로 서버를 분리하는 방법이 있다. 

독립 도메인을 주고 업체들이 자사매입을 거기서 처리할 수 있도록 배려하는 것이다. 

엉뚱하지만, 가장 쉽고 빠른 방법이다. 

다만 업체들에게 이 서버를 쓰라고 알려줘야 하고 주의점을 일러줘야 한다. 

한달내로 교육가능한 방법이다.


(4) 그외...


정말 초보자가 짜거나 악의적으로 짠 게 아니라면 소스코드는 대부분 잘못 되어 있지 않다. 

다만, 사업 확장에 따른 기능확장, 구조개선이 안되어 있는 경우가 많다. 

그래서 대부분 옵션 하나 고치는 걸로 해결되지 않는다. 

사람의 행동이 시스템의 예측을 벗어나는 것이다.



문제해결. 어떻게 대응할까?


네이버나 Daum 같은 포털이라면 고민할 필요가 없다. 

DDOS 공격으로 생각하고 차단하면 된다.



하지만, 쇼핑몰들은 그렇지 않다. 각 호출이 과금트래픽이다. 

프로세스가 죽어서 중간에 끊어지면 정산데이터가 틀어진다. 

재수 없으면 누락분을 찾기 위해 그 날 모든 트래픽을 대조해야 할 수도 있다. 

야근이 디폴트가 된다. 

그래서 함부로 서버 프로세스를 내리면 안된다.



정책적으로 못하게 하면 좋지만, 당장 해결될 문제는 아니다. 

특정 트래픽이 식별되어도 막을 수는 없다. 

sleep을 충분히 주거나 짬짬이 돌리면 좋은데 그렇게 강제할 수도 없다.



이래도 안되고, 저래도 안된다. 

그럴 땐, 복잡한 사안을 단순화 시키는 것이 좋다. 초점을 단순화시키면 집중력이 높아진다.


당시 사업팀을 찾아가 문제현상을 공유했다. 

기술적 접근만으로는 한계가 있다는 것도 말했다. 

선택가능한 방안들을 몇 개 말했다. 

본질적인 해결방안들도 말을 했다. 

그리고, 함께 머리를 맞대어 대응책을 함께 마련했다.


교훈

시스템을 벗어나는 사람은 늘 있다.


IT사업에서 현실문제는 서버나 앱의 문제로 나타난다. 

논리오류이기 때문이다. 문제가 있으면 100% 나타난다. 

그래서 평소 모르던 것을 새로 정리해야 한다. 

제휴 사업이나 플랫폼 사업은 이런 경우가 더욱 많다.


"자사매입의 법칙"은 "음성적 위험전가"의 대표사례이다. 

Rule에서 벗어난다. 이런 크고 작은 사례는 늘 우리 주변에 있다. 

반면 소프트웨어는 Rule의 세계이다. 

그래서, 현실세계는 늘 "예외 덩어리"들이다.


현실세계는 불완전하다. 그런데, 시스템은 그걸 수용해야 한다.


그래서 서버 문제는 대부분 다자간의 문제이다. 

여러 이익단체의 이해가 얽혀 있다. 

그런데, 이런 공동의 문제는 아무리 해결책이 옳아도 혼자 풀면 안된다. 

부족하고 못나고 준비되지 않는 업체들이 언제나 존재하기 때문이다.


갑작스러운 움직임은 선의의 피해자를 만들어 낸다. 

기다려줄 필요가 있다. 

부족한 채로 마무리 지을 때도 있다. 

중요한 건 문제가 재발되지 않아야 한다. 

덮어둔 문제는 항상 바쁠 때 다시 터진다.


문제해결능력은 개발능력이 아니다. 

"정해주세요."라고 말하지 말자. 

그건 개발자를 구현자로 국한시키는 말이다. 

개발자로부터 책임감을 분리해낸다.


직접 개발자가 책임의식 없이 프로그램을 만드는 건 무서운 일이다. 

세상이 혼란스러워진다. 

내가 알고 있는 대안들을 제시해보고 여러 사람과 토의하자. 

나는 개발자들이 그렇게 일했으면 좋겠다.




댓글을 달아 주세요