Tech

ChatGPT, 코딩을 부탁해! : 채용담당자의 ChatGPT 활용기

ChatGPT와 함께 만든 다양한 결과물을 공유합니다

2023-12-14 Glenn Lim

안녕하세요. 숨고 People Team에서 채용을 맡고 있는 Glenn입니다.

저는 올해 ChatGPT를 사용해 두 건의 재미있는 미니 프로젝트를 진행했습니다. ChatGPT가 범용적으로 사용된지 꽤 오랜 시간이 흐른 만큼 이번 포스팅의 내용이 아주 새로운 내용은 아닐 수 있습니다. 하지만 채용 담당자로서 그동안에는 하기 어려웠던 일들을 ChatGPT를 사용함으로써 도전해볼 수 있었기에 그 결과물을 많은 분들에게 공유해보고자 합니다.

들어가며

저는 비교적 이른 시점에 ChatGPT를 알게 되었습니다. 당시에 저는 ChatGPT를 한국어를 조금 못 알아듣지만 착한 인공지능 친구 정도로 생각했는데요.

실제 올해 1월 ChatGPT와의 첫 대화
실제 올해 1월 ChatGPT와의 첫 대화

당시 질문과 답변을 보시면 알겠지만 제 관심사는 이 인공지능이 얼마나 유창하게 말을 하는지, 흔히 왜곡(Hallucination)이라 불리는 현상이 얼마나 있는지였습니다. 그래서 주로 사실 관계가 명확한 내용을 위주로 질문했고 간간히 번역 용도로만 사용했을 뿐 ChatGPT를 업무에 사용할 생각은 미처 하지 못했었습니다.

하지만 점차 사람들이 ChatGPT에 관심을 갖기 시작하더니 급기야는 생성형 인공지능이 하나의 사회 트렌드가 되면서 저도 이 ChatGPT를 통해 무언가 생산적인 일을 해볼 수 있지 않을까했는데요. 그 때 떠오른 아이디어가 바로

그래. 얘한테 코드를 짜달라고 해보자

였습니다. 그동안 저는 이런저런 어려움이 있을때 '아, 이런 것들을 이런 식으로 만들어보면 좋을텐데'라는 생각은 있었지만 대부분 문제의 해결 방법이 개발, 즉 코딩이었기 때문에 시도조차 해볼 수 없는 일들이 많았습니다. 하지만 개발을 누군가 도와준다면 내 스스로 해볼 수 있는 일이 많을수도 있겠다는 생각이 들었습니다.

ChatGPT야 나는 생각을 할테니 너는 코드를 짜거라
ChatGPT야, 나는 아이디어를 줄테니 너는 코드를 짜거라

물론 당시에는 프롬프트 엔지니어링이나 Chain of Thought 등 LLM을 다루는 다양한 스킬에 대해서는 알지 못했기 때문에 무작정 부딪혀보는 수 밖에 없었습니다. 그래도 ChatGPT의 성능을 믿고 해볼만한 가치가 있는 일이라고 생각했기에 크게 두 가지 일감을 시험해보기로 했습니다.

프로젝트 시작 전

저는 더 좋은 결과물을 위해 질문을 자동으로 번역해주는 프롬프트지니를 사용하였습니다. 그 외에는 ChatGPT 내 Custom Instruction 중 How would you like ChatGPT to respond? 항목에 다음과 같은 프롬프트를 적용하였습니다.

When I ask you for a code, Please give me the code with detailed description about the code. a code you created is most efficient and clear than any other option.

진행 상황에 따라 중간중간 ChatGPT에게 버그가 있는지를 체크하거나 코드 전체에 대한 리팩토링을 요청했습니다. 또한 간단한 오타 수정이나 자잘한 에러는 ChatGPT를 사용하지 않고 직접 해결했고 여러차례 질문을 이어간 경우도 있어 중간에 생략된 과정도 있습니다.

또한 이번 포스팅에서는 분량 상 저의 질문과 ChatGPT가 작성해 준 코드만을 옮겨두었습니다. 하지만 실제로는 질문을 하게 되면 코드에 대한 설명이나 왜 이렇게 수정을 해야하는지 등을 함께 답변해줍니다. 이 부분을 참고한다면 이번 포스팅의 예시보다 더 좋은 결과물을 만들 수 있을 것이라 생각합니다.

Python으로 Wordcloud 만들기

먼저 올해 초 진행했던 전사 조직 만족도 조사의 주관식 질문들 중 몇 가지를 뽑아 숨고의 강점이라는 키워드로 묶어 워드클라우드로 만들어보았습니다.

질문 : 아래의 조건에 맞는 코드를 작성해줘

  • 파이썬을 사용한 한국어 워드클라우드
  • 가장 유명한 형태소 분석기를 사용
  • Input file type은 .csv이고 Output file type은 .png
import pandas as pd
from konlpy.tag import Okt  # You can use other analyzers like Mecab, Komoran, etc.
from wordcloud import WordCloud
import matplotlib.pyplot as plt

# Define a function to read a CSV file and generate a word cloud
def generate_korean_wordcloud(csv_file, output_png):
    # Read the CSV file (make sure it contains a column with Korean text)
    data = pd.read_csv(csv_file)

    # Initialize the Korean morpheme analyzer (in this case, Okt)
    analyzer = Okt()

    # Tokenize the text data and join the tokens into a single string
    text = ' '.join([' '.join(analyzer.nouns(sentence)) for sentence in data['KoreanText']])

    # Generate the word cloud
    wordcloud = WordCloud(
        font_path='YOUR_FONT_FILE_PATH',  # Replace with the path to a Korean font file
        background_color='white',
        width=800,
        height=600,
        colormap='viridis',  # You can choose a different colormap
    ).generate(text)

    # Display the word cloud (optional)
    plt.figure(figsize=(8, 6))
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.show()

    # Save the word cloud as a PNG file
    wordcloud.to_file(output_png)

# Usage
csv_file = 'your_input_file.csv'
output_png = 'output_wordcloud.png'
generate_korean_wordcloud(csv_file, output_png)

그러자 ChatGPT가 친절하게 설치해야 할 라이브러리(konlpy, wordcloud, pandas)를 명시해주면서 코드를 만들어주었습니다. 하지만 처음으로 준 코드에는 두 가지 문제가 있었습니다.

먼저 가공한 CSV파일에는 첫번째 열에 header가 포함되지 않았는데 ChatGPT는 header가 있다고 스스로 생각해 미리 KoreanText라는 항목을 임의로 추가하였습니다. 두 번째는 한국어 폰트 경로를 정해두지 않은 것이었는데요. 첫 번째 문제는 CSV에 직접 헤더를 추가하는 방식으로, 두 번째는 TTF 폰트 파일을 프로젝트 폴더 내에 넣어서 경로를 지정해주는 방식으로 해결할 수 있었습니다.

image

그렇게 결과물을 보니 의미 없는 단어(수, 것, 때, 더) 같은 단어들의 비중이 너무 높았습니다. 워드클라우드는 빈도수에 따라 글씨 크기가 커지기 때문에 자연스러운 발화에서 많이 나오는 단어들이 크게 표현되기 마련입니다. 따라서 워드클라우드를 만들때 필요 없는 단어들을 빼주는 작업이 필요합니다.

자연어 처리에서는 이를 불용어(Stopword) 처리라고 하는데 저는 조사와 어미 등의 문법 형태소와 단독으로 사용했을 때 의미를 갖지 않는 명사(의존명사)나 접속사 등을 제거하는 식으로 불용어 처리를 진행했습니다. 그 외에도 수집된 데이터에 많이 나오는 단어들을 따로 불용어 처리할 수 있도록 커스텀 영역도 마련했습니다.

질문 : 토큰화를 할때 의미 없는 형태소(접속사, 조사, 의존명사 등)을 제거하는 코드를 추가해줘

// ...

# Define a list of custom Korean stopwords
custom_stopwords = ["불필요한", "단어", "포함", "불용어", "설정", "예시"]

# Define a list of meaningless morphemes (POS tags to exclude)
meaningless_pos = ["Josa", "Punctuation", "Eomi", "Suffix", "Conjunction"]

# Define a function to read a CSV file and generate a word cloud
def generate_korean_wordcloud(csv_file, output_directory):
    # Read the CSV file (make sure it contains a column with Korean text)
    data = pd.read_csv(csv_file)

    # Initialize the Korean morpheme analyzer (in this case, Okt)
    analyzer = Okt()

    # Tokenize the text data, filtering out custom stopwords and meaningless morphemes
    tokens = []
    for sentence in data['KoreanText']:
        for token, pos in analyzer.pos(sentence):
            if token not in custom_stopwords and pos not in meaningless_pos:
                tokens.append(token)

    text = ' '.join(tokens)

// ...

image

약간의 불용어 처리를 마치고 나니 아까보다 결과물이 나아진 것이 보입니다. 하지만 사각형으로 나오다보니 영 재미가 없습니다. 숨고의 로고에 맞춰서 워드클라우드를 출력하기 위해 한번 더 질문해보았습니다.

질문 : 특정 이미지에 맞게 워드클라우드의 모양을 바꾸고 싶어

import pandas as pd
from konlpy.tag import Okt
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from datetime import datetime
from PIL import Image

...

    # Load the mask image
    mask_image = Image.open(mask_image_path)

    # Generate the word cloud with the mask image
    wordcloud = WordCloud(
        mask=mask_image,  # Use the mask image to define the word cloud shape
        background_color='white',
        width=800,
        height=600,
        colormap='viridis',  # You can choose a different colormap
    ).generate(text)

    # Display the word cloud with the shape defined by the mask image
    plt.figure(figsize=(8, 6))
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.show()

    # Generate a timestamp for the output file name
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")

    # Save the word cloud as a PNG file with a timestamp in the file name
    output_png = f"{output_directory}/wordcloud_{timestamp}.png"
    wordcloud.to_file(output_png)

# Usage
csv_file = 'your_input_file.csv'
output_directory = 'output_directory'  # Replace with the path to the directory where you want to save the file
mask_image_path = 'your_mask_image.png'  # Replace with the path to your custom mask image
generate_korean_wordcloud(csv_file, output_directory, mask_image_path)

ChatGPT의 답을 보니 Pillow라는 라이브러리를 추가로 불러왔고 이미지를 마스킹하는 코드가 추가되었습니다. 그런데 이 부분에서 예상치 못하게 에러가 발생했습니다. ChatGPT에게 여러 차례 바꾸어 물어보았지만 영 감을 잡지 못하기에 조금 더 찾아보니 이미지를 그대로 사용하는 것이 아닌 numpy 배열로 바꾸는 처리가 필요하다는 결론을 얻었습니다. 이에 이미지를 처리하는 코드를 mask_image = np.array(Image.open(mask_image_path)) 로 바꾸어주었습니다. 해당 코드를 적용한 후 결과물은 아래와 같습니다.

image

이렇게 총 1시간 반, 10번 내외의 질문과 답변만으로 쉽고 빠르게 예쁜 워드클라우드를 만들 수 있었습니다. ChatGPT와 함께 완성한 코드와 워드클라우드 파일은 github 링크에서 확인할 수 있습니다.

입사자 자동알림 봇

다음 프로젝트는 실제 업무 프로세스의 일부를 자동화하는 것이었습니다.

대상이 된 프로세스는 입사 전에 진행하는 서류 제출 및 장비 조사 프로세스였는데요. 저희가 사용하고 있는 입사 서류 및 장비 수요 조사를 통해 모이는 데이터는 이름, 생년월일 등의 개인정보, 합류하게 될 팀과 직무명, 입사일같은 기본 정보, 입사에 필요한 서류, 그리고 장비 선택 여부 등 확인해야 하는 데이터가 굉장히 많습니다.

기존에는 이렇게 많은 데이터를 입사자가 메일을 통해 전달하면 이 파일을 Talent Partner가 정리하여 내부에 공유하는 방식이었습니다. 그러다보니 파일이 누락되는 등의 휴먼에러가 생기기도 하고 내용을 정리하는데도 시간이 꽤 걸렸었죠.

그래서 저는 Google App Script와 Slack API를 활용해 입사자 서류 및 정보를 Google Form에서 자동으로 받아 특정 private 채널에 뿌려주는 slackbot을 계획했습니다. 물론 Zapier나 Mattermost 등의 노코드 툴을 사용해 slackbot을 만들 수도 있습니다. 하지만 직접 만드는 쪽이 훨씬 뿌듯하기도 하고 아무래도 직접 만들게 되었을때 유지보수에 편하지 않을까라는 생각이었습니다. 적은 금액이지만 월 구독료도 아낄 수 있고요.

이 포스팅에서는 Google App Script를 사용한 자동화 설정이나 Slack에서의 webhook 설정에 대한 자세한 설명은 별도로 다루지 않고 ChatGPT와 함께 코딩한 내용을 위주로 다루어 보겠습니다.

먼저 Google Form을 통해 제출된 데이터는 설문지와 연동된 시트에 자동으로 쌓이게 됩니다. 가장 첫 번째 칸에 제출 일시(Timestamp)를 시작으로 질문 순서대로 답변이 쌓이고 다른 사람이 제출할때 마다 다음 줄에 동일한 형식으로 데이터가 쌓이게 되죠. 이것을 고려해 ChatGPT에게 새 행이 업데이트 될때마다 각 행의 데이터를 가져오는 코드를 만들어달라고 질문했습니다.

질문 : Google Sheet의 새 row가 업데이트 될때마다 그 row의 내용을 가져오는 Google App Script를 만들어줘

function onFormSubmit(e) {
  // Get the sheet where the new row was added
  var sheet = e.range.getSheet();

  // Get the row number where the new data was added
  var row = e.range.getRow();

  // Get the values from the new row
  var values = sheet.getRange(row, 1, 1, sheet.getLastColumn()).getValues()[0];

  // Do something with the values
  // For example, log the values to the console
  console.log(values);
}

ChatGPT는 제 질문을 새로운 데이터가 들어오면 해당 시점의 시트 맨 마지막 줄 데이터만 확인하면 되잖아?로 해석해서 코드를 만들어주었습니다. ChatGPT가 만들어준 코드에서는 1차원 배열인 values에 가장 마지막 줄의 항목이 하나씩 들어가 있고 이를 콘솔에 띄워주는 형식으로 구현되어 있네요. Slack과의 연동 후 채널에 데이터를 출력하는 코드를 추가하기 위해 한 번 더 질문을 던져보았습니다.

질문 : 조금 전 만든 코드를 참고해서 슬랙봇으로 특정 채널에 value를 차례대로 출력하는 코드를 작성해줘

function onFormSubmit(e) {

    // ...    

    // Set up the Slack webhook URL and message
    var webhookUrl = "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK/URL";

    // Create a message with values joined by line breaks
    var message = "New row added:\n" + values.join("\n");

    // Send the message to Slack using the webhook
    var payload = {
        "text": message
    };

    var options = {
        "method": "post",
        "contentType": "application/json",
        "payload": JSON.stringify(payload)
    };

    // Use the UrlFetchApp to send the message to Slack
    UrlFetchApp.fetch(webhookUrl, options);
}

이전에 만들었던 코드에 Slack과 연동하는 부분과 및 values 배열에 들어있는 값들을 한 줄씩 메시지로 뿌려주는 코드가 추가되었습니다. 이미 코드 자체가 어느 정도 완성되었기 때문에 메시지 영역만 커스텀해도 작업이 마무리됩니다. 하지만 가장 첫 칸에 들어가는 타임스탬프와 같이 시간이나 날짜 형식의 데이터는 실제 출력하게 되었을때 Tue Nov 14 2023 16:00:00 GMT+0900 (Korean Standard Time) 과 같이 가독성이 떨어지는 형식으로 출력되는 문제가 있었습니다.

질문 : 데이터 중에 타임스탬프 형식의 데이터가 있는데, 이 데이터를 연-월-일의 Asia/Seoul locale을 적용한 데이터로 출력하게 하는 코드를 추가해줘. 되도록이면 Google App Script 내의 함수를 사용해줘.

function sendMessage(e) {

    // ...

    var timestamp = values[0];
    var formattedDate = Utilities.formatDate(new Date(timestamp), 'Asia/Seoul', 'yyyy-MM-dd');

    // Define the message
    var message = "*[신규 입사자 알림]*\n\n" +
        "-----------------------------\n\n" +
        "- 제출 일자: " + formattedDate + "\n" +
        "- 이름: " + values[1] + "\n" + // Assuming the name is in the second column
        // Add more data as needed
        "...\n";

    // Create the payload for the Slack message
    var payload = {
    "text": message
    };

    // ...
}

Google App Script에 내장된 Utilities.formatDate 메서드를 사용해서 날짜 표기 방법을 바꾸어준 것을 확인할 수 있습니다. 마지막으로 자잘한 수정과 코드 리팩토링을 마치고 난 후 실제 저희가 사용중인 슬랙봇의 예시는 다음과 같습니다.

image

ChatGPT와 함께 완성한 코드는 github 링크에서 확인할 수 있습니다.

글을 마치며

제가 진행한 프로젝트들은 약간의 검색만으로도 ChatGPT 없이 결과물을 만들 수 있는 비교적 쉬운 작업들이라고 생각합니다. 하지만 개발자의 도움 없이도 코딩을 통해 결과물을 만들어볼 수 있다는 점에서 나름의 의미를 두고 싶습니다.

또 개인적으로는 ChatGPT가 실제 업무에 도움이 된다는 것을 체감하게 된 만큼 앞으로는 채용, 또는 HR의 다양한 분야의 문제들을 ChatGPT로 해결할 수 있겠다는 자신감도 가질 수 있었습니다. 이번 프로젝트를 계기로 앞으로는 보다 더 난이도가 높은 문제들에도 도전해 볼 계획입니다.

이 포스팅을 통해 인사 담당자분들의 업무 효율화에 ChatGPT를 활용하실 수 있는 다양한 아이디어를 얻으셨길 바랍니다.

감사합니다.

Glenn Lim Talent Acquisition Lead
좋은 사람들로 북적이는 숨고를 만들기 위해 노력합니다.