DevOps 20일차 - WAS 실습

문한성·2023년 4월 6일
0

부트캠프

목록 보기
30/123
post-thumbnail

개요: WAS 실습

Achievement Goals

  • API 문서를 작성할 수 있습니다.
  • Fastify를 이용해 DB와 통신하는 서버를 만들 수 있습니다.
  • PostgreSQL을 이용하여 DB를 구성할 수 있습니다.
  • GitHub을 활용하여 팀원들과 협업합니다.

Day1

DevOps 부트캠프가 진행한 지 벌써 한 달이 지났고, 실습과제가 시작됐다.

주제는 쇼핑몰과 LMS(학습 관리 시스템) 두 개가 있고, 우리 팀은 LMS 주제로 진행이 되었다.

만들어야 할 애플리케이션의 조건은 7개의 최소 요구사항을 가지고 있었고, 다음과 같다.

LMS(학습 관리 시스템)
사용자는 모든 수업을 조회할 수 있다
사용자는 특정 분류의 수업을 조회할 수 있다(예: 강의자/ 수업명 / 수업코드 등)
사용자는 수업을 수강신청 할 수 있다
사용자는 모든 수강중인 수업을 조회할 수 있다
사용자는 이메일 정보와 같은 개인정보를 변경할 수 있다
사용자의 타입이 강의자일 경우 새로운 수업을 생성할 수 있다
사용자는 수업에 대한 수강신청을 취소할 수 있다

1. ERD 구성

우리 팀은 백엔드를 경험 했던 사람이 총 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)는 중복 값을 가질 수 없다.

2. API 문서 작성

https://neat-apartment-b02.notion.site/API-b6d629abd43d434dac26db36dc3c2cf0

Day2

Project Setting

  • fastify 프로젝트 생성 및 DB 연결

MileStone1

  • DB 구성 및 서버 연결

MileStone2
API 문서에 따른 서버 구현

1. 데이터베이스 준비

PostgreSQL

  • ElephantSQL 접속 - 인스턴스 생성
  • 테이블 생성

2. fastify 프로젝트 생성

팀 레포지토리 클론 후 이동

fastify generate .

fasify 플러그인을 활용하여 데이터베이스와 연결

  • \plugins\postgres.js 파일 생성
'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}`
  })
})
  • .env 파일
DATABASE_USER=아이디
DATABASE_PASSWORD=패스워드
DATABASE_HOST=호스트
DATABASE_NAME=아이디
  • \routes\aricle\index.js 파일 생성
'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()
    }
  })
}
  • 경로 접속 시

3. API 기능 구현

내가 맡은 API는 다음과 같다

사용자 수강 조회 GET /class/enrollment

사용자는 모든 수강중인 수업을 조회할 수 있다. 요청이 성공적으로 서버에 전달되면 200 OK를 반환하며, 요청 처리 중 발생한 오류는 응답 객체의 error필드에 나타납니다.

NameTypeDescriptionRequired
AuthorizationString사용자 인증 토큰 값O

Response

FieldTypeDesc
class_idInteger등록된 강의 Id
"data": [
		        {
		            "class_id": 2,
		            "title": "강의2",
		            "professor_id": 1,
		            "professor_name": "문한성",
		            "professor_email": "hansung@gmail.com"
		        },
		        {...}
        ]

사용자 정보 수정 PATCH /user

사용자는 이메일 정보와 같은 개인정보를 변경할 수 있다. 요청이 성공적으로 서버에 전달되면 200 OK를 반환하며, 요청 처리 중 발생한 오류는 응답 객체의 error필드에 나타납니다.

Header

NameTypeDescriptionRequired
AuthorizationString사용자 인증 토큰 값O

Request parameters

NameTypeDescriptionRequired
user_info(body)Object변경될 사용자 정보O

user_info

NameTypeDescriptionRequired
emailString변경될 사용자 이메일O
{
	"email" : "email"
}

Response

FieldTypeDesc
user_idInteger수정된 회원의 id
{
  "user_id" : 12
}

Section 1이 끝난 후

팀원들과 같이 역할을 분담하여 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에 가까워질 수 있는 학습을 하니 나태해지지말고 지금까지 하던 것 처럼 꾸준히 지치지 말고 나아갈 수 있었으면 좋겠다!

profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글