목차(클릭하세요)
안티그래비티로 모든 선생님들의 로망: 진실의 자리바꿈을 구현해보자!
진실의 자리 바꿈이란?
같이 앉으면 안되는 학생들을 미리 셋팅하여 원활한 자리배치가 만들어지는 시스템
[깃허브 페이지]
•
클릭해서 전체 파일 확인가능!
[시작전 주의사항]
•
기능이 많다보니 절대 한번에 완성될 수 없음을 인지하고, 중간중간 브레이크 포인트로 저장
1. 래퍼런스 자료 찾기
•
자리바꾸기 프로그램 샘플을 찾아서
1-1. 전설중의 전설: 김명식 허명성의 과학사랑
•
김정식 수석 선생님의 자리바꾸기, 아마 교사라면 한번쯤은 이 프로그램을 보지 않았을까?
•
리스펙! 그 잡채!
•
파일 업로드
•
해당 설명서를 면밀히 분석해보고, 업그레이드 할 부분, 내 입맛에 맞게 수정할 부분을 취사선택하기
•
생성형AI를 활용해 해당pdf파일을 넣고 특장점을 먼저 분석하기
[이유]안티그래비티는 pdf파일 업로드 기능이 현재는 없음
•
이후 안티그래비티에 전달할 제작 명세서 요청하기
•
명세서 예시
** 자리바꾸기 웹 애플리케이션 개발 명세서**
📌 프로젝트 개요
- 프로젝트명: ClassSeat Manager (가칭) - 스마트 자리 배치 시스템
-개발 목적: 기존 데스크톱 기반 "자리바꾸기 5.0" 프로그램을 웹 기반으로 재구현하여, 구글 스프레드시트 연동을 통한 실시간 학생 데이터 관리 및 자리 배치 자동화를 구현
- 개발 의뢰자: 광양고등학교 AI교육 담당교사 (yangPhago)
- 참고 자료: 자리바꾸기 5.0 (이천중학교 김정식 수석교사 제작)
-설명서: 첨부된 PDF 문서
🎯 핵심 요구사항
1. 구글 생태계 완전 연동
데이터 입력: 구글 스프레드시트에서 학생 정보 가져오기
데이터 출력: 배치 결과를 구글 스프레드시트에 자동 저장
인증: Google OAuth 2.0 기반 로그인
백엔드: Google Apps Script (GAS) 활용
2. 웹 기반 반응형 UI
PC, 태블릿, 모바일 모두 지원
실시간 미리보기
직관적인 드래그 앤 드롭 인터페이스
3. 교육 현장 특화 기능
학생들과 함께 화면을 보며 실시간 자리 배치
다양한 화면 효과로 공정성 인식 강화
교사의 교육적 의도 반영 가능한 고급 기능
📊 데이터 구조
구글 스프레드시트 입력 형식
Sheet 1: 학생 기본정보
| 번호 | 이름 | 성별 | 특이사항 | 비고 |
|------|--------|------|-----------------|------|
| 1 | 김철수 | 남 | 시력약함 | |
| 2 | 이영희 | 여 | | |
| 3 | 박민수 | 남 | 휠체어 사용 | |
| 4 | 최지우 | 여 | ADHD, 앞자리 필요 | |
필드 설명:
번호 (필수): 학생 번호 (정수)
이름 (필수): 학생 이름 (문자열)
성별 (필수): "남" 또는 "여" (문자열)
특이사항 (선택): 자리 배치 시 고려사항 (문자열)
비고 (선택): 기타 메모 (문자열)
Sheet 2: 자리 배치 이력 (자동 생성)
| 날짜 | 시간 | 좌석번호 | 학생번호 | 학생이름 | 고정여부 |
|------------|-------|----------|----------|----------|----------|
| 2025-01-26 | 09:00 | A1 | 1 | 김철수 | N |
| 2025-01-26 | 09:00 | A2 | 2 | 이영희 | Y |
Sheet 3: 레이아웃 설정 (자동 생성/수정)
| 레이아웃명 | 좌석배치JSON | 생성일 |
|------------|--------------|------------|
| 기본6x5 | {...} | 2025-01-26 |
| 모둠4x4 | {...} | 2025-01-26 |
🎨 UI/UX 설계
메인 화면 구성
┌─────────────────────────────────────────────────────────┐
│ ClassSeat Manager [구글 계정] [설정] [도움말] │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────────────────────────────┐ │
│ │ 컨트롤 패널 │ │ 자리 배치 영역 │ │
│ │ │ │ │ │
│ │ 📊 학생정보 │ │ [교탁] │ │
│ │ 🎲 자리배치 │ │ │ │
│ │ ⚙️ 레이아웃 │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ 💾 저장/불러오기│ │ │김철수│ │이영희│ │박민수│ │최지우│ │ │
│ │ 🖨️ 출력 │ │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ │
│ │ 🎬 화면효과 │ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │ │ │
│ └─────────────┘ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │최수민│ │박지성│ │김나영│ │이하은│ │ │
│ │ │ 5 │ │ 6 │ │ 7 │ │ 8 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ └──────────────────────────────────┘ │
│ │
│ [상태바] 총 30명 | 남 15명, 여 15명 | 고정 2명 │
└─────────────────────────────────────────────────────────┘
좌석 카드 디자인
┌──────────────┐
│ 김철수 👨 │ ← 성별 아이콘
│ 1번 │ ← 학생번호
│ [🔒/○] │ ← 고정 토글 버튼
└──────────────┘
↑
클릭 시 선택 (검정 테두리)
좌석 상태 표시:
일반 상태: 연두색 배경
선택 상태: 빨간색 테두리
고정 상태: 자물쇠 아이콘 + 붉은색 버튼
남학생 지정 좌석: 파란색 테두리 (M 표시)
여학생 지정 좌석: 핑크색 테두리 (F 표시)
빈 좌석: 회색 점선 테두리
🔧 기능 명세
Phase 1: 필수 기능 (MVP)
1.1 구글 연동
javascript기능: 구글 스프레드시트 연동
- 사용자 Google OAuth 인증
- 스프레드시트 URL 입력 및 연결
- 학생 데이터 실시간 가져오기 (Fetch)
- 배치 결과 자동 저장 (Update)
API 엔드포인트 (Google Apps Script):
- GET /students : 학생 목록 조회
- POST /save-arrangement : 배치 결과 저장
- GET /layouts : 저장된 레이아웃 조회
- POST /save-layout : 레이아웃 저장
1.2 기본 자리 배치
javascript기능: 무작위 자리 배치
- [자리배치] 버튼 클릭 시 랜덤 배치
- Fisher-Yates 셔플 알고리즘 사용
- 애니메이션 효과 (카드 섞기)
- 배치 완료 후 상태 표시
입력: 학생 목록, 좌석 수
출력: 학생-좌석 매핑 객체
1.3 수동 자리 조정
javascript기능: 드래그 앤 드롭 자리 변경
- 학생 카드 드래그
- 다른 학생 카드에 드롭하여 위치 교환
- 실시간 미리보기
- Undo/Redo 기능 (최대 10단계)
라이브러리: react-beautiful-dnd 또는 dnd-kit
1.4 자리 고정
javascript기능: 특정 학생 좌석 고정
- 학생 카드의 고정 버튼 클릭
- 고정된 학생은 랜덤 배치 시 제외
- 시각적 표시 (자물쇠 아이콘)
- 고정 해제 가능
상태 관리:
- students 배열에 isFixed: boolean 플래그 추가
1.5 남녀 구분 배치
javascript기능: 성별 기반 자리 배치
- [남학생자리표시] 모드 활성화
- 원하는 좌석 클릭하여 남학생 좌석 지정
- 자동 남녀 배치 또는 수동 배치 선택
- 남학생 수 ≠ 남학생 좌석 수 시 경고
로직:
1. 남학생 좌석 선택 (파란 테두리)
2. 남학생 수 === 선택된 좌석 수 → [남녀자동배치] 옵션 활성화
3. 자동 배치: 남학생 → 남학생 좌석, 여학생 → 여학생 좌석
4. 수동 배치: 성별 불일치 시 고정 불가 처리
1.6 구글 시트 저장
javascript기능: 배치 결과 자동 저장
- [저장] 버튼 클릭 시 Google Sheets에 기록
- 저장 내용: 날짜, 시간, 좌석-학생 매핑, 고정 여부
- 저장 완료 알림
- 실패 시 재시도 옵션
Google Apps Script 함수:
function saveArrangement(data) {
const sheet = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName('자리배치이력');
// 데이터 삽입 로직
}
Phase 2: 고급 기능
2.1 책상 레이아웃 커스터마이징
javascript기능: 자유로운 책상 배치
- [책상배치하기] 모드 진입
- 드래그로 책상 위치 이동
- 책상 추가/삭제
- 레이아웃 프리셋 (6x5 기본형, 4x4 모둠형, ㄷ자형 등)
- 책상배치모드 페이지에서 마우스 드래그를 통해 2개 이상의 책상을 한꺼번에 이동할 수 있도록 기능
- 커스텀 레이아웃 저장
데이터 구조:
{
layoutName: "모둠형",
desks: [
{ id: 1, x: 100, y: 50, width: 80, height: 60 },
{ id: 2, x: 200, y: 50, width: 80, height: 60 },
...
]
}
2.2 화면 효과
javascript// 효과 1: 카운트다운
기능: 자리 배치 전 카운트다운
- "3... 2... 1... 배치!" 애니메이션
- 긴장감 조성 및 공정성 인식
- 효과 ON/OFF 토글
// 효과 2: 덮개 효과
기능: 제비뽑기 스타일 공개
- 배치 완료 후 모든 학생 카드에 덮개 표시
- 클릭 시 하나씩 공개
- 뒤집기 애니메이션
- 전체 공개 버튼
2.3 이전 배치 중복 방지
javascript// 기능 1: 이전 자리 안앉기
- 바로 직전 배치와 비교
- 같은 좌석에 배치 시 재배치
- 최대 재시도 횟수 설정
// 기능 2: 이전 짝꿍 안앉기
- 최근 N회 짝꿍 이력 조회
- 같은 짝꿍 배치 시 재배치
- 짝꿍 정의: 좌우 인접 좌석
알고리즘:
function avoidPreviousSeat(currentArrangement, history) {
// 이력에서 충돌 검사
// 충돌 시 스왑 후 재검사 (최대 10회)
}
2.4 의도적 배치 (CTRL+배치)
javascript기능: 교사가 미리 정한 순서대로 배치
- UI에서 원하는 배치 수동 작성
- [CTRL+C] 기능: 현재 배치를 저장
- [의도적배치] 버튼: 저장된 순서로 배치
- 학생들에게는 "랜덤"으로 보임
사용 시나리오:
1. 교무실에서 미리 배치 작성
2. 저장 (CTRL+C 대체 기능)
3. 교실에서 몇 번 랜덤 배치 시연
4. "이번엔 진짜다!" → [의도적배치] 클릭
5. 미리 정한 순서로 배치 (우연 가장)
여기까지 이해했다면, 아직 작업을 시작하지 말고 , ok해봐
JavaScript
복사
•
확인 결과
1-2.추가할 기능 미리 생각하기
•
이미 다 만들어진 다음 기능을 추가하다보면 생각보다 오류발생률이 높으므로 처음부터 새로운 기능까지 제시해서 안티그래비티를 이해시킨 다음 작업을 진행하도록!!
•
구글 스프레드 시트 연동을 통해 시트를 별도로 관리할 예정
◦
학생 명렬표 구글 시트
◦
자리배치를 저장할 시트
◦
교사 진심을 반영한 비밀 요구사항 시트
•
추가 기능 예시 프롬프트
구글 스프레드시트와 구글 앱스 스크립트를 활용할꺼야.
- 원본파일 주소: https://docs.google.com/spreadsheets/d/1Rjxf6jR_Dkp101iEeZ8xlYe_KZKK7SUJm0eqSXN6POs/copy
- 학생 명렬표 구글 시트 '학생명렬'
- 교사 진심을 반영한 비밀 요구사항 'hidden'시트
- 자리배치를 저장할 시트 주소(앱스 스크립트 활용)
1. '학생 명렬'시트의 B열에 학번, C열에 이름, D열에 성별, E열에 특이사항, F열에 비고가 적어져 있어. 해당 시트에서 데이터를 읽으면 되
2. 교사 진심을 반영한 'hidden'시트주소에 는 다음 4가지 정보가 있어
-짝궁으로 배치되면 안되는 학생
-같이 배치해주어야 할 학생
-가장 뒷줄로 보내면 안되는 학생
-맨 앞줄로 보내야 하는 학생
이 4가지 정보는 우선순위가 가장 높아. 이것을 반영하여 자리를 배치하는 거야. 무엇보다 이 정보는 학생들에게 절대 유출되어서는 안되. 극비보안 사항이야.
3. 나머지는 먼저 제시한 개발명세서를 따라 웹페이지로 구축해.
4. 자리배치가 완성되면 자리배치를 저장할 시트인 '배치결과'에 결과를 저장해(앱스 스크립트 활용)
앱스 스크립트에 들어가는 코드는 너가 작성해서 알려줘
JavaScript
복사
1-3.image와 sava저장폴더 준비
나중에 출력할 때 번호나 사진도 함께 출력할 수 있도록 내가 학생 사진을 'image'폴더에 담아 저장할꺼야.
1. 만약 image폴더에 사진이 있다면 자리배치할 때 웹 페이지에 학생 사진도 함께 출력해줘. 만약 사진이 없다면 그냥 번호와 이름만 출력해
2. 배치된 결과를 '최종저장'버튼을 누르면 'save'폴더에 해당 날짜를 이름으로 한 엑셀 또는 메모장 파일이 저장될 수 있도록 코드 추가해.
JavaScript
복사
1-4.기타 주의사항
#주의사항
- 가장 안정적인 방법인 Tailwind CSS v3의 표준 설정사용
- 오류없이 가장 확실한 Tailwind CSS v3 표준 설정 복구 방법으로 진행
- 플러그인 오류 없도록 처음부터 Tailwind CSS연결 테스트
JavaScript
복사
어느정도 원하는 기능이 완성되었다면, 기타 기능을 추가하기전 브레이크포인트로 중간저장
1-5.추가기능 및 사진
•
자리배치를 위한 페이지 추가
웹페이지를 총 2개로 구성할꺼야. 메인페이지 말고, 자리 배치 전용페이지를 만들어
- 원하는 대로 책상배치를 바꿀 수 있는 페이지야.
- 책상을 마우스로 드래그해서 원하는데로 배치할 수 있는 페이지
- 자리배치를 바꾼 후 저장 버튼을 누르면 책상배치도 함께 자동으로 저장됨
- 책상배치가 바뀌면 메인 페이지에 있는 책상배치도 연동되면 되겠지?
아래 이미지 참고해
JavaScript
복사
•
자잘한 기능들 추가하기
다음 기능들을 메인페이지에 옵션으로 선택할 수 있도록 추가해봐
1. 화면 효과 극대화 하기: 자리배치 클릭시 이펙트를 보다 더 임팩트 있도록
2. 덮개효과 켜기: 사용자가 마우스를 클릭했을때 이름이 나오도록 숨김처리
3. 이전 자리 안앉기 체크박스
4. 이전 짝궁 앚앉기 체크박스
5. 남녀 자동배치: 최대한 남녀 성비에 맞춰, 남녀 짝궁으로 배치하되,성비가 맞지 않을 경우에는 알아서 배치
JavaScript
복사
•
구현이 안된 기능들, 특히 UI와 관련된 부분은 반드시 확인 필요
🎨 UI/UX 설계
메인 화면 구성
┌─────────────────────────────────────────────────────────┐
│ ClassSeat Manager [구글 계정] [설정] [도움말] │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────────────────────────────┐ │
│ │ 컨트롤 패널 │ │ 자리 배치 영역 │ │
│ │ │ │ │ │
│ │ 📊 학생정보 │ │ [교탁] │ │
│ │ 🎲 자리배치 │ │ │ │
│ │ ⚙️ 레이아웃 │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ 💾 저장/불러오기│ │ │김철수│ │이영희│ │박민수│ │최지우│ │ │
│ │ 🖨️ 출력 │ │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ │
│ │ 🎬 화면효과 │ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │ │ │
│ └─────────────┘ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │최수민│ │박지성│ │김나영│ │이하은│ │ │
│ │ │ 5 │ │ 6 │ │ 7 │ │ 8 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ └──────────────────────────────────┘ │
│ │
│ [상태바] 총 30명 | 남 15명, 여 15명 | 고정 2명 │
└─────────────────────────────────────────────────────────┘
좌석 카드 디자인
┌──────────────┐
│ 김철수 👨 │ ← 성별 아이콘
│ 1번 │ ← 학생번호
│ [🔒/○] │ ← 고정 토글 버튼
└──────────────┘
↑
클릭 시 선택 (빨간 테두리)
좌석 상태 표시:
일반 상태: 연두색 배경
선택 상태: 빨간색 테두리
고정 상태: 자물쇠 아이콘 + 붉은색 버튼
남학생 지정 좌석: 파란색 테두리 (M 표시)
여학생 지정 좌석: 핑크색 테두리 (F 표시)
빈 좌석: 회색 점선 테두리
JavaScript
복사
[책상 레이아웃 관련 설정]
템플릿을 수정해야해
1. 3분단용: 전체 책상을 3분단으로 나누어, 짝궁포함하여 배치, 즉 6줄
2. 4분단용: 전체 책상을 4분단으로 나누어, 짝궁 포함하여 배치, 즉 8줄
3. 5분당용: 전체 책상을 5줄로 배치, 짝궁 미포함, 5줄
4. 모둠용 4분단: 전체 책상을 4분단으로 나누고, 4명 1팀으로 책상 배치
5. 모둠용 3분단: 전체 책상을 3분단으로 나누고, 4명 1팀으로 책상 배치
JavaScript
복사
[저장/시트저장/불러오기 기능 관련]
이제 이 레이아웃처럼 저장/시트저장/불러오기 기능을 버튼 컴포넌트로 만들고, 기능을 구현하자
1. '저장'을 누르면 해당 페이지가 이미지 상태로 'save'폴더에 저장
2.'시트저장'을 누르면 구글 앱스스크립트를 활용해 구글 시트에 저장: 시트이름은 '~월달 배치결과'
3. 불러오기 기능을 누르면 구글시트를 파일을 불러와서 화면에 출력할 수 있도록
복잡할 수 있으니 단계별로 오류없이 점검해가면 진행해
JavaScript
복사
2. 사전 준비
2-1. 학생 명렬표 구글 시트
•
순서, 학번, 이름, 성별, 특이시항, 비고 등
2-2.자리배치를 저장할 시트
•
구글 시트에 ‘ ~’월 형태로 저장
•
이를 위해 구글 앱스 스크립트 기능 활용
•
실제 데이터 저장은 로컬 폴더의 ‘save’폴더로 별도 설정
2-3.교사 진심을 반영한 비밀 요구사항 시트
•
사전에 별도 시트에 해당 내용을 기록
•
현재 교실에 필요한 기능을 4가지로 간추려 정리함
3. 작업 및 결과물 확인
3-1. 체크사항
•
학생수가 변경됨에 따라 레이아웃도 자동으로 변경되는지 확인
•
언제나 학생수가 고정된 것은 아니니까
자 이제 코드를 수정해야해.
학생수가 언제나 30명인 것은 아니야
1. 학생수는 구글 스프레드 시트에 있는 숫자를 기준으로 셋팅되어야해.
2. 이말은 곧 레이아웃도 학생수에 따라 유동적으로 배치가 바뀌어야 한다는 거지. 따라서 구글 스프레드 시트로 학생들을 불러온 다음 초기 레이아웃과 초기 배치를 자동으로 변경되도록 코드 수정해
# 핵심: 책상 레이아웃을 정하는 페이지의 초기 템플릿 역시 학생수에 맞춰서 자동변경되도록 변경해
JavaScript
복사
•
30명일때의 초기 레이아웃
•
24명일때의 초기 레이아웃
3-2. 점검 또 점검
1.
카운트 효과 및 효과음
1. 카운트 효과를 추가하자.
- 새 자리배치를 선택하면
3,2,1이 화면에 나타난뒤 결과가 나오도록 수정해
2. 폭죽효과를 강화하자
- 화면이 흔들리는 효과를 보다 키우고
- 이펙트를 지금보다 4배정도 업그레이드 해
- 이펙트 효과에 풍선 터지는 효과도 추가
3. 효과음 소리를 선택할 수 있는 체크박스를
왼쪽 UI에 포함시켜
- 체크박스에 선택하면, 3,2,1 카운트 소리와 폭죽소리를 들을 수 있어야 해
- 카운트 다운 소리재생을 위해 Web Audio API를 도입해
JavaScript
복사
2.
구글 시트 저장시 편의성 개성
구글시트 저장을 눌렀을때는 시트번호 순서대로 오름차순으로 정렬해서 저장될 수 있도록 코드 수정해
- 학생번호 1번부터가 아니라 시트번호1번부터 오름차순으로
JavaScript
복사
3.
가장 중요한 배치 오류는 반드시 더블체크
1.남녀자동배치를 클릭했을때는 되도록 남자와 여자가 함께 앉을 수 있도록 배치되어야 하는데, 이 부분 다시 확인해봐
2.지금 hidden 시트에 따르면 곽현우 학생은 자리배치시에 맨뒤로 가면 안되고 1~2줄로 가야하는데, 반영된거 맞아? 테스트해봤는데 맨뒤로 배치되었어
3. 특히, 남학생, 여학생 좌석을 고정한 다음 배치했을때, hidden 시트에 따르면 곽현우 학생은 자리배치시에 맨뒤로 가면 안되고 1~2줄로 가야하는데, 반영된거 맞아? 테스트해봤는데 맨뒤로 배치되었어
4. 알고리즘 고도화 과정에서 발생한 로직 충돌 및 연산 오류를 꼭 점검해.
JavaScript
복사








