---
title: "강원과학고 기숙사•급식 출석관리 플랫폼"
url: https://agwo2.dev/kshs-dormitory-school-meal-platform
author: "채은우 (Eunwoo Chae)"
date: 2024-05-04
tags: ["Next.js", "Log", "Prisma", "공모전"]
summary: "학생증 기반의 기숙사 귀가 및 급식 출석관리플랫폼 개발 공모전 개발로그"
---

# 강원과학고 기숙사•급식 출석관리 플랫폼

### 개발목적

강원과학고는 주말에 학교에 들어올 때 학생이 학교에 들어왔는지 확인하기 위해 수기명부를 사용했었다. 작년 나는 해당 수기명부를 보고 웹을 통해 GPS기반으로 학생들이 체크인 하면 좋지 않을까? 라는 생각을 하긴 하였지만 이것저것 다른 일에 치여 실제로 구현은 하지 않았었다. 그런데 올해 학교 내부에서 주말에 들어오는 학생들에 대한 출석체크 프로그램 공모전이 열려서 해당 플랫폼을 개발하게 됐다. (다만, 웹기반이긴 하나 학교에서 요구하는 조건에 맞춰 개발하여 GPS기반 체크인 기능은 만들지 않았다.)

### 아이디어 구상

먼저 프로젝트를 구현하기 위해 아이디어 구상을 시작했다. 아래는 공모전 포스터 중 일부인데 학생증을 활용하여 출석인증을 구현하는 것이 가장 큰 목표였다. 학생증에는 기본적으로 앞면에 학생 사진과 이름 그리고 뒷면에는 각 학생별로 부여된 고유 바코드가 존재한다. 나는 이번 프로젝트에서 학생증 뒷면 바코드 인식을 통해 학생정보를 특정하고 해당 학생에 대한 출석을 인정하는 형태로 개발을 진행하고자 했다.

또한 응용프로그램으로 개발할것인지 웹 형태로 개발할 것인지도 신중히 선택했는데, 아무래도 출석체크 정보를 확인함에 있어 선생님들이나 담당자가 휴대폰으로 바로 확인할 수 있도록 하는 것이 편리할 것 같다고 판단하기도 했고 휴대폰을 통해 담당자가 플랫폼에 접근하여 출석체크를 할 수 있게 하여 플랫폼 사용에 대한 공간제약을 줄이면 좋을 것으로 생각하여 웹을 통해 프로그램을 구현하기로 하였다. 아래는 전체적인 플랫폼의 구상도이다.

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F8c603655-90a0-494e-8ab3-285fb7d7b87d%2FUntitled.png?table=block&id=039244bb-899f-47c8-b5b6-cc1a87bac056)

### 개발과정

#### 사용한 프레임워크

> Front & Back: NextJS

#### 학생증 바코드 리딩

바코드는 바코드 리더기가 있다면 매우 쉽게 인식이 가능하다 다만, 나는 이번 프로젝트에서 웹을 이용해 플랫폼에 접근하여 출석체크 등을 하게 할 생각이었다. 즉 태블릿과 같은 기기에서 위 플랫폼에 접근하여 카메라에 학생증을 입력해도 출석체크를 할 수 있게 말이다. 그래서 바코드 리더기를 통한 인식을 지원함과 동시에 카메라에서 학생증 바코드를 인식하여서도 출석체크를 할 수 있도록 개발하였다.

그런데 나는 python을 통해 바코드를 인식하는 것은 시도해본 적이 있지만 이번에 개발함에 있어 채택한 JS기반에서 바코드를 인식하는 것은 해본 적이 없었다. 하지만 다행히도 이미 만들어져 있는 라이브러리(**[@zxing/library](https://www.npmjs.com/package/@zxing/library)**)가 있어 이를 통해 카메라에서 바코드를 인식 받고 사전에 구성된 데이터베이스에서 바코드 아이디와 학생 정보를 대조하여 출석체크 기능을 구현하였다.

```javascript
const [localStream, setLocalStream] = useState<MediaStream | null>(null);
const cameraRef = useRef<HTMLVideoElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [displayMessage, setDisplayMessage] = useState('');

useEffect(() => {
  const initializeCamera = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: "user" },
      });
      setLocalStream(stream);
      if (cameraRef.current) {
        cameraRef.current.srcObject = stream;
      }
    } catch (error) {
      console.error('Camera initialization failed:', error);
      setDisplayMessage('카메라 접근에 실패했습니다.');
    }
  };

  initializeCamera();

  return () => {
    localStream?.getTracks().forEach(track => track.stop());
  };
}, []);

useEffect(() => {
  if (!cameraRef.current || !localStream) return;

  const hints = new Map();
  const formats = [
    BarcodeFormat.QR_CODE,
    BarcodeFormat.DATA_MATRIX,
    BarcodeFormat.CODE_128,
    BarcodeFormat.CODABAR,
    BarcodeFormat.EAN_13,
    BarcodeFormat.EAN_8,
    BarcodeFormat.CODE_39,
    BarcodeFormat.CODE_93
  ];
  hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);

  const scanner = new BrowserMultiFormatReader(hints, 500);
  scanner.decodeFromStream(localStream, cameraRef.current, (result, err) => {
    if (result) {
      handleBarcodeDetected(result.getText());
    }
  });

  return () => scanner.reset();
}, [localStream]);

const handleBarcodeDetected = (data: string) => {
  if (data !== lastBarcode) {
    setDisplayMessage('처리 중...⏳');
    sendScannedData(data);
  }
};
```

위 코드는 해당 라이브러리를 이용하여 카메라에서 받아온 정보에서 바코드 고유아이디를 추출하는 코드의 일부이다. 이때 인식할 수 있는 바코드 규격은 일부러 다양한 규격을 지원하게 해두었다. ~~(그래서 사실 자신의 학생증 고유아이디만 안다면 그걸로 다른 QR코드 같은 걸 만들어서 찍어도 출석이 가능하다.)~~

#### 로그인-회원가입 구현

아무래도 시간적으로 가장 많은 부분을 투자한 부분인 것 같다. 기능 자체는 매우 간단한데 생각보다 관련 개념을 이해하고 적용하기 까지가 시간이 오래걸렸던 것 같다. 처음부터 모두 구현하는 것이 아닌 NextAuth를 이용해 비교적 쉽게 구현 했음에도 생각보다 잘 되지 않았었다. 물론 현재 코드는 문제없이 구현되어 있지만 나중에 Django를 통해 다시 제대로 구현하면서 관련 개념을 정리할 생각이라 여기에 따로 관련 내용을 서술하지는 않겠다.

#### 컴포넌트화 및 폴더 구조화 지향

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F5dd4d2c4-17c0-43ef-99d3-df138ba7cac2%2F%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA_2024-05-04_%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB_2.05.20.png?table=block&id=473c7024-9153-451c-b22f-bd94a7790a0a)

그렇게 대단한 것은 아니지만 그간 내가 짰던 코드와 비교해서 이번 프로젝트에서 크게 달라진 점은 아마도 이것일 것이다. 나는 코딩을 함에 있어 재활용가능성 또는 확장가능성을 생각하고 코드를 짜지 않고 있었다. 그런데 불행하게도 그렇게 짜져 있는 작년 프로젝트에서 기능을 추가해야할 일이 생기는 바람에 매우 고생했었다. 그래서 이번에는 앞으로의 확장가능성과 코드를 최대한 재활용하기 편하게 짜보고자 했다. 물론 당연히 혼자 바로 적용하기는 힘들어서 github에서 여러가지 오픈소스를 보며 관련 틀을 잡고 참고해서 이번 코드를 짜봤다. 덕분에 이제는 새로운 기능을 추가할 일이 생겨도 쉽게 수정할 수 있게 되었다.

### 공모전 발표 PPT

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fb299f273-a99e-48bf-acf9-ddf12dfcbb1f%2F001.png?table=block&id=b44b67a7-a903-433d-a7c5-d21eef8bf96b)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F22d9a6b5-57e4-448f-b097-250238c057c6%2F002.png?table=block&id=5f0eb954-7035-4121-99a3-899a572a72eb)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F9182cd53-3d36-45f1-b69a-e5fefaa5fc8f%2F003.png?table=block&id=d65b5524-c097-4b6c-938e-22d60332b846)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fd47962df-304b-4005-9241-9038f5f46e9d%2F004.png?table=block&id=b28c9280-0d2b-4252-ae33-ef8b37973d2e)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Ff2eb1d68-d7c6-426b-8722-7ea6a5f80d27%2F005.png?table=block&id=b9dc8a14-7da9-44c7-9f2a-8d60608b3c52)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fe98ba990-d284-49eb-aea9-70193585ed2e%2F006.png?table=block&id=e22c4cfd-b322-4424-aeb7-a80fb42ad136)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F586593bf-5749-4bef-b17f-7c159f7fe350%2F007.png?table=block&id=dccb7bd6-e11b-4d43-b4be-68b5688c2f83)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fd0a73949-2699-439c-9b6f-b6692dea1785%2F008.png?table=block&id=6809e180-7e24-4137-9744-6d98742964ba)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Faee1a742-201c-41c4-b47c-41f8375380e2%2F009.png?table=block&id=a49d4773-b22a-41f0-ade2-290923465f37)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F9ddcb769-8372-47e4-94c8-5e7f15306bd2%2F010.png?table=block&id=b6416541-cd12-4ae6-8ce4-6d31bd132ffd)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2F0c17f64f-bac3-4108-95ea-1c0a72a8a251%2F011.png?table=block&id=e9ab15ab-b537-4dad-8de0-73f1d7eb793b)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fe8391b67-963e-4152-9a52-00398ed9d996%2F012.png?table=block&id=2fe88ee4-a777-4489-ad84-e9d4f9a5605a)

![](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F342e3572-6698-498c-b69e-db1b812e83c7%2Fa5c4cd5d-f51f-4d94-a50c-3b818a9dd5e3%2F013.png?table=block&id=0c1cc8bd-ed19-4196-a2d0-86f5780b7f67)

교내에서 진행한 공모전 최종발표에서 사용한 PPT이다. 프로젝트에 대한 간략한 내용이 들어 있으며 참고하길 바란다.

### 공모전 수상에 관하여

정말 감사하게도 교내 공모전에서 수상하여 상을 받을 수 있었다. 또한 5월 6일부터 위 플랫폼을 학교에서 이용한다고 하는 데 그 과정에서도 많은 것을 배울 것으로 생각하고 있다. 추가적으로 이번 공모전을 진행하며 학교가 그렇게 크지 않다보니까 친구와의 경쟁 아닌 경쟁에 대한 새로운 경험을 하게되었는데 이를 통해 심리적으로도 성장할 수 있는 계기가 되었다고 생각한다. 아래는 공모전 수상에 대해 보도한 MBC, 강원도민일보 기사를 첨부한다.

[https://www.youtube.com/watch?v=GrUNvpi7P5E](https://www.youtube.com/watch?v=GrUNvpi7P5E)

[“수기작성 불편” 고교생 직접 기숙사 출석 시스템 개발](https://www.kado.net/news/articleView.html?idxno=1239024)

---
출처: https://agwo2.dev/kshs-dormitory-school-meal-platform
