Achievement Goals
DevOps 부트캠프가 진행한 지 벌써 한 달이 지났고, 실습과제가 시작됐다.
주제는 쇼핑몰과 LMS(학습 관리 시스템) 두 개가 있고, 우리 팀은 LMS 주제로 진행이 되었다.
만들어야 할 애플리케이션의 조건은 7개의 최소 요구사항을 가지고 있었고, 다음과 같다.
LMS(학습 관리 시스템)
사용자는 모든 수업을 조회할 수 있다
사용자는 특정 분류의 수업을 조회할 수 있다(예: 강의자/ 수업명 / 수업코드 등)
사용자는 수업을 수강신청 할 수 있다
사용자는 모든 수강중인 수업을 조회할 수 있다
사용자는 이메일 정보와 같은 개인정보를 변경할 수 있다
사용자의 타입이 강의자일 경우 새로운 수업을 생성할 수 있다
사용자는 수업에 대한 수강신청을 취소할 수 있다
우리 팀은 백엔드를 경험 했던 사람이 총 3명이 있었고, 서로 의견을 공유하며 수월하게 테이블 생성과 테이블 간의 관계를 설정할 수 있었다.
1.1 테이블
요구사항을 분석해 class(수업), users(사용자), users_class(수강정보) 테이블을 구성했다.
문제사항 1
이 때, 사용자가 수강자인지 강의자인지 구분을 해야 했기에, users 테이블에 역할을 부여할지, 역할 테이블을 따로 만들어서 관리를 할지 고민을 했고, 이 과정에서 role(역할), role_user(유저 역할 정보) 테이블이 생성이 됐다.
토의 결과
우리는 토의를 한 결과, 수강정보 데이터가 1년 혹은 상/하반기로 나눠지며 상반기에서 하반기로 이동 시 상반기 정보 테이블은 제거되고 신규 생성이 되는 것으로 가정을 세웠고, 역할의 수 또한 수강자, 강의자로 제한되는 등 역할의 수가 많아지지 않을 것으로 예상했다.
그러하여 role, role_user 테이블을 삭제하고 user테이블에 is_professor 컬럼을 추가하여 역할을 관리하는 것으로 했다.
문제사항 2
나는 class 테이블 내에 강사명을 명시하는 professor_name 컬럼을 생성할 시 사용자가 수업정보를 검색할 때, 강사명으로 검색을 한다면, users 테이블을 조회하지 않더라도 professor_name 컬럼을 통해 class 테이블만 조회하여 처리할 수 있지 않을까 라는 생각을 했다.
토의 결과
우리는 오랜 시간 토의한 결과, users 테이블과의 조인을 통한 데이터 검색을 하도록 결정지었다.
이는, 정규식 조건을 지키면서 코드 구현 과정에서 SQL의 join문을 사용해 하나의 쿼리로 유저 정보까지 받아 올 수 있게 하여, professor_name 이외의 user 정보 또한 모두 가져오는 것이 좋을 것 같아 professor_name 컬럼은 삭제하였다.
1.2 테이블 관계
users & class 테이블의 일대다 관계
한 명의 사용자(강의자)가 여러 개의 수업을 진행할 수 있지만, 각 수업에는 한 명의 강의자만 있을 수 있기 때문에 일대다 관계를 지어준다.
즉, class 테이블의 user_id는 중복 값을 가질 수 있지만(한 명이 여러 개의 수업 진행), users 테이블의 기본 키 id(사용자의 고유한 id)는 중복 값을 가질 수 없다.
users & class & users_class 테이블의 각각 일대다 관계
여러 명의 사용자가 각각 여러 개의 수업을 수강신청 할 수 있기에 각각 일대다 관계를 지어준다.
즉, users_class 테이블의 user_id와 class_id는 중복 값을 가질 수 있고, users 테이블의 기본 키 id(사용자의 고유한 id)와 class 테이블의 기본 키 id(수업별 고유한 id)는 중복 값을 가질 수 없다.
https://neat-apartment-b02.notion.site/API-b6d629abd43d434dac26db36dc3c2cf0
Project Setting
MileStone1
MileStone2
API 문서에 따른 서버 구현
PostgreSQL
팀 레포지토리 클론 후 이동
fastify generate .
fasify 플러그인을 활용하여 데이터베이스와 연결
'use strict'
const fp = require('fastify-plugin')
const {
DATABASE_USER,
DATABASE_PASSWORD,
DATABASE_HOST,
DATABASE_NAME
} = process.env
module.exports = fp(async function (fastify, opts) {
fastify.register(require('@fastify/postgres'), {
connectionString: `postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}/${DATABASE_NAME}`
})
})
DATABASE_USER=아이디
DATABASE_PASSWORD=패스워드
DATABASE_HOST=호스트
DATABASE_NAME=아이디
'use strict'
module.exports = async function (fastify, opts) {
fastify.get('/', async function (request, reply) {
const client = await fastify.pg.connect()
try {
const { rows } = await client.query(
'SELECT * FROM public.users'
)
reply.code(200).send(rows)
} finally {
client.release()
}
})
}
내가 맡은 API는 다음과 같다
사용자는 모든 수강중인 수업을 조회할 수 있다. 요청이 성공적으로 서버에 전달되면 200 OK를 반환하며, 요청 처리 중 발생한 오류는 응답 객체의 error필드에 나타납니다.
Name | Type | Description | Required |
---|---|---|---|
Authorization | String | 사용자 인증 토큰 값 | O |
Field | Type | Desc |
---|---|---|
class_id | Integer | 등록된 강의 Id |
"data": [
{
"class_id": 2,
"title": "강의2",
"professor_id": 1,
"professor_name": "문한성",
"professor_email": "hansung@gmail.com"
},
{...}
]
사용자는 이메일 정보와 같은 개인정보를 변경할 수 있다. 요청이 성공적으로 서버에 전달되면 200 OK를 반환하며, 요청 처리 중 발생한 오류는 응답 객체의 error필드에 나타납니다.
Name | Type | Description | Required |
---|---|---|---|
Authorization | String | 사용자 인증 토큰 값 | O |
Name | Type | Description | Required |
---|---|---|---|
user_info(body) | Object | 변경될 사용자 정보 | O |
Name | Type | Description | Required |
---|---|---|---|
String | 변경될 사용자 이메일 | O |
{
"email" : "email"
}
Field | Type | Desc |
---|---|---|
user_id | Integer | 수정된 회원의 id |
{
"user_id" : 12
}
팀원들과 같이 역할을 분담하여 fastify를 사용하여 기능을 작성하는데 낯선 언어에 낯선 프레임워크를 사용하다 보니 기능 구현이 많이 힘들었다.
특히 SQL문을 직접 작성해야하는 부분에서 3번의 join을 해야하는 SQL문을 만들었어야 했는데 팀원들에게 도움을 구해야만 했다.
// 강사 찾기 쿼리
const findMyClassQuery = `
SELECT
c.id AS class_id,
c.title AS title,
professors.id AS professor_id,
professors.name AS professor_name,
professors.email AS professor_email
FROM
class c
JOIN users_class uc ON uc.class_id = c.id
JOIN users u ON uc.user_id = u.id
LEFT JOIN users professors ON professors.id = c.user_id
WHERE
u.id = ${userId}`;
기존에 벡엔드를 배웠었던 경험이 있어 설계나 api문서 자체에는 버거움을 느끼진 않았지만 막상 하루만에 새로운 언어에 새로운 프레임워크를 사용해서 요구사항을 만족하는 API를 만들어라! 라고 과제가 나오자 쉽게 만들 수 없었다.
nodeJS를 사용한다는 말을 듣고 express를 공부를 하고있었던 나로써는 레퍼렌스도 잘 존재하지 않는 프레임워크의 사용에 어려움을 많이 느꼈다 다행히 팀원중에 nodeJS사용에 익숙한 분이 있어서 정말 많은 도움을 받은거 같다.
특히나 이번 Section1을 하는동안 학습시간 이후에 따로 예습을 했었는데 너무 앞서서 공부를 했기에 문제상황에서의 해결능력이 내게 없다는걸 느꼈다. 이후론 배웠던걸 복습해 나가고 활용법을 더찾아보는 방법으로 공부시간을 써야겠다.
이제 본격적인 DevOps에 가까워질 수 있는 학습을 하니 나태해지지말고 지금까지 하던 것 처럼 꾸준히 지치지 말고 나아갈 수 있었으면 좋겠다!