[Developer] 전역변수

Developer 2020. 5. 28. 22:57

Simple한 얘기를 해보자. 

 

  • 전역 변수 - 파일 내 어디서든 접근 가능하며, 변하는 값(변수)

엄청나게 유용해 보인다. 소스 파일 내의 어디서는 접근이 가능하다니!! 

하지만

'변수'라는 상태가 문제다.

소스 파일내 어디서든 이 값을 변경할 수 있다는 것이다. 

 

만약 프로그램이 One Thread의 순차처리 방식이라면 당연히 문제가 없겠지만

Multi Thread일 경우 누가 어느 시점에 이 값을 바꿀지 모른다.

 

 

[ 프로그램 동작 전제 ]

  1. Non-Block Packet Receive로 지속적으로 메시지를 수신하여 동일 로직을 처리한다.
  2. 사용자는 1개의 세션을 통해 연결 후, 모든 Transaction이 끝날 때까지(즉, End 메시지를 전송할 때까지) 메모리에 데이터를 유지한다.
  3. 세션관리자는 사용자의 Transaction 진행 여부를 알 수 있다.
  4. 세션 연결 후, 첫 메시지 처리 과정에 사용자 정보를 구조체 배열 메모리(Context Index 기준)에 저장 후, 두 번째 이후 메시지 부터는 사용자 번호를 기준으로 Context Index를 가져와 사용자 정보를 조회/갱신 한다.
  5. Transaction 종료 시, 구조체 배열 메모리 및 세션 관리에서 데이터를 삭제한다.

위의 케이스는 전에 다니던 회사에서 겪은, 실제 운영 시스템에서 발생한 장애 상황을 심플하게 줄여서 정리한 것이다. (실제로는 훨씬..무지막지하게 복잡하다...)

한 시점에 여러명의 사용자가 지속적인 Transaction 처리 중인 상태가 될 수 있기 때문에, Non-Block 상태에서 여러 Transaction을 처리하는 프로그램의 세션, Context 관리란 정말 골치 아프다. 

 

A 사용자가 Transaction을 진행하고 있다. a라는 메시지를 시작으로 30번의 Context ID를 할당받고, b라는 메시지를 전달했을 때, 세션관리자가 A 사용자라는 것을 인지하고 30번의 Context ID를 알려주어 아주 빠른 메모리 접근으로 작업을 처리하도록 했다.

문제는 세션관리자가 Context ID를 'Global Index'에 넣어주고 Process #1은 이 값으로 메모리에 접근하게 되어 있었다는 것이다. (아마 처음 이 프로그램을 만든 사람은...a라는 메시지를 처리하는 함수와 b라는 메시지를 처리하는 메시지가 별도의 파일로 관리되고 있어 전역 변수를 선언해서 extern 명령어로 어디서든 접근하기 쉽게 하려고 했던것 같다.)

 

만약 A 사용자가 a 메시지를 처리하고 b 메시지를 전달후 b 메시지에 대한 함수를 타기 바로 전에 B 사용자가 전송한 새로운 a 메시지가 먼저 처리되면...? 

A 사용자의 b 메시지를 처리하기 바로 직전에 Global Index는 A 사용자의 Index 30에서 B 사용자의 Index 25로 변경될 것이다. 그럼 A 사용자의 b 메시지를 처리할 때는 당연히 Index 25에 접근하게 되어 잘못된 데이터를 처리하게 될 것이다.

 

이것이 얼마나 심각한 문제일지는 겪어본 사람은 알겠지...

거대한 운영 시스템에서 원인 분석만 꼬박 일주일을 잡아 먹은적도 있을 정도다. 

장애 이후 전역변수를 없애는 일 또한 엄청난 곤욕이다.

 

오늘부로 아래 3가지만 실천해 보자.

  1. 모든 전역'변수'는 제거한다.
  2. 변수는 반드시 함수의 Parameter(인자)로 넘겨줘서 사용한다. Call-by-Value든 Call-by-Reference든 상관없다.
  3. 전역으로 선언할 수 있는 것은 오직, 값을 변경할 수 없는 '상수'뿐이란 것을 명심하자.

 

다음에는 위 문제로 새로 만들었던 'Context 관리 라이브러리'를 포스팅 해봐야겠다.

'Developer' 카테고리의 다른 글

[Developer] Input Validation - 입력값 검증  (0) 2020.05.26
[Developer] 개발할 때가 좋았는데.....  (0) 2020.05.25
Posted by [ 브랜든 ]
,

Input Value. 즉, 프로그램 사용자의 입력은 정말 무궁무진하다.

 

이 사용자의 입력에 관해서는 CUI와 GUI는 확연히 큰 차이를 보인다.

 

GUI의 경우, 예를 들면 C# WinForm, HTML/CSS와 같은...

사용자의 입력 Value를 입력 받음과 동시에 제어할 수가 있다.

 

문자열일 경우 Text Box에 길이 제한을 두어 Max 길이 이상 입력이 되지 않게 한다든지...

ENUM의 값을 갖는 경우 Select Box를 만들어 한정된 값 내에서 사용자가 선택하게 한다든지...


이전 회사에서 쓰던 GUI 화면 예시

  •   PFX는 숫자만 입력이 될 것이며 최소 3자리, 최대 15자리까지만 입력이 가능하다.
  •   IDTYPE은 Select Box로 되어 사용자가 정의된 값들만 입력할 수 있다.
  •   DESC는 어떠한 문자도 입력이 가능하고 최대 20자까지만 입력할 수 있다.

하지만 CUI는 사용자가 입력하는 대로 무궁무진하게 입력 받는다.

CUI환경에서는 Input Data Validation(검증) 작업이 무엇보다 중요하며, 시스템 장애를 막을 수 있는 가장 첫번째 관문이다.


 

그럼 System의 어떤 모듈에서 이 작업을 해야 가장 효율적일까?

 

GUI의 경우를 보면 알수 있듯이...당연히 최초 입력값이 생성되는 시점이다.

이전 회사에서는 아래와 같이 하나의 시스템이 대부분 동일한 구조를 갖고 있었다.

 

TCP/IP를 통해 들어오는 특정 Protocol 형식의 패킷이 Application까지 전달되는 과정의 계층 구조

Input Data Validation 작업은 어디서 해야할까?

당연히 Stack 모듈에서 해야하는, 아니 Stack 모듈에서 구현되어야 하는 기본 기능중의 하나이다.. 

그래야 그 위에서 동작하는 모든 Application들이 사용하는 Value들에 대해 의심하지 않고 

사용할 수 있기 때문이다. 

 

Stack 모듈에서 걸러주지 않는다면....?

각각의 Application들이 실제 사용하는 값들만 직접 검증하면....?

만약 100개의 입력값이 있다고 가정해 보자. 하지만 각각의 Application들은 100개 중 일부(약 10개? 15개?)의 

서로 다른 값을 사용한다고 했을 때, 후자가 훨씬 적합해 보이지 않을까? 필요한 것들만 골라서 쓰면 전체적인 작업도 훨씬 줄어 들고.

 

약 20개의 Application이 Stack 위에서 동작한다고 했을 때, 물론 서로 다른 입력값들을 사용할 수 있지만, 일부 필수 값들(Mandatory)은 중복되서 사용할 수 있다. 마치 동일한 상위 클래스를 상속받은 클래스들 처럼....

그렇게 될 경우, Stack 모듈에서 1번만 검증하면 되는 작업을 20개의 Application이 똑같은 값을 다~ 검증하고 있는 셈이 된다. (5개라고 가정한다면...시스템 입장에서는 100개의 입력 값을 검증하는 셈이지 않을까? 다 같은 값인데...). 아무리 봐도 비효율적이다.

 

10년간의 경험적 측면에서의 핵심은 '실수를 최소화 할 수 있는 방향'을 선택하는 것이다.

실수가 없을것 같지...?만! 어디에도 있더라...그리고 언젠가는 장애가 나더라...사람이 만드는 것이니...

더 큰 문제는 그 수많은 값들 중에 어떤 값인지 정확히 알수가 없었다는 것....

(시스템 마다 다르겠지만 1초에 수십만의 패킷이 유입되는 시스템이라면 유입되는 모든 패킷의 Parameter들을 실시간으로 전부 Logging할 수 없으니...H/W 용량도 용량이지만...File Writing 작업이....)

 

이 정도면 Input Data Validation이 귀찮고 하찮은것 같지만 무엇보다 중요하다는 것을 알수 있을 것이다. 

 

그럼 Python으로 Data 검증 함수들을 하나씩 만들어 보자. 

막상 보면 엄청 심플하고 필요 없을 것만 같은 작업이다. 실제로도 간단하고.... 하지만 실전에서는 필수 작업이다.

 

2020/05/27 - [Python] - [Python] Check Validation

'Developer' 카테고리의 다른 글

[Developer] 전역변수  (0) 2020.05.28
[Developer] 개발할 때가 좋았는데.....  (0) 2020.05.25
Posted by [ 브랜든 ]
,

나는 이제 막 PM의 길에 들어선 10년차 개발자이다. 

 

컴퓨터 공학을 전공하였지만 그렇게 개발이 싫었다.

그렇게 나는 먹고살기 위해 개발자의 길에 서게 되었고 '지옥'같은 시간을 보내게 되었다.

('지옥'이라는 말을 쓴 이유는, 개발자, 프로그래머의 길을 쉽게 생각지 말라는 점에서...)

 

나의 첫 직장은 이름만 들어도 알만한 이동통신 네트워크 Provider의

80% 이상 시스템을 구축하는 1차 Vendor였다. 

이곳은 10년 이상의 안정된, 그리고 체계적인, 기술력 있는 회사다운 회사였다.

 

내 앞길만 보자니...개발의 '개'자도 모르는 놈이 

메모리, 포인터의 C언어, 그것도 네트워크...그 중에서도 하루가 멀다하게 Next Generation 기술이 튀어나오는...

3GPP 국제규격까지 준수해야 하는 이동통신 네트워크라니...

참 실체를 알기 전까지는 얼마나 무모한 선택이었는지 몰랐다.

 

나에게 주어진 첫 프로그램.

내가 처음으로 만든 프로그램.

그것은 시스템에서 사용하는 Configuration Value(환경 설정 값)들을 Control하는 모듈.

 

내가 들은 첫 마디.

"니가 만든 소스는 쓰레기야."

 

당시의 나는 별로 충격 먹지 않았다. 내가 그정도 수준이라고 스스로 생각하고 있었기 때문에..

(나중에 알게됐지만 이유는 배열의 Index를 1부터 사용했기 때문이었다.)

 

하지만 

그곳에서 내가 잘할 수 있는 것을 꿰뚫어 본 스승을 만나게 되었고, 지금처럼 성장할 수 있었다.

 

지금의 나는 나의 능력을 맘껏 펼칠 수 있는(그렇게 믿고 있는) 인공지능 벤처로 이직하여 음성인식 사업분야의 Leader로써 열심히 달리고 있다.

 

2년간 PM으로써 여러사업을 진행하면서 함께 일한 젊은 친구들로부터 느낀것은 

그동안 개발의 기본이라고 배웠던 부분들에 대한 필요성과 중요성에 대해 전혀 모른다는 것이었다.

 

나 역시 공부하는 차원에서 남기는 이 글들이 좋은 개발자가, 좋은 Leader가 되고 싶은 누군가에게 도움이 되었으면 한다. 

나는 머리가 좋은 것도, 공부를 잘했던 것도, 좋은 대학을 졸업한 것도 아니지만, 나만의 개발철학을 갖고 일을 하는 사람으로써 순전히 경험에 의한 나의 humble knowledge가 어딘가에 기록되는 즐거움을 느껴보기로 한다.

'Developer' 카테고리의 다른 글

[Developer] 전역변수  (0) 2020.05.28
[Developer] Input Validation - 입력값 검증  (0) 2020.05.26
Posted by [ 브랜든 ]
,