같은 코드를 세 번째 복사하고 있다면
엑셀 반복 업무를 파이썬으로 자동화하다 보면 어느 순간 비슷한 코드를 계속 복사해서 붙여넣고 있는 자신을 발견하게 됩니다. 파일명에서 날짜를 뽑는 코드, 전화번호 형식을 맞추는 코드, 특정 조건으로 데이터를 걸러내는 코드 같은 것들입니다. 처음에는 이 정도쯘 복붙해도 괜찮다고 생각하지만, 조건이 하나라도 바뀌면 복붙해둔 코드를 전부 찾아서 똑같이 고쳐야 합니다. 열 군데 중 한 군데라도 빠뜨리면 그 부분만 다른 결과가 나옵니다.
이럴 때 필요한 게 함수입니다. 함수는 반복되는 작업을 이름 붙여서 한 곳에 모아두고, 필요할 때마다 그 이름만 불러서 쓰는 방법입니다. 비전공 사무직을 위한 코딩 입문 로드맵에서 언급했듯 코딩 학습은 내 업무의 반복 지점을 찾는 데서 시작하는데, 함수는 그 반복을 실제로 코드 안에서 정리하는 도구입니다.
함수가 하는 일, 세 문장으로
함수는 정확히 세 가지를 합니다. 값을 받고, 무언가를 처리하고, 결과를 돌려줍니다. 이것만 이해하면 함수의 절반은 이해한 셈입니다.
def add_tax(price):
result = price * 1.1
return result
print(add_tax(10000)) # 11000.0
print(add_tax(50000)) # 55000.00000000001
add_tax라는 이름의 함수를 하나 만들었습니다. 이 함수는 price라는 값을 받아서, 10퍼센트를 붙인 다음, 그 결과를 돌려줍니다. 함수를 만들어두면 이후로는 세율 계산 로직을 다시 쓸 필요 없이 add_tax(가격)만 적으면 됩니다. 만약 세율이 10퍼센트에서 13퍼센트로 바뀐다면, 함수 안의 숫자 하나만 고치면 이 함수를 쓰는 모든 곳에 한꺼번에 반영됩니다.
실무에서 자주 쓰는 함수 형태
거래처 목록에서 전화번호 형식을 통일하는 상황을 예로 들어보겠습니다. 어떤 셀에는 010-1234-5678, 어떤 셀에는 01012345678, 어떤 셀에는 공백이 섞인 010 1234 5678이 들어 있습니다.
def normalize_phone(phone):
digits = phone.replace("-", "").replace(" ", "")
if len(digits) == 11:
return f"{digits[:3]}-{digits[3:7]}-{digits[7:]}"
return digits
samples = ["010-1234-5678", "01012345678", "010 1234 5678"]
for s in samples:
print(normalize_phone(s))
세 가지 다른 형식을 넣어도 모두 010-1234-5678 형태로 통일해서 돌려줍니다. 이 함수 하나만 만들어두면 엑셀에서 pandas로 불러온 데이터프레임 전체에 apply 함수로 한 번에 적용할 수 있습니다.
import pandas as pd
df = pd.read_excel("거래처명단.xlsx")
df["전화번호"] = df["전화번호"].apply(normalize_phone)
수백 개의 행을 하나하나 손으로 고치는 대신, 함수 하나와 한 줄의 적용 코드로 끝납니다. 텍스트 정리 규칙이 복잡해질수록 정규표현식과 함수를 함께 쓰면 훨씬 정교하게 처리할 수 있습니다.

함수를 나누는 기준
함수를 처음 만들 때 가장 자주 하는 실수는 하나의 함수에 너무 많은 일을 몰아넣는 것입니다. 파일을 읽고, 정리하고, 계산하고, 저장하는 일을 전부 함수 하나에 넣으면 나중에 어디서 문제가 생겼는지 찾기 어려워집니다.
기준은 간단합니다. 함수 하나는 한 가지 일만 하도록 만듭니다.
def read_data(filepath):
return pd.read_excel(filepath)
def clean_data(df):
df = df.dropna(subset=["금액"])
df["금액"] = df["금액"].astype(int)
return df
def calculate_total(df):
return df.groupby("부서")["금액"].sum()
def run():
df = read_data("매출.xlsx")
df = clean_data(df)
total = calculate_total(df)
print(total)
run()
이렇게 나누면 “정리 단계에서 숫자 변환이 잘못됐다”거나 “합산 결과가 이상하다”는 문제가 생겼을 때, 어느 함수를 살펴봐야 하는지 바로 알 수 있습니다. 함수 이름만 봐도 무슨 일을 하는지 짐작할 수 있다는 것도 큰 장점입니다.
기본값과 여러 개의 값 돌려주기
함수를 쓰다 보면 매번 똑같은 값을 넣는 게 귀찮아지는 경우가 있습니다. 이때는 기본값을 지정해둘 수 있습니다.
def add_tax(price, rate=0.1):
return price * (1 + rate)
print(add_tax(10000)) # 세율 기본값 10퍼센트 적용
print(add_tax(10000, 0.13)) # 세율을 직접 지정
또한 함수는 결과를 하나만 돌려줘야 하는 게 아닙니다. 여러 값을 한꺼번에 돌려줄 수도 있습니다.
def summarize(numbers):
total = sum(numbers)
average = total / len(numbers)
return total, average
total, average = summarize([10, 20, 30, 40])
print(total, average) # 100 25.0
합계와 평균을 각각의 변수로 받아서 바로 활용할 수 있습니다. 이런 형태는 데이터 요약 작업이나 보고서 자동 생성 스크립트에서 자주 쓰입니다.
에러가 나도 당황하지 않기
함수를 만들다 보면 처음에는 에러가 자주 납니다. 특히 함수에 값을 잘못 넘겼을 때 나오는 TypeError나 missing argument 메시지를 자주 보게 됩니다.
def add_tax(price):
return price * 1.1
add_tax()
# TypeError: add_tax() missing 1 required positional argument: 'price'
이 메시지는 함수가 필요한 값을 받지 못했다는 뜻입니다. 겁먹을 필요 없이 메시지가 가리키는 부분만 확인하면 됩니다. 에러 메시지를 읽는 습관은 함수를 다루는 데도 그대로 이어지는데, 이 부분은 에러 메시지 읽는 법에서 더 자세히 다루고 있습니다.
함수는 문서가 되기도 합니다
함수 이름과 매개변수 이름을 명확하게 지어두면, 코드를 나중에 다시 볼 때나 동료에게 넘길 때 훨씬 이해하기 쉬워집니다. def f(x): 대신 def calculate_monthly_total(sales_df): 라고 쓰면, 함수 이름만 읽어도 무슨 일을 하는지 알 수 있습니다. 자동화 스크립트를 오래 유지보수하려면 이런 이름짓기와 더불어 변경 이력을 남기는 습관도 중요한데, 이에 대해서는 자동화 로그 작성법에서 다루고 있습니다.
처음에는 함수 세 개면 충분합니다
함수를 처음 배울 때 너무 많은 개념을 한꺼번에 익히려 하지 않아도 됩니다. 본인의 반복 업무 중 딱 하나를 골라서, 그 작업을 값 받기, 처리하기, 돌려주기의 세 단계로 나눠보는 것부터 시작하면 충분합니다. 매달 반복하는 파일 정리, 매주 취합하는 보고서, 매일 확인하는 데이터 필터링 중 하나를 함수로 만들어보면, 그다음부터는 비슷한 작업을 자연스럽게 함수로 나누는 감각이 생깁니다.
함수는 코드를 짧게 만드는 기술이 아니라, 반복되는 업무 로직을 한 곳에 모아 안전하게 관리하는 방법입니다. 픽셀앤코드는 양주 지역 중소기업과 공공기관을 대상으로 비전공자 실무자가 자신의 업무에 맞는 자동화 스크립트를 직접 작성할 수 있도록 돕는 IT 교육 과정을 운영하고 있으며, 실제 업무 데이터를 예제로 활용해 함수 작성부터 자동화 적용까지 단계별로 안내하고 있습니다.