Blog Archive

2024-08-28

최적화(자원 배분) 문제 - 엑셀의 해 찾기(solver)

제가 교육 업무 현업에 있을 때 대략 다음과 같은 문제에 자주 맞닥드리게 되었습니다. 

상황 1. 연간 기본 교육 계획 수립

문제 

주어진 총 예산은 1,000만원이다. 교육 프로그램의 종류가 4가지가 있는데, 제일 비싼 것 A는 100만원, 그 다음 B가 60만원, 그 다음 C가 30만원, 가장 가벼운 프로그램 D는 20만원이다. 예산 1,000만원을 다 쓰는 범위 내에서 각 프로그램을 몇 회 씩 운영해야 할 지 계획을 세워라. 
단, 모든 프로그램은 모두 연간 2회 이상 운영해야 하고, 가장 비싼 프로그램은 최대 3회 이내에서 운영할 수 있고, 가장 가벼운 프로그램도 최대 30회 이내에서 운영해야 한다.

문제 분해

이런 문제가 전형적인 최적화 문제입니다. 즉, 목표치가 주어지고, 목표치와 몇 가지 제약 조건에 맞추어서 주어진 자원을 어떻게 배분하느냐의 문제이지요. 엑셀, 구글 시트, 리브레오피스의 캘크의 "해 찾기(solver)" 기능으로 답을 찾을 수 있습니다. 

  • 목표: 연간 예산 총액 1,000만원에 맞추기
  • 변수: A, B, C, D 프로그램의 운영 횟수 (각각 a, b, c, d라고 하겠습니다.)
  • 제약 조건:
    • a, b, c, d는 모두 정수(integer)이다.
    • a, b, c, d는 모두 2 이상이다.
    • a는 3 이하이다.
    • d는 30 이하이다.
  • 방정식: 100a + 60b + 30c + 20d = 1000 을 만족하는 미지수 a, b, c, d를 구하라. 
    • 미지수가 여러 개인 다항식이기 때문에 일차 방정식이지만 해가 여러 개 존재한다. 
    • 따라서, 주어진 목표값에 이르기 위한 입력값을 여러 가지로 변화시켜보는 목표 탐색 기법을 써야 한다.

엑셀의 해 찾기에 대입

엑셀 (2024년 8월 28일 현재, Microsoft 365 기준)의 '해 찾기'에 이 문제를 넣기 위해 아래와 같은 표를 만들었습니다. 

목표는 총합이 천만원(분홍색 E7)이 되는 것이고, 변수는 횟수(노란색 D열)이다.
목표는 총합이 천만원(분홍색 E7)이 되는 것이고, 변수는 횟수(노란색 D열)이다.

목표 셀에 커서를 놓은 상태에서, 엑셀의 해 찾기를 실행합니다. 
  • 제일 위에 E7이라고 지정한 것이 목표 셀입니다. 바로 밑에서 목표 지정값으로 10,000,000원을 주었습니다. 
  • 중간에 변수들의 범위를 지정합니다. 운영 횟수, 즉 D3 ~ D6가 변수 부분입니다.
  • 마지막으로, 특별히 제약 조건이 무엇인지 지정합니다. 예를 들면, 변수는 모두 정수이고, 2 이상이고 등 총 4가지 제약 조건이 들어가 있습니다. 
엑셀의 해 찾기 대화 상자
엑셀의 해 찾기 대화 상자

이렇게 해서 해 찾기를 실행하면, 아래와 같은 계산 결과가 나옵니다. 

해 찾기를 했더니 노란색 D열의 운영 횟수가 채워졌습니다.
해 찾기를 했더니 노란색 D열의 운영 횟수가 채워졌습니다.

이런 결과가 마음에 들지 않으면, 다시 해 찾기를 실행하거나, 제약 조건을 더 추가해서 실행하면 다른 해를 찾아줍니다.

상황 2. 팀간 예산 균등 배분

문제 

사무실 소모품(과자, 물티슈, 휴지 등)으로 10만원의 예산을 썼다. 사후에 이것을 3개의 팀에 되도록 공평하게 부담시키려고 한다. 즉, 대략 3.3만원 내외에서 이미 써버린 항목들을 각 팀에 배분해야 한다. 어떤 항목을 어떤 팀에 배분해야 하는가?

예산 균등 배분 문제: 노란색에 팀 번호가 들어가면, 해당 팀의 배분액에
      금액이 들어간다.
예산 균등 배분 문제: 노란색에 팀 번호가 들어가면, 해당 팀의 배분액에 금액이 들어간다. 각 팀에 최대한 비슷하게 예산이 배분되어야 한다.


문제 분해

이 문제는 앞의 문제와는 달리 명확한 목표가 잘 안 보입니다. "3개 팀에 공평하게 배분"한다는 것을 어떻게 단일한 목표값으로 치환할 수 있을까요? 

제가 쓴 방법은 "세 팀의 예산 배분액의 표준편차를 최소화"하는 단일한 목표를 설정함으로써 문제를 단순화했습니다!

  • 목표: 3개 팀 예산 배분액 합의 표준편차가 최소가 되도록 한다. (아래 그림에서 E12, F12, G12의 표준편차가 최소가 되도록)
  • 변수: 각 항목별 팀 배정 번호(내역)
  • 제약 조건:
    • 모든 번호는 정수이다.
    • 모든 번호는 1 이상이다.
    • 모든 번호는 3 이하이다.
표준 편차 최소화라는 단일한 목표 설정
표준편차의 최소화라는 단일한 목표를 세웠습니다.


엑셀의 해 찾기 실행

목표 셀인 C13에 커서를 두고, 해 찾기를 실행합니다. 

해 찾기 대화상자. 목표값을 최소로 하는 해를 찾는다. 해법은 Evolutionary를 사용
해 찾기 대화상자. 목표값을 최소로 하는 해를 찾는다. 해법은 Evolutionary를 사용

  • 목표 셀은 C13 (3개 팀 배분액의 표준편차)입니다. 이번에는 목표 값을 지정한 것이 아니고, 목표값이 최소가 되도록 요구하였습니다.
  • 변수는 각 항목별 팀 배정 번호인 D3 ~ D11 노란색 부분이죠.
  • 제약사항은 변수들이 정수로서 1, 2, 3 중에 하나의 값을 갖도록 하였습니다. 
  • 해법 선택: 이번에는 해를 찾는 방법에 '단순 LP'나 'GRG 비선형' 대신에 'Evolutionary'를 선택했습니다. 각 방법의 차이는 수학적으로 좀 복잡하니 여기서는 다루지 않겠습니다.

계산 결과

표준편차가 289라는 작은 값으로 각 팀에 예산이 배분되었다.
표준편차가 289라는 작은 값으로 각 팀에 예산이 배분되었다.

위 그림과 같이 표준편차가 289라는 상당히 작은 값으로, 세 개의 팀에 3만3천5백원, 3만3천5백원, 3만3천원으로 거의 비슷하게 예산이 배분되었습니다. 

예시에 사용된 엑셀 파일: 예산 균등 배분 - 해 찾기.xlsx

해 찾기 기능을 이용하면, 이외에도 경영상에 부딫히는 수많은 최적화 문제, what-if 문제를 해결할 수 있습니다. 여러분의 문제 해결에도 써보시기 바랍니다.

2024-08-24

한 여름에 읽은 「우리가 겨울을 지나온 방식」

사상 최장의 열대야 기록을 깼다는 2024년 여름의 끝자락에서 지독하게 추운 겨울을 살아가는 사람들의 이야기를 읽었다. 혼자 살아가지 않는 우리 모두에게 돌봄은 남의 이야기가 아니다. 그리고, 그것의 무게는 겪어보지 않은 사람은 알 수 없다. 끝이 보이지 않은 긴 터널을 지나가는 명주와 준성의 삶은 반전은 커녕 더욱 진흙탕 속으로 빠져들어간다.

우리가 겨울을 지나온 방식. 문미선 장편소설

왜 외면하지 않고, 돌봄을 택한 어떤 사람에게는 삶이 이렇게 힘든 것인가.

치매 걸린 어머니를 간병하며 연금으로 근근히 살아가는 명주도, 아버지를 돌보며 젊은 시절을 송두리째 보냈지만 오히려 더 궁지에 몰린 준성도, 요양원에서 도망쳐나온 할머니도, 증평댁과 여행을 꿈꾸며 온기를 전했던 진천할아버지의 인생도 모두 소중하다. 지금껏 아버지를 돌보며 살았던 그의 인생은 무엇이었는지 준성이 묻는다. 벼량 끝에 몰려 뉴스에 나올 만한 결정을 한 그들에게 누가 돌을 던지겠는가?

신도, 국가도, 의료 기술도, 법에서도 도와주지 않는 엉망진창인 삶의 위기에 빠진 이웃들이 어떻게 어떻게 손을 잡았다. 그들의 선택이 어떤 결말을 가져올지 모른다. 하지만, 그렇게 바닥으로 꺼져가는 인생에서 두 손을 잡고 바다에 빠지지 않으려는 그들의 몸짓에 책을 읽는 사람도 소심한 희망을 가져본다. 각자도생의 시대, 누군가는 잔혹한 현실에서 삶의 무게를 오롯이 혼자 짊어지고 간다.

2024-08-06

복수 선택 항목 설문 문항의 통계 처리

온라인 설문지를 만들다보면, 한 질문에 대해 복수 응답이 가능하도록 문항을 만드는 경우가 자주 발생합니다. 예를 들면, "지금 먹고 싶은 과일을 모두 선택하세요."라고 하면, 선택한 과일의 갯수가 0개가 될 수도 있고, 1개가 될 수도 있고, 그보다 많을 수도 있습니다. 

1. 체크박스를 이용한 복수 선택 문항

이런 설문지를 만들 때, 보통은 복수 선택형 체크박스(checkbox)를 사용합니다. 


체크박스로 구현한 복수 응답 설문 문항
체크박스로 구현한 복수 응답 설문 문항


이렇게 문항을 만들면 결과 데이터를 담는 스프레드시트(구글 시트 또는 엑셀 등)의 한 개의 셀에 여러 개 과일 이름이 한꺼번에 들어갑니다. 예를 들면, 셀 하나에 "사과, 수박" 이렇게 값이 들어갑니다. 설문 응답자가 여러 명일 때에, 전체 응답자 중에 "사과"라는 응답이 몇 개 나왔는지 카운트하려면 매우 어렵습니다. 

이런 경우, 텍스트 구분자(이 경우 쉼표)를 기준으로 컬럼을 잘라준 다음, 데이터 분석을 하는 방법이 있고, 그렇지 않으면, 셀 안에 있는 텍스트들을 분석하는 다소 복잡한 수식을 만들어야 합니다. 

결과가 저장된 스프레드 시트. 선택한 응답들이 한 셀에 모두 들어가 있어, 빈도를 분석하기 어렵다
선택한 응답들이 한 셀에 모두 들어가 있어, 빈도를 분석하기가 어렵습니다.

위의 그림에서 총3명의 응답을 분석해보면 사과가 2회, 딸기가 1회, 수박이 2회, 포도가 1회 나왔습니다. 과일 이름이 셀 단위로 분리되지 않았으므로, 셀 안에 있는 특정 단어를 카운트하기 위해서

  1. 3명 응답 전체의 텍스트 길이를 구합니다.
    =sumproduct(len(b$2:b$4) ...
  2. A10 셀에 있는 "포도"라는 단어가 몇 번 나왔는지 카운트하기 위해 "포도"를 제거한 전체 텍스트 길이를 구합니다.
    len(substitute(b$2:b$4,A10,""))
  3. 이제 전체 텍스트 길이에서 포도를 제거한 텍스트 길이를 빼줍니다.
    =sumproduct(len(b$2:b$4)-len(substitute(b$2:b$4,A10,"")))
  4. "포도"라는 단어가 나온 횟수(빈도)를 계산하기 위해 방금 뺀 값 전체를 "포도" 텍스트 길이로 나눠줍니다.
    =sumproduct(...)/len(A10)
이렇게 하면, 각각의 단어가 여러 셀에 걸쳐서 몇 번 출현했는지 빈도를 구할 수 있습니다. 하지만 이 방법은 꽤 번잡하고, 번거롭습니다. 


2. 체크박스 그리드 형식으로 설문을 만들기

구글 설문에서는 "체크박스 그리드" 형식을 선택하면 훨씬 수월하게 통계 처리가 가능합니다. 네이버 폼에서는 문항 형식을 "표형"을 선택하면 됩니다.

체크박스 그리드로 구성한 복수 응답 설문 문항
체크박스 그리드로 구성한 복수 응답 설문 문항

이 경우에는 결과분석 시트가 훨씬 단순하게 나옵니다. 각 응답 항목 하나가 하나의 컬럼으로 분리되어 나오기 때문에, 각 컬럼별로 단어가 들어있는 셀의 갯수만 세어주면 됩니다.

체크박스 그리드 형식의 문항에 대한 결과 시트. 응답 항목 하나가 하나의 셀로 분리가 되어 빈도 계산이 훨씬 쉽다.
응답 항목 하나가 하나의 셀로 분리가 되어 빈도 계산이 훨씬 쉽습니다.


즉, 위의 그림에서는 컬럼 C에 사과, D에 딸기, E에 수박, F에 포도라는 응답이 분리되어 저장되므로, 각각의 빈도만 계산해주면 됩니다. 예를 들어, 포도라는 응답이 나온 횟수를 계산하기 위해, 포도 컬럼에서 "선택"이라는 단어가 몇 개 있는지만 세어주면 됩니다.

=countif(f2:f4, "선택")

3. 결론

특별한 경우가 아니라면, 복수 응답을 받아야 하는 설문지를 설계한다면, 단순한 체크박스 형식으로 문항을 만들지 말고, 결과 처리를 미리 생각해서, 체크박스 그리드로 만드는 것이 훨씬 좋습니다. 

그러나, 이미 체크박스 형식으로 설문지를 만들어서, 응답들이 한 셀에 모두 한꺼번에 들어가 있을 수 있습니다. 위에서 소개한 대로, 찾고자 하는 항목의 텍스트 길이와 전체 텍스트 길이를 계산해주면, 그 항목의 출현 빈도를 계산할 수 있으니, 천천히 해보시기 바랍니다. 

2024-08-02

경영지도사 인적자원관리 분야 2007년~2024년 기출문제 풀이(예시 답안) 데이터베이스

일전에, 2024년 경영지도사 인적자원관리 분야 시험 문제 및 예시 답안을 작성해서 공개한 적이 있습니다. 그리고 18년간 시험 문제 출제 경향 (출제 빈도) 분석도 한 적이 있구요.

이제 지난 18년간 기출 문제와 그 예시 답안을 모두 담은 데이터베이스를 공개해도 될 것 같습니다. 경영지도사 시험 문제가 공식적으로 공개된 것은 2013년부터입니다. 그래서 그 이전 자료는 응시자들의 기억에 의해 복원된 문제들입니다. 그렇게 복원된 문제들을 여러 곳에서 찾아서, 예시 답안을 작성하고, 그것을 소위 "DB화" 하였습니다. 





개요 화면: 3개 과목, 18년간 총 324문제에 대한 풀이를 담았다. 모든 문제는 총 56개의 주제로 분류하였다.
3개 과목, 18년간 총324문제 풀이가 담겨있다. 주제 분류는 총56개로 하였다.



불편했던 점

제가 시험 준비를 하면서 수험생으로서 아쉬웠던 점이 있었습니다. 즉, 기출 문제가 체계적으로 정리되어 있지 않아서, 내가 공부하는 주제에 맞추어, 이 분야에서는 어떤 기출 문제가 있었는지, 그리고 그것에 대한 답안은 어떤 관점으로 정리하면 좋을지 바로 참조할 수 있는 곳이 없었습니다. 

몇몇 학원가에서 제공하는 기출문제 풀이는 최근 몇 년에 집중되어 있었는데, 그것도 "DB화" 되어있지 않아서, 공부하는 장(챕터)에 맞추어, 관련 문제를 전부 열람하고, 풀어볼 수가 없었습니다. 그래서 문제와 문제 풀이를 (한글, 워드, 구글 독스같은) 워드프로세서에 정리해나갔는데, 주제별, 과목별, 연도별로 정리가 잘 안 되니, 활용도가 낮고, 공부하기가 불편했습니다.

대안을 찾다가, 문제와 답을 (엑셀, 구글 시트 같은) 스프레드시트로 옮기려고 했는데, 답안이 길고, 서식이 있는 리치 텍스트(rich text)여서 스프레드시트로 정리하는 것은 매우 어려웠습니다. 그래서 다양한 형식의 데이터를 수용할 수 있고, 다양한 조건으로 조회(쿼리)가 가능한 데이터베이스로 옮기는 게 좋겠다고 결론을 내렸습니다. 

기출문제 풀이 데이터베이스 구성

결론적으로, 로우코드 데이터베이스인 에어테이블(Airtable)에 정리를 하고, DB 구조도 몇 번 변경을 하면서 가장 적합한 형태로 바꾸어갔습니다. 18년간 문제를 모두 정리하다보니 총 324문제가 되더군요. 이것들의 답안을 정리하는 데에 엄청난 시간이 걸렸습니다. 제가 가지고 있는 수험 교재 세 권, 그리고 국가법령정보센터, 노동OK, 한국어/영어 위키피디아, 각종 블로그 아티클, 대학 강의 자료 등을 참조하고, 그래도 답을 쓰기가 애매한 경우는, 생성형 AI(제미나이, 챗GPT, 끌로드, 코파일럿 등)의 도움을 받아서 답안을 정리하였습니다. 또 문제별로 키워드를 자동 추출하기 위해 에어테이블의 AI 필드의 도움을 좀 받았으나, 제가 쓰는 요금제로 쓸 수 있는 용량이 정해져 결국에는 노가다(?) 작업으로 거의 진행했습니다. 

출제 경향 분석 화면. 전과목, 개별 과목에 대해 어떤 주제에서 출제가 많이 되었는지 분석해준다.
출제 경향 분석 인터액티브 차트. 전과목 분석, 과목별 분석이 가능하다.



사용자 인터페이스 구성

아무리 에어테이블이 쉽게 만들어놨다고 하지만, 데이터베이스 날 것의 테이블들은 일반적인 사용자가 접근하면 어디에서 무엇을 해야 할 지 감이 안 옵니다. 그래서 사용자 인터페이스 화면을 만들어줘야 하는데, 고려한 솔루션은 에어테이블 자체 인터페이스 디자이너(Interface Designer), 소프터(Softr), 노로코(Noloco)였습니다. 노로코는 기능이 세세하고 막강하여, 트라이얼 기간동안 몇 번 감탄하며 UI를 만들어봤는데, 트라이얼 기간이 끝나니, 요금이 너무 비쌌습니다. 소프터는 한국에서는 가장 알려진 도구인데, 이상하게 저하고는 잘 안 맞았는지, 제가 원하는 인터페이스를 도저히 만들 수가 없었습니다. 인터페이스 디자이너는 기능 면에서 가장 떨어지지만, 에어테이블에 네이티브하게 붙어 있어서 가장 간편하고 안정적(?)입니다. 

현재 사용자 인터페이스는 간단하게 문제 목록을 목록형으로 과목별로 조회하는 것이 주된 기능입니다. 조회할 때 기본적으로 필터, 검색, 정렬, 그룹핑을 원하는 대로 할 수 있습니다. 문제 목록이 목록형으로 나오는 것이 별로 맘에 안 들면, 카드 형식으로 나오는 메뉴도 추가했습니다. 그러다가, 이왕 데이터베이스가 구축된 것, 주제별로 어떤 분야에서 문제가 많이 나왔는지 빈도 분석 차트도 넣어봤습니다. 이것도 처음에는 그냥 몇 개 고정형 차트로 보여주다가, 출제연도를 선택해가면서 약간은 인터액티브하게 다이나믹한 차트로 변경시켜놓았습니다. 

문제 카드 화면: 카드를 선택하면, 문제 풀이가 나온다. 필터, 카드의 정렬 방식 등을 바꿀 수 있다.
카드 형식으로 제공되는 문제 (필터, 정렬 방식 등을 바꿀 수 있다.)



사용자 의견 반영 실시간 업데이트


마지막으로, 종이책도 아니고 전자책(ebook)도 아닌 클라우드 기반의 시스템 장점을 살려, 사용자의 의견 제출 기능을 추가했습니다. 문제 풀이 과정에 오류, 오타, 개선점을 발견한 경우, [의견 보내기] 버튼을 눌러서 수정 의견을 내면, 제가 접수하여 오류를 재빠르게 수정합니다. 제출된 의견은 고유 티켓 번호가 붙어서 추적 관리되고, 그 결과를 알려드립니다. 그렇게 해서 기존의 출판물과 달리, 사용자 의견을 반영하여 지속적으로 품질이 좋아지고, 항상 최신 버전이 유지되는 기출문제 시스템이 됩니다.
각 문제 풀이마다 수정 의견을 제출하는 버튼이 있어서 의견을 내면, 빠르게 업데이트된다.
어떤 문제에 대해 수정 의견을 제출하면, 업데이트 후, 그 내용이 모두에게 실시간으로 반영된다.

패키징과 판매

에어테이블의 큰 단점은 소프트웨어를 패키징하여 판매하는 방법이 상당히 어렵다는 것입니다. 한 기업 내에서 엔터프라이즈용으로 사용할 때에는 접근 권한을 조정하면서 데이터와 접근 메뉴를 사용자들에게 배분하면 되는데, 일반 소비자용으로 판매하는 것은 생각할 문제가 매우 많습니다. 판매할 대상이 데이터 자체인지, 데이터베이스 구조인지, 그것의 인터페이스인지, 또는 그런 것들의 결합인지에 따라 다른 접근법을 취해야 합니다. 몇 가지 복잡한 방법들도 있지만, 결국에 찾다가 찾다가 네이버 스마트스토어에 접근 권한을 판매하는 방식으로 결정하였습니다. 스마트스토어의 상품 분류를 어떻게 하느냐부터 시작해서 애매하고 잘 맞지 않은 부분이 많았지만, 현재는 스마트스토어에 입점한 상태입니다. 

판매 가격

무료로 공개해볼까 생각을 안 한 것은 아닌데, 그래도 제가 여기에 투자한 시간에 대한 보상, 그리고 이 제품(프로그램)을 쓰는 사람들이 잠재적으로 얻게 되는 이득과 가치가 어느 정도 있다고 판단했습니다. 그리고, 이게 단순히 기출문제 풀이집을 전자책이나 종이책으로 제공하는 것이 아니라, 클라우드 시스템이기 때문에, 개인 맞춤형(?)으로 문제들을 재구성할 수 있고, 프로그램에 새로운 기능이 업그레이드되거나, 결함이 제거되거나, 내용이 실시간으로 업데이트됩니다. 그런 것들을 고려하여, 적당한 가격을 붙였습니다. 구독형은 아니고, 그냥 일회성 구매만 하면 됩니다.

구입 방법



네이버 쇼핑에 경영지도사 2차 시험 인적자원관리분야 기출문제 풀이(2007년~2024년, 18년간) 데이터베이스라는 이름으로 올렸습니다. 구매 과정이 좀 복잡한데, 먼저 네이버 쇼핑에서 구매(결제)를 하고, 기출문제 데이터베이스 시스템에 접속하여, Airtable에 회원 가입을 한 다음, 시스템 접근할 때 뜨는 접근 권한 요청을 하면 됩니다. 
또는, 네이버 쇼핑에서 구매(결제)를 하고, 이메일을 네이버 톡톡으로 저에게 알려주시면 됩니다.
그러면 제가 결제자와 권한 요청자가 동일하다는 것을 확인하고, 요청자에게 접근 권한을 드립니다. 

데모 영상

네이버 쇼핑에 올린 18초짜리 간단한 동영상입니다. 어떻게 생긴 프로그램인지 대충 감을 잡을 수 있습니다.