본문 바로가기
IT 공부/알고리즘 (컴퓨팅 사고력 연습)

문제를 정확히 정의할 줄 아는 능력...

by exdus3156 2023. 11. 29.

1. 디스크 파일 정렬 문제

존 벤틀리의 <생각하는 프로그래밍>의 첫 칼럼에서는 아래와 같은 사례가 있다.

그 프로그래머의 질문은 간단했다. "디스크 파일을 어떻게 정렬하지?" 내가 처음에 어떤 실수를 했는지 말하기 전에, 여러분에게 내가 했던 대답보다 더 잘 할 수 있는 기회를 주겠다. 여러분이라면 어떻게 대답했을까?

 

처음에 저자는 아무 생각없이 "merge sort를 써" 라고 대답했다. 그러나 이내 자신이 엉뚱한 대답을 했다는 것을 깨달았다. 프로그래머가 처한 문제 상황은 정확히 다음과 같았기 때문이다.

  • 이 기능은 큰 시스템의 일부이기 때문에 메모리를 많이 사용할 수 없다. 기껏해야 1MB 정도다.
  • 파일은 최대 10,000,000(1천만)개의 레코드를 가진다.
  • 각 레코드는 7자리 양의 정수이며, 모든 정수는 서로 중복되지 않는다. 
  • 중복되는 경우 심각한 에러로 취급한다.
  • 파일에는 레코드를 제외한 다른 정보는 없다.
  • 정렬을 하는 도중에는 시스템은 다른 작업을 할 수 없다.
  • 정렬된 파일은 평균 한 시간에 한 번 정도 주기로 요청한다. 오래 걸려도 2분 안에 완료되었으면 좋겠다.

 

확실히 요구사항과 제약조건을 보면 시간이 오래 걸릴 것 같다. 7자리 숫자 범위를 커버하기 위해 4바이트 정수형 데이터 타입을 사용하는 경우, 대략 40,000,000바이트(약 40MB)가 필요하기 때문이다. 최소 40번 정도는 파일에서 데이터를 메모리로 가져와야 한다.

이를 해결하기 위해 저자가 제시한 솔루션은 비트맵 데이터 구조를 활용하는 것이다. 일렬로 나열된 비트열이 있다고 하자. [0,0,0,0,0,0,0,....] 비트열의 각 위치를 0, 1, 2, 3, 4, .. 숫자와 대응시킨다. 그러면 각 비트열이 1이 되면 해당 숫자가 있다는 것을 가리킬 수 있다.

1천만개의 양의 정수를 비트열로 표현하려면 대략 1.2MB 정도가 된다. 메모리 한계를 넘긴 한다. (저자는 이 문제의 해결을 연습문제로 남겨뒀다.) 여하튼 이렇게 비트맵을 마련하고, 파일에서 숫자를 하나씩 읽어와 해당되는 비트열의 값을 1로 바꾼다. 입력 파일의 끝에 다다르면 비트맵을 순서대로 읽어서 숫자를 출력 파일에 기록하면 된다. 한 번의 파일 읽기와, 한 번의 파일 쓰기로 끝난다. 메모리도 절약하면서..!!

 

2. 구글 면접 시뮬레이션

잠깐 다른 이야기를 하자면, 예전에 작성한 포스팅에서 아래와 같은 구글 면접 시나리오를 읽은 적이 있었다.

A : 숫자 3개를 정렬해보세요.
B : 숫자 3개만 정렬한 것인가요? 혹은 더 많은 숫자를 정렬할 필요가 생기나요?
A : 나중에는 숫자가 늘어날 것입니다.
B : 정렬 조건은 고정되었나요? 혹은 오름차순, 내림차순 등 정렬 방식을 선택해야 하나요?
A : 선택해야 합니다.
B : 숫자가 정수인가요? 아니면 실수인가요?
A : 두 가지 모두 사용합니다.
B : 정수일 경우 범위가 어떻게 되나요?
A : 최대 30자리 정수입니다. 최소는 마이너스로 10자리 정도 됩니다.
B : 실수는 어떤가요?
A : 소수점 이하 20자리까지 정확해야 합니다.
B : 이 프로그램이 독립적인 응용 프로그램인가요? 아니면 Function으로 제공하는 것입니까?
A : 둘 다 필요합니다.
B : 그러면 응용프로그램은 누가 사용하려는 것인가요?
A : 우주관제센터입니다.
B : 이 프로그램은 어떤 운영환경에서 사용됩니까?
A : IBM 메인프레임입니다.
B : 이 프로그램을 얼마나 자주 호출합니까?
A : 1초에 1억번 호출합니다.
B : 그렇다면 소수점 20자리를 계산하기는 불가능해 보입니다.
A : 메모리는 늘릴 수 있어요. 어떤 알고리즘을 써야 빠를까요?
B : 정렬이면 O(N logN) 시간복잡도가 빠르지만, 정렬해야 하는 숫자가 만 개를 넘는 수준이 아니라면 별 차이는 없을 것 같습니다. 중요한 것은 해당 Function을 호출할 때 숫자가 최대 30자리나 되니까 인자로 그대로 넘기지 말고 pointer나 글로벌 변수로 접근하는 것이 좋을 것 같습니다.
A : 그렇게 하면 객체지향 설계적인 측면에서 어떤 문제가 있을까요? 

(...)

 

<글로벌 소프트웨어를 말하다>의 저자에 따르면, 이런 식으로 IT 회사들은 애초에 단기간에 준비가 불가능한 문제를 통해 면접자의 실력을 가린다고 한다. 어쩔 때는 1시간 이상을 할애해가며 개발자의 문제 정의 능력과 해결 능력을 검증한다.

 

3. 문제 정의 능력

이렇게 문제를 컴퓨팅 관점에서 정확하게 정의하고, 또 솔루션까지 제공하는 개발자들이 내 눈에는 너무나 멋있어 보인다. 성격적으로 나는 이런 전문가스러움(?), 공학자스러움(?), 엔지니어스러움을 좋아하고, 그런 사람을 옆에서 보면서 본받고 싶다.

하지만 한편으로는 숨이 턱 막히는 느낌이 들기도 한다.

알고 있는 모든 지식을 총동원해서 문제를 정확하게 정의하고, 거기서 다시 솔루션을 이끌어내야 한다. 엄청난 역량이다. 추상적인 문제를 컴퓨터 레벨로 끌어오고, 거기서 제약 조건에 적합한 솔루션을 이끌어낸다. 후자도 힘든데, 사실 전자가 더 엄청난 역량인 것 같다.

가면 갈수록 AI가 잘하게 되면서 단순히 문제를 풀고 그러는 것은 남들에게 자랑할만한 역량이 아니게 될텐데, 점점 취업이 쉽지 않아 질텐데 말이다. 뛰어난 개발자가 되고 싶으면서도 마음 한 켠이 참 착잡하고 불안하다.