EZSET-전자출결-01-DB설계하기

Seok·2020년 12월 6일
0

EZSET

목록 보기
1/7
post-thumbnail

EZSET 프로젝트를 진행하면서 small-j와 함께 출석 파트를 담당했다. 출석 파트를 개발하는 과정을 기록해보려한다.


0.환경

서버는 Node.js를 프론트는 Vue.js를 데이터베이스는 MongoDB를 사용하기로했다.


1.목표

소목표로 잡았던 구현 할 기능들은 아래와 같다.

  1. 전자출결
  • 출결 시작시 랜덤코드 생성 및 화면에 띄움
  • 사용자들을 관리자 화면에 보이는 코드입력으로 출석
  1. 출결 조회
  • 월별 조회(관리자)
  • 월별 조회(사용자)
  • 일별 조회
  • 출결 상태 변경

2. DB설계 시작

이름,날짜,출결상태(출석/지각/결석/공결) 출결에 꼭 필요하다고 생각했던 항목들이다.

정말정말 단순하게 아래와 같은 형태의 Document를 작성 할 수 있겠지만

//document 예시_1
{
    	"name": "(사용자ID)",
	"day" : "(날짜)",
	"state" : "(출결정보)",
}

목표기능의 월별조회 일별조회 기능 구현을 생각해보면 조금 더 구조를 효율적으로 바꿔야 겠다고 생각했다.

위의 Document구조를 1년동안 적용 했을 때,
ALCUK의 작년 기준 회원수로 최대 40명으로 사용자를 잡고, 1년 동안 휴식하는 주를 12주 정도를 제외하고 40주, 주3회 스터디로 계산해본다면
40 X 3 X 40 = 4800개의 Document가 존재한다.

서버의 성능에 영향을 줄정도의 양은 아니라고 생각한다. 하지만 더 나은 구조가 있을거라고 생각했고, 계속 고민했다.

2-1. 조금 더

출결정보는 날짜를 단위로 형성된다. 그래서 날짜를 기준으로, 그리고 그 날짜의 정보들은 SubDocument를 이용하여 배열로 관리하는 방법을 생각했다.

//document 예시_2
{
	"day" : "(날짜)",
	"status": ["SubDocument","SubDocument", "..."]
}
//SubDocument
{
	"name":"(사용자명)",
	"state":"(출결정보)",
}

위와 같은 구조로 이제 날짜로 한개의 Document만 찾으면 그 Document의 SubDocument배열을 읽어주면 그날의 출석정보는 만족스럽게 해결할 수 있게되었다.

하지만 문제가 있었다.

일별출결현황 같은 경우는 날짜를 기준으로 데이터를 읽어오기 때문에 괜찮지만, 월별출결현황(사용자) 같은 경우는 사용자 별로 데이터를 읽어야해서 날짜를 찾고, SubDocument 배열에서 사용자 한명을 찾고, 그다음 날짜를 읽고 또 그 SubDocument배열에서 찾고를 반복해야한다.

즉 페이지별로 읽어오는 기준이 다르기때문에 한 항목을 기준으로 정해버리면 문제가 생기게 되었다.

2-2 조오금 더

지금까지 설계에 필요한 정보들을 정리해 보면

  1. 1년동안 출결정보가 쌓여도 4800개 정도이다.
  2. 페이지별로 기준이 되는 항목이 다르다.
  3. document 예시_1을 따르기에는 조금 더 효율적인 구조가 필요하다.

그래서 생각한 다음 구조는 데이터를 중복으로 가지고 있지만 두가지의 기준으로 가지고 있는 방법을 생각했다. 즉, 2개의 Collection을 사용하는 방법이다.

//날짜 기준 Collection
//document 예시_3
{
	"day" : "(날짜)",
	"status": ["SubDocument","SubDocument", "..."]
}
//SubDocument
{
	"name":"(사용자명)",
	"state":"(출결정보)",
}
//사용자 기준 Collection
//document 예시_3
{
	"name" : "(사용자명)",
	"status": ["SubDocument","SubDocument", "..."]
}
//SubDocument
{
	"day":"(날짜)",
	"state":"(출결정보)",
}

이렇게 된다면 1년동안의 최대 document 수는(SubDocument 기준) 9600 개로 2배가 되고, 정보 업데이트시 두개의 Collection을 항상 같이 업데이트 시켜줘야 한다는 단점이있지만, 조회 기능 페이지들에서 기준이 달라지더라고 효율적인 조회가 가능하다고 생각했다.

따라서 위의 구조를 최종 선택했다.


3 node.js 에서 Model 작성

AttendanceDays.js

  • 날짜를 기준으로 데이터를 저장하는 Collection의 Document 모델
//document
{
	"day" : "(날짜)",
	"status": ["SubDocument","SubDocument", "..."]
}
//SubDocument
{
	"name":"(사용자명)",
	"state":"(출결정보)",
}
var mongoose = require('mongoose')
var Schema = mongoose.Schema

const statusSchema = new mongoose.Schema({
    name: {
        type: String,
    },
    state: {
        type: String,
    },
})
const Status = mongoose.model('status', statusSchema)

var attendanceDaySchema = new Schema({
    day: {
        type: String,
        unique: true,
    },
    status: [statusSchema],
})

attendanceDaySchema.methods.addStatus = function(name, state) {
    this.status.push(
        new Status({
            name,
            state,
        })
    )
    return this.save()
}
module.exports = mongoose.model('attendanceDay', attendanceDaySchema)

AttendanceDays.js

  • 사용자를 기준으로 데이터를 저장하는 Collection의 Document 모델
//document
{
	"name" : "(사용자명)",
	"status": ["SubDocument","SubDocument", "..."]
}
//SubDocument
{
	"day":"(날짜)",
	"state":"(출결정보)",
}
var mongoose = require('mongoose')
var Schema = mongoose.Schema

const datestatusSchema = new mongoose.Schema({
    date: {
        type: String,
    },
    state: {
        type: String,
    },
})
const DateStatus = mongoose.model('dateStatus', datestatusSchema)

var attendanceUserSchema = new Schema({
    name: {
        type: String,
    },
    status: [datestatusSchema],
})

attendanceUserSchema.methods.addStatus = function(date, state) {
    this.status.push(
        new DateStatus({
            date,
            state,
        })
    )
    return this.save()
}

module.exports = mongoose.model('attendanceUser', attendanceUserSchema)

SubDocument의 삽입은 addStatus method로 만들어서 SubDocument 생성 시 용이하게 했다.

profile
🦉🦉🦉🦉🦉

0개의 댓글