교육계획안 작성 도구 만들기

미키오·2024년 10월 7일
3

Gapple

목록 보기
3/4
post-thumbnail

0. 들어가며

유아교육에서 교육계획안이란 유아의 발달과 학습을 체계적으로 지원하기 위해 교육 활동을 계획하고 조직한 문서이다. 교육계획안은 유아의 전인적 발달을 도모하고, 다양한 활동을 통해 유아의 흥미와 필요를 반영하여 교육 목표를 달성할 수 있도록 하는 중요한 도구이다.

사범대를 다니면서 수많은 교육계획안을 작성해야 했다.
특히 사범대 특성상 팀 프로젝트가 많았고, 팀 단위로 협업하여 하나의 교육계획안을 완성해야 했다. 처음에는 한글 파일 하나 던져주고 다 같이 써오라는 방식이 일반적이었다. 처음에는 과방에 모여 한 사람이 컴퓨터로 타이핑하고 옆에서 구두로 내용을 써내려가는 일이 잦았다.

그러다 새내기 시절, 좀 더 효율적인 방법을 제안하며 한글 파일을 구글 독스로 이관하고, 이를 과 톡방에 공유했다. 이렇게 하니 팀원들이 각자 집에서 동시에 협업할 수 있었다. 이 방식은 특히 코로나 시기때 빛을 발하며 2021년 말쯤에는 교류가 없던 동기들마저 거의 모든 팀이 구글 독스를 사용하게 되었다.

부트캠프를 거치고 개발 공부를 위해 1년간 휴학하면서 개발자들이 사용하는 다양한 도구들 (트렐로, 노션, 피그마, 깃허브 등)을 접하게 되었다. 그중 학부 수업에서도 쓸 수 있을 만한 것들을 학우들에게 소개하고 싶어서 그 일환으로 구글 독스에서 노션으로 교육계획안 데이터를 이관해 협업하려 했다. 노션의 데이터베이스 기능을 통해 연령과 활동 유형 같은 고정된 데이터를 쉽게 관리할 수 있었다.

하지만 기존 한글 파일 작업에 익숙한 예비 교사들에게는 노션이 다소 어려웠다.
Markdown 문법을 알아야 하고, 방대한 기능과 복잡한 조작법이 진입장벽이 되었다.

특히 교육계획안에 특화된 표 형식을 만드는 데 제약이 있었고, 현장에서 노션과 MD 문법을 사용할 일이 없는 예비 교사들에게는 불필요한 학습 부담이 있었다. 그러나 노션의 데이터베이스 기능을 활용해 교육계획안의 고정된 데이터를 쉽게 관리할 수 있다는 점은 분명한 장점이었다.

이 과정을 거치면서 "교육계획안 작성에 특화된 웹 도구를 만들고 싶다"는 생각을 하게 되었다.

1차 스프린트에서는 실제 유아교사들을 초대해 계획안 만들기 페이지에 대해 논의했다.
처음에는 단순히 <select><input> 태그를 사용해 사용자가 데이터를 입력하는 방식을 도입했다.

"활동 유형의 종류가 너무 적어서 현장과 괴리가 있다",
"더 직관적인 UI가 필요하다" 등의 의견이 나왔다.
어떻게 하면 웹의 장점을 더 살릴 수 있는지 고민해보았다 🤔

1. 쉬운 UI 제공하기

앞서 교사들이 언급했듯이,
유치원 교사들에게 가장 친숙한 UI는 네이버 블로그나 게시글 작성 형식이었다.

Gapple에서도 최대한 간단한 UI를 제공하려고 노력했다.
네이버와 더불어 직관적인 UI의 끝판왕인 Velog의 작성 페이지를 분석해보았다.

  • 제목을 상단에, 무조건 크게
  • 네이버의 경우 제목 하단부터 자율성이 엄청나다는게 느껴진다. 그러나 교육계획안에서는 준수해야하는 고정 형식이 있으므로 이 정도의 자율성은 필요가 없다.
  • 벨로그의 제목 하단에는 태그 입력칸이 있다. 태그는 SEO에 꽤나 핵심적이다.

교육계획안의 태그에 해당하는 것이 무엇이 있을까 고민해본 결과, 바로 수업 전체를 관통하는 ‘주제’와 ‘세부 주제’가 있을 것이다. 그러나 여러개의 키워드를 다는 태그와 달리 보통 주제와 세부주제는 딱 한 가지씩 가져가므로 하나의 키워드만 작성할 수 있는 input 창을 만들었다.

2. 귀엽"개" 디자인하기

컴퓨터 공부를 하면서 점점 무채색적인 디자인을 선호하게 되었지만,
유아교육계에서는 귀여움이 중요한 요소임을 다시 깨달았다.

기획 단계에서 유아교사들과 유아교육과 사람들을 인터뷰해본 결과
확실히 귀여운걸 좋아해서 그 길을 선택한 사람들이라 그런가
시크함, 간단함, 전문적인 분위기보다 ‘귀여운 분위기’를 선호하는 듯 했다.

그러다 문득 Generate AI PLanner를 줄여서 GAPL 이라 지었는데


개 + 애플? 이 무의식적으로 생각이 나서 2차 기획에서 이 그림을 그려갔다.

대표 캐릭터가 생겼다는 사실에 다들 좋아해주었다.
이어서 중대유교 대표 금손 G양이 캐릭터를 디벨럽을 시켜주었고..

이어서 색감에 관한 샘플도 여러가지 뽑아갔다.

귀여움강아지, 사과 등 사이트의 모티브가 되는 요소들을 생각해보았을때
1번 시안이 활용도가 가장 높을 것이라 판단하여 4명 중에 3명이 1번을 1등으로 뽑았다.

3. 고정 데이터 넣기

유치원 교육계획안에는 명확한 컨벤션이 존재한다.
교육부의 2019 개정 누리과정 현장지원 자료를 오랜만에 꼼꼼하게 숙지하고
고정 데이터를 반영했다.

대표적으로 3,4,5세로 이루어진 연령,

소집단(5명 이하), 중집단(5~10명), 대집단(10명 이상)으로 이루어진 집단 규모,

요리, 이야기나누기, 음악 감상, 과학 실험, 신체 활동 등으로 이루어진 다양한 활동 유형이 있다.


export const AGE = [
    { label: '만 3세', value: '3', image: '/images/age/age3.png' },
    { label: '만 4세', value: '4', image: '/images/age/age4.png' },
    { label: '만 5세', value: '5', image: '/images/age/age5.png' },
  ];

export const GROUP_SIZE = [
    { label: '소집단', value: 'small', image: '/images/group/small.png' },
    { label: '중집단', value: 'medium', image: '/images/group/medium.png' },
    { label: '대집단', value: 'large', image: '/images/group/large.png' },
  ];
  
export const CATEGORY = [
  { name: '요리', value: 'cook', image: '/images/category/cook.png' },
  {
    name: '음악감상',
    value: 'musicListen',
    image: '/images/category/musiclisten.png',
  },
  { name: '노래 부르기', value: 'sing', image: '/images/category/sing.png' },
  {
    name: '악기 연주',
    value: 'playInstrument',
    image: '/images/category/playInstrument.png',
  },
  { name: '동극', value: 'musical', image: '/images/category/musical.png' },
  {
    name: '신체표현',
    value: 'bodyExpression',
    image: '/images/category/bodyExpression.png',
  },
  { name: '미술', value: 'art', image: '/images/category/art.png' },
  {
    name: '미술 감상',
    value: 'artWatch',
    image: '/images/category/artWatch.png',
  },
  { name: '동시', value: 'poetry', image: '/images/category/poetry.png' },
  { name: '게임', value: 'game', image: '/images/category/game.png' },
  { name: '이야기 나누기', value: 'talk', image: '/images/category/talk.png' },
  {
    name: '과학•실험',
    value: 'science',
    image: '/images/category/science.png',
  },
];

선생님들로부터 받은 데이터를 constant 파일에 넣고 앞서 G양이 제공해준 그림 또한 반영했다.

const AgeSelect = ({ options, onSelect }: AgeSelectorProps) => {
  const [selectedValue, setSelectedValue] = useState<string | null>('3');

  const handleAgeClick = (value: string) => {
    onSelect(value);
    setSelectedValue(value);
  };

  return (
    <>
      <h1 className={'title-effect'}>{'연령 선택'}</h1>
      <div className={'flex justify-center laptop:justify-start items-center'}>
        <div className={'grid grid-cols-3 gap-x-3'}>
          {options.map((option) => (
            <button
              type={'button'}
              key={option.value}
              onClick={() => handleAgeClick(option.value)}
              className={`focus:outline-none bg-transparent border-4 transition duration-300 ease-in-out 
                         ${option.value === selectedValue ? 'border-primary300' : 'hover:border-gray-300 border-transparent'}`}
            >
              <Image
                width={100}
                height={100}
                src={option.image}
                alt={`${option.value}`}
                className={'w-20 h-20 laptop:w-28 laptop:h-28'}
              />
              <div className={'text-slate-700 text-xs '}>{option.label}</div>
            </button>
          ))}
        </div>
      </div>
    </>
  );
};

export default AgeSelect;

상태 관리와 이벤트 핸들링을 통해, 사용자가 버튼을 클릭할 때마다
즉각적인 시각적 피드백을 받을 수 있게 선택된 항목은 다홍색 네모로 선택 표시를 해두었다.

또한 보통 교사들이 수업을 고안할때
연령, 집단규모, 활동 유형은 미리 정해놓고 가는 것을 반영하여 가장 상단에 배치했다.

4. 누리교육과정 반영하기 (계층적 데이터 구조 렌더링)

다음은 제일 어려웠던 누리교육과정 반영이다.

누리과정이란 2019년부터 반영된 3~5세 유아를 위한 국가 수준의 공통 교육과정이다.

따라서 유치원과 교육기관에서는 교육계획안 수립 시 각 영역별 (신체운동건강, 의사소통, 사회관계, 예술경험, 자연탐구) 목표 및 내용을 숙지하고 수업과 놀이에 반영해야 한다.

이것이 은근히 불편했던 이유가 데이터는 고정되어 있지만
수업을 만들 때마다 늘 옆에 교육부 누리과정 고시문을 펼쳐놓고
하나하나 찾아서 수기로 작성해야한다는 점이었다.

가장 먼저 한 일은 중첩된 배열과 객체 형식으로 되어 있는 데이터 변환이었다.

혹시라도 JSON으로 제공하는 공공 데이터가 있나 찾아보았는데 찾는 것에 실패해서 직접 자바스크립트로 이관했다.

export const nurriCurriculum: CurriculumCategory[] = [
  {
    '신체 운동 • 건강': [
      {
        '신체활동 즐기기': [
          '신체를 인식하고 움직인다.',
          '신체 운동능력을 조절한다.',
          ...
        ],
        '건강하게 생활하기': [...],
        '안전하게 생활하기': [...],
      },
    ],
    '의사소통': [...],
    '사회관계': [...],
    ...
  }
];

이를 통해 nurriCurriculum 배열은 다양한 학습 카테고리와 관련 세부 사항을 포함한다. 또한, 각 카테고리는 하위 카테고리와 그에 해당하는 세부 항목들로 구성된다. 이 계층적 데이터는 UI에서 사용자의 선택에 따라 동적으로 내용을 표시하는 데 사용된다.

이어서 백엔드 개발자와 함께 DB에도 반영했다.

-- Categories 테이블 생성
CREATE TABLE categories (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

-- Subcategories 테이블 생성
CREATE TABLE subcategories (
    id INT AUTO_INCREMENT PRIMARY KEY,
    category_id INT,
    name VARCHAR(255) NOT NULL,
    FOREIGN KEY (category_id) REFERENCES categories(id)
);

-- Details 테이블 생성
CREATE TABLE details (
    id INT AUTO_INCREMENT PRIMARY KEY,
    subcategory_id INT,
    description TEXT,
    FOREIGN KEY (subcategory_id) REFERENCES subcategories(id)
);

-- Categories 데이터 입력
INSERT INTO categories (name) VALUES
('신체 운동 • 건강'),
('의사소통'),
('사회관계'),
('예술경험'),
('자연탐구');

-- Subcategories 및 Details 데이터 입력
-- 신체 운동 • 건강
INSERT INTO subcategories (category_id, name) VALUES
(1, '신체활동 즐기기'),
(1, '건강하게 생활하기'),
(1, '안전하게 생활하기');

INSERT INTO details (subcategory_id, description) VALUES
(1, '신체를 인식하고 움직인다.'),
(1, '신체 운동능력을 조절한다.'),
(1, '기초적인 이동동작, 제자리 동작, 도구를 이용한 동작을 한다.'),
(1, '실내외 신체활동에 자발적으로 참여한다.'),
(2, '자신의 몸과 주변을 깨끗이 한다.'),
(2, '몸에 좋은 음식에 관심을 가지고 바른 태도로 즐겁게 먹는다.'),
(2, '하루 일과에서 적당한 휴식을 취한다.'),
(2, '질병을 예방하는 방법을 알고 실천한다.'),
(3, '일상에서 안전하게 행동하고 사용한다.'),
(3, 'TV, 컴퓨터, 스마트폰 등을 바르게 사용한다.'),
(3, '교통안전 규칙을 지킨다.'),
(3, '안전사고, 화재, 재난, 학대, 유괴 등에 대처하는 방법을 경험한다.');
...

다시 리액트로 돌아와서 주안점을 두가지를 잡았다.

  1. 단계적으로 탐색할 수 있도록 설계하기 : 사용자가 클릭할 때마다 관련 항목이 열리도록 하여 복잡한 데이터를 시각적으로 쉽게 접근.
  2. 사용자 피드백: 선택된 항목은 배경색과 텍스트 색상이 변경되어 시각적으로 피드백을 제공하기.

가장 먼저 초기화된 데이터 상태를 선언했다.

  const initialState = [
    { selectedNurri: '', selectedSubNurri: '', selectedCurriculum: '' },
  ];

이후 하위에 CurriculumSection 컴포넌트와 CurriculumToggle 컴포넌트를 만들었다.

  • CurriculumSection : 전체 커리큘럼 요소를 포함하며, 각 요소를 선택하고 추가하거나 제거할 수 있는 기능을 제공한다. 이 컴포넌트는 여러 개의 CurriculumToggle 컴포넌트를 포함하여, 사용자가 카테고리와 하위 항목을 쉽게 탐색할 수 있게 한다.
  • CurriculumToggle : 사용자가 특정 카테고리를 선택하면 해당 카테고리의 하위 항목과 세부 사항을 표시한다. 이 컴포넌트는 각 버튼을 클릭했을 때 상태를 변경하는 방식으로 동작한다.

위의 CurriculumToggle 컴포넌트는 계층적 데이터 구조를 동적으로 렌더링하기 위해 아래와 같은 과정을 거친다.

카테고리 탐색 (find 메서드 사용)

find 메서드는 배열에서 조건을 만족하는 첫 번째 요소를 반환한다.
이 코드에서는 사용자가 선택한 카테고리selectedNurri (신체운동, 의사소통, 사회관계 등)를 기반으로 nurriCurriculum 배열에서 해당 카테고리의 객체를 찾는다.

const selectedCategory = nurriCurriculum.find((category) => {
  const categoryKey = Object.keys(category)[0];
  return categoryKey === selectedNurri;
});

이 코드는 selectedNurri와 일치하는 카테고리를 찾기 위해 객체 배열을 순회한다.

하위 카테고리 접근

selectedNurri를 사용하여 find 메서드의 결과로 얻은 객체에서 해당 카테고리의 값을(하위 카테고리 배열) 접근한다. 사용자가 특정 카테고리나 하위 카테고리를 선택할 때마다, 해당 선택에 따라 조건부로 렌더링이 이루어진다.

const subCategories = selectedCategory[selectedNurri];

하위 카테고리 매핑 (map 메서드 사용)

하위 카테고리 배열을 반복 처리하여 각 하위 카테고리와 해당 세부 사항을 동적으로 렌더링한다.
map 메서드를 사용하여 각 하위 카테고리에 대해 UI 요소를 생성할 수 있다.

<ul>
 {subCategories.map((subCategory) => {
   const subCategoryKey = Object.keys(subCategory)[0];
   const details = subCategory[subCategoryKey];
   return (
     <li key={subCategoryKey}>
       <button onClick={() => onSubNurriClick(subCategoryKey)}>
         {subCategoryKey}
       </button>
       <ul>
         {details.map((detail) => (
           <li key={detail}>
             <button onClick={() => onDetailClick(detail)}>
               {detail}
             </button>
           </li>
         ))}
       </ul>
     </li>
   );
 })}
</ul>

각 단계별로 map 함수를 사용하여 하위 항목을 반복적으로 렌더링한다. nurriCurriculum에서 카테고리, 하위 카테고리, 세부 사항을 순차적으로 탐색하여 각 버튼을 생성하고, 이를 통해 사용자가 인터랙티브하게 탐색할 수 있도록 한다.

각 세부 사항은 버튼으로 렌더링되며, 사용자가 클릭할 수 있는 형태로 제공된다.

<button
	type={'button'}
	onClick={(e) => onSubNurriClick(subCategoryKey, e)}
	className={`flex justify-center items-center 
				cursor-pointer w-48 p-2 hover:text-slate-900
				hover:bg-primary100 shadow-md ${isSelectedSubNurri
                          ? 'bg-primary100 text-slate-900'
                          : 'text-slate-700'
                      }`}
                    >
    {subCategoryKey}
</button>

이어서 선택된 항목은 배경색과 텍스트 색상이 변경되어 시각적으로 피드백을 제공하였다.

5. 기타 : 동적 데이터, 파일 업로드

유아교사의 자율성이 필요한 활동 내용, 활동 도구, 평가, 유의사항 등의 항목은 동적 데이터로 관리했다.

대부분 비슷한 로직이라 대표적인 Tool 로직을 예로 들겠다.

import React, { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';

interface Tool {
  id: string;
  value: string;
}

const ToolSection = () => {
  const [tools, setTools] = useState<Tool[]>([]);

  const addTool = () => {
    const newTool = { id: uuidv4(), value: '' };
    setTools([...tools, newTool]);
  };

  const removeTool = (id: string) => {
    setTools(tools.filter(tool => tool.id !== id));
  };

  const handleToolChange = (id: string, value: string) => {
    setTools(tools.map(tool => tool.id === id ? { ...tool, value } : tool));
  };

  return (
    <div>
      {tools.map((tool, index) => (
        <div key={tool.id}>
          <input
            type="text"
            value={tool.value}
            onChange={(e) => handleToolChange(tool.id, e.target.value)}
          />
          <button onClick={() => removeTool(tool.id)}>Remove</button>
        </div>
      ))}
      <button onClick={addTool}>Add Tool</button>
    </div>
  );
};

export default ToolSection;
  • 요소 추가: addTool 함수에서는 새 도구 객체를 생성하고 기존 배열에 추가한다. 이때 각 도구는 고유한 ID (uuid)를 가지므로 배열에서 쉽게 식별하고 관리할 수 있다.
  • 요소 제거: 특정 도구를 제거할 때는 해당 도구의 ID를 이용해 필터링하였다. filter 메소드를 사용하여 해당 ID를 제외한 새 배열을 생성할 수 있다.
  • 요소 수정: handleToolChange 함수에서는 입력 변경 사항을 감지하고 해당 도구의 상태를 업데이트한다.

파일 업로드는 이전 프로젝트에서 사용했던 드래그앤 드롭과 클릭 방식 모두 지원하도록 구현했다.

6. 마무리

이번 Gapple 프로젝트는 교육계획안 작성의 효율성을 높이는 것에 주안점을 두고 있다.
개인적으로는 한글 파일에서 구글 독스로, 다시 노션으로, 그리고 웹 개발을 통해 Gapple 까지 발전해 오면서 유아교육계에서 교육계획안을 작성하는 방식에 많은 변화를 시도해 보았다.

특히 교육계획안 작성 페이지에서는 친숙한 UI 제공, 고정된 데이터를 손쉽게 관리할 수 있는 기능, 귀여운 디자인 요소 도입 등 다양한 시도를 통해 사용자 경험을 극대화하고자 했다. 특히 누리과정을 반영한 계층적 데이터 구조와 직관적인 사용자 인터페이스는 유아교사들이 쉽게 사용할 수 있으리라 기대된다.

이번 프로젝트는 기술적으로 새로 사용한다던가 엄청 어려운 로직을 사용하지는 않지만 사용자들과의 정기적인 피드백을 통해 현장의 요구사항을 깊이 이해하고, 그것을 반영하기 위해 공부하고 더 나은 솔루션을 만들어 나가는 과정이 분명한 차별점이 있다는 것을 느꼈다.

유아교육 분야에서 기술이 가져올 수 있는 변화를 직접 경험하면서, 기술과 교육의 접점을 찾고 이를 통해 더 나은 교육 환경을 만드는 데 기여하고 싶다는 목표가 더욱 확고해지는 것 같다.

점차 완성되어 가는 Gapple 도구의 발전을 통해 많은 유아교사들이 효율적으로 교육계획안을 작성하고, 아이들에게 더 나은 교육을 제공할 수 있기를 기대한다 :)

profile
교육 전공 개발자 💻

4개의 댓글

comment-user-thumbnail
2024년 10월 7일

캐릭터와 색감이 너무 예뻐서 보기만 해도 기분이 좋아져요 🙂 사용자 집단의 특성을 잘 반영한 서비스네요!
저도 한국어 교육을 위해 교수계획안을 작성할 때 구글 독스로 협업했던 유사한 경험이 있는데, 딱딱한 UI와 데이터 활용의 불편함을 개선한 맞춤형 서비스는 정말 좋은 아이디어 같아요! 학우들을 위해 직접 개발하시다니 최곱니다

1개의 답글
comment-user-thumbnail
2024년 10월 9일

타켓층에 딱 맞춤형인 서비스네요,, 대단해요 👍🏻 응원합니다!!!!!

1개의 답글

관련 채용 정보