학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화

힘센캥거루
2026년 3월 14일(수정됨)
6
1

2022개정 교육과정이 들어오면서 과목이 많아지고, 이에 따라 평가 계획서도 매 학기마다 새롭게 써야하는 일이 생겼다.

문제는 평가 계획서에는 각 단원별 성취 기준, 성취 수준 등을 모두 기재해야하는 요식 행위를 필요로 한다는 것이다.

이런 기준들은 따로 교사가 작성하는 것이 아니라 단순히 복사+붙여넣기를 하는 것.

그래서 해당 내용들을 테이블로 정리한 뒤, 엑셀이나 스프레드시트의 FILTERTEXTJOIN 함수를 이용해 자동으로 합쳐보기로 했다.

1. 성취수준 데이터베이스 만들기

각 선택교과 당 성취수준은 아래의 KICE 학생평가지원포털에서 얻을 수 있다.

상단 목차의 [초/중/고] -> [교육과정 성취기준] -> [성취기준 자료실] 에서 검색한 뒤 다운받으면 된다.

예를들어 세계시민과 지리의 성취수준을 보며 아래와 같다.

문제는 이런 성취 기준이 적게는 15개이고, 각 성취 기준마다의 성취 수준을 복사해서 A~E까지 합쳐야 한다는 것이다.

이제 이 자료들을 테이블로 만들어 보자.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-1

먼저 hwp로 되어 있는 파일을 hwpx 파일로 만들어준다.

hwpx파일은 내부 파일 구조를 xml 데이터로 저장하기 때문에 다른 프로그램으로 내부를 파싱할 수 있게 해준다.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-2

그리고 파이썬을 이용해 hwpx 내부의 테이블을 뽑아내 본다.

아래 코드는 당연히 chatGPT 형님의 도움을 받았다.

hwpx 파일은 zip + xml 구조이므로 파이썬으로 내부 xml을 읽어 테이블을 추출할 수 있다.

// 이 코드는 생성형 AI를 이용해 제작한 코드입니다.

import zipfile
import xml.etree.ElementTree as ET
from openpyxl import Workbook

hwpx_path = "사회과 선택과목 성취수준 현장 보급본.hwpx"
xlsx_path = "output.xlsx"


def tag_name(elem):
    return elem.tag.split("}")[-1]


def collect_text(node):
    texts = []

    # tc 내부에 중첩 tbl이 있으면 그 하위 텍스트는 제외한다.
    stack = [node]
    while stack:
        cur = stack.pop()

        if cur is not node and tag_name(cur) == "tbl":
            continue

        if tag_name(cur) == "t" and cur.text:
            t = cur.text.strip()
            if t:
                texts.append(t)

        children = list(cur)
        stack.extend(reversed(children))

    return "\n".join(texts)


def is_title_like(text):
    if not text:
        return False

    compact = text.replace(" ", "")

    # 표 전체 내용을 붙여 놓은 긴 문장은 제목으로 취급하지 않는다.
    if len(text) > 80:
        return False

    # 표 헤더/본문 키워드가 포함되면 제목 행으로 넣지 않는다.
    if "성취기준" in compact and "성취수준" in compact:
        return False

    return True


wb = Workbook()
ws = wb.active
ws.title = "tables"

saved_table_count = 0
current_row = 1

with zipfile.ZipFile(hwpx_path, "r") as z:
    section_files = sorted(
        name for name in z.namelist()
        if name.startswith("Contents/section") and name.endswith(".xml")
    )

    for section_file in section_files:
        xml_data = z.read(section_file)
        root = ET.fromstring(xml_data)

        elems = list(root.iter())

        for i, elem in enumerate(elems):
            if tag_name(elem) != "tbl":
                continue

            tbl = elem

            prev_text = ""
            for j in range(i - 1, -1, -1):
                if tag_name(elems[j]) != "p":
                    continue

                texts = []
                for x in elems[j].iter():
                    if tag_name(x) == "t" and x.text:
                        t = x.text.strip()
                        if t:
                            texts.append(t)

                candidate = " ".join(texts)
                if not candidate:
                    continue

                if is_title_like(candidate):
                    prev_text = candidate
                    break

            table_rows = []
            for tr in tbl:
                if tag_name(tr) != "tr":
                    continue

                row_values = []
                for tc in tr:
                    if tag_name(tc) != "tc":
                        continue
                    row_values.append(collect_text(tc))

                if row_values:
                    table_rows.append(row_values)

            if not table_rows:
                continue

            preview_text = "".join(table_rows[0])

            # 1행 1셀 같은 요약성/오검출 표는 제외한다.
            has_enough_shape = len(table_rows) >= 2 and any(len(r) >= 2 for r in table_rows)

            if "성취기준별" in preview_text and "성취수준" in preview_text and has_enough_shape:
                saved_table_count += 1

                table_title = prev_text if is_title_like(prev_text) else ""

                for row_values in table_rows:
                    # 1열에는 표 제목을 두고, 실제 표 데이터는 오른쪽(2열부터) 배치한다.
                    ws.cell(row=current_row, column=1, value=table_title)

                    first_value = row_values[0].strip() if row_values and isinstance(row_values[0], str) else ""
                    start_col = 3 if first_value in {"B", "C", "D", "E"} else 2

                    for col_idx, value in enumerate(row_values, start=start_col):
                        ws.cell(row=current_row, column=col_idx, value=value)

                    # 오른쪽으로 밀린(B/C/D/E) 행은 표의 첫 번째 열(2열)을 바로 윗행 값으로 채운다.
                    if start_col == 3 and current_row > 1:
                        ws.cell(row=current_row, column=2, value=ws.cell(row=current_row - 1, column=2).value)

                    current_row += 1

                # 표 사이 한 줄 띄우기
                current_row += 2

if saved_table_count == 0:
    ws["A1"] = "조건에 맞는 표를 찾지 못했습니다."

wb.save(xlsx_path)
print(f"완료: {saved_table_count}개 표를 하나의 시트에 저장")

이렇게 하면 내부 테이블이 아래처럼 뽑혀 나온다.

이렇게 해도 제대로 나오지 않는 표이 있다면 손으로 데이터를 약간만 정제해주자.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-3

그냥 엑셀에서 필터와 텍스트 나누기를 이용해 각각 성취기준 코드, 내용, 성취기준별 성취수준을 분리시켰다.

이를 정규화를 하면 성능은 올라가겠지만, 사람이 확인하기는 어렵기에 그냥 중복된 컬럼으로 두기로 했다.

그리고 이렇게 만들고 나니, 차라리 데이터베이스 공개 청구를 할걸 그랬나 하는 생각도 든다.

2. 스프레드시트 만들기

일반적인 학교들은 평가 계획에 각 주차에 맞는 성취코드와 성취 기준을 넣는다.

그래서 월별로 성취코드만 선택하면 자동으로 채워지도록 만들면 평가 계획 입력이 훨씬 쉬워질 것이라 생각했다.

스프레드시트는 filterunique 함수를 이용해 입력하려고 하는 과목, 단원, 성취코드를 조합해 만들었다.

만약 어렵다면 AI와 함께 만들어보길 권해본다.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-4

첫번째 탭에서는 월, 주차, 단원명, 성취기준코드를 입력하면 가장 오른쪽에서 붙여넣기만 하면 되도록 만들어보았다.

가운데 있는 초록색 박스 부분은 내가 넣은 성취기준을 확인하기 위해 만들어 두었다.

이렇게 선택을 해주면 단원별 성취기준 및 성취수준, 학기 단위 성취 수준이 모두 완성되도록 만들었다.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-5

사실 일반적인 교과에서는 모든 성취기준을 평가 계획에 넣으니 그냥 다 때려박아도 상관 없지만, 교육과정 재구성을 고려해서 제작했다.

그냥 A~E를 모두 합쳐주는 시트도 한번 넣어볼까 고민중이다.

그리고 수행평가를 위한 시트도 하나 만들어 보았다.

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-6

내가 수행평가에 넣고싶은 성취기준 코드를 넣으면, 평가 계획서에 넣을 수 있도록 A~E 수준을 모두 합쳐준다.

우리가 고민해야 할 부분은 복사, 붙여넣기가 아니라 실질적으로 어떤 평가가 이루어져야 할 것인지이다.

3. 사용 후기

학교 업무 자동화 - 스프레드시트로 평가 계획서 초안 제작 자동화-7

안타깝게도 많은 교사들이 평가 계획에 시간을 쏟아부음에도 불구하고, 교실에 있는 사람들은 그 누구도 성취 수준의 문장을 궁금해 하지 않는다.

평가 계획 보다는 평가 계획에 따라 구현되는 평가 그 자체가 중요하기 때문이다.

성취 기준을 평가 기준에 넣기 시작했던 시기부터 졸업한 사람들에게, 성취 기준이 무엇이었는지 물어본다면그 누구도 기억하지 못할 것이라고 자신있게 말할 수 있다.

그래서 평가 기준에 이러한 문장들을 넣는 것이 의미 없는 요식 행위일 뿐이라고 말할 수 있을 것이다.

학교에서 이루어지는 교육 현장은 성취 코드, 성취 기준 따위 처럼 정적인 것이 아니라 동적이다.

우리는 평가 계획의 공문서적 완성도 보다는, 평가 자체의 질적인 문제를 고민해야 하는 시간이 더 필요하지 않은가 하는 생각이 든다.

아마 제대로 된 사용 후기는 실제로 사용한 뒤인 7~8월 이후에나 올릴 수 있을 것 같다.

옆자리 선생님께 이 스프레드 시트를 공유했더니, 지금 당장 2학기 평가 계획을 만둘수 있을 것 같다며 좋아하셨다.

아마 많은 도움이 되지 않을까 싶다.

관련 글

Review of Offline Participation in the 2026 Dongguk University Future Society Teacher Competency Enhancement Forum
Review of Offline Participation in the 2026 Dongguk University Future Society Teacher Competency Enhancement Forum
One of the teachers introduced a training program that looked interesting.It was AI-related training held at Dongguk University.AI training is nice, b...
Review of Visiting the Education Korea Expo (2026)
Review of Visiting the Education Korea Expo (2026)
I happened to find information about the Education Korea Expo through Instagram.Last year, it overlapped with another event so I couldn’t go, which ma...
Preview of Earth Science Content in the 2022 Revised Curriculum - Unit 3: Celestial Bodies in the Solar System and the Evolution of Stars and the Universe
Preview of Earth Science Content in the 2022 Revised Curriculum - Unit 3: Celestial Bodies in the Solar System and the Evolution of Stars and the Universe
This time, it’s the last stop in our tour of Earth Science.We’re going to look at Unit 3.1. Content structureIn the content structure of Unit 3, the t...
National Education Commission Overhauls Completion Criteria for High School Credit System
National Education Commission Overhauls Completion Criteria for High School Credit System
[This article was produced using AI based on a live video stream.]Attendance-focused vs. achievement-reflecting… “Finalizing the system without suppor...
Training on Educational Research and Statistical Analysis for Teachers – Summary of Sessions 21–30 and Reflections
Training on Educational Research and Statistical Analysis for Teachers – Summary of Sessions 21–30 and Reflections
Today I’d like to write down what I remember from sessions 21–30 of the educational research and statistical analysis course for teachers, along with...
Educational Research and Statistical Analysis Training for Teachers - Collection of R Practices from Sessions 13–20
Educational Research and Statistical Analysis Training for Teachers - Collection of R Practices from Sessions 13–20
Previously, I used to wonder whether I really needed to learn R when I already knew Python.Through this training, I realized that there’s actually no...

댓글을 불러오는 중...