Project_1 CRUD 기능을 가진 API 서버 제작

박형석·2022년 3월 8일
1

프로젝트

목록 보기
1/4
post-thumbnail

fastify와 mongodb를 이용한 API서버 만들기 프로젝트.

목차

  1. 주제 선정 및 기획
  2. 구현 목표
  3. 시나리오
  4. 실제 구현 결과
  5. 어려웠던 점
  6. 해결 방안
  7. 후기
  8. 앞으로의 목표


✍개요

  • fastify와 mongodb를 이용해서 API서버를 3인 1조로 기획하고 만드는 프로젝트.
  • 데이터를 모델링하고, API 문서화 진행.
  • Git을 이용한 협업을 진행

작년, 미스터트롯이라는 서바이벌 트로트 경연 프로그램이 방영 되었다. 이때 우승자 투표를 위해서 문자투표를 진행하였지만 한꺼번에 많은 투표수를 처리해야하는 문제 때문에 우승자 발표가 한참 늦어졌다.

4차 산업혁명 시기에 문자투표가 웬말인가!

우리는 결과를 빠르게 집계하는 웹 애플리케이션 서버를 만들것 이다.

이 서버의 특징은 서바이벌 프로그램뿐만 아니라 대국민 투표 정식 웹사이트를 목표로 일반 사용자는 투표를 만들 수 없지만 관리자 권한을 가진 사용자만이 투표를 만들수 있게 제작 하였다.


주제

대국민 서바이벌 투표 웹 애플리케이션 서버 제작.


구현 목표

  • 여러개의 투표를 한 페이지에 불러올 수 있다.
  • 중복투표가 가능하다.(설정값에 따름)
  • 사용자와 관리자는 인증키로 구분한다.
  • 사용자는 투표 페이지에서 후보자를 클릭하여 후보자에 대한 정보를 조회할 수 있다.
  • 사용자는 투표 후 결과값을 조회할 수 있다. (퍼센테이지로 표현)
  • 커뮤니티 탭을 만들어 해당 투표에 대한 토론이 가능.
  • 로그인은 소셜 로그인으로 간편하게 이용 가능.
  • 단순 투표 홈페이지로 끝나는 것이 아닌 커뮤니티 사이트로써의 비즈니스 모델.
  • 같은 인물이 투표에 다시 나와도 고유한 투표 ID값으로 데이터를 분류.

시나리오

  1. 투표는 관리자만이 생성할 수 있다.
  2. 또, 관리자만이 후보자의 정보를 등록할 수 있다.
  3. 일반 사용자는 특정 투표를 선택해 후보자를 뽑을 수 있다.(중복투표 설정 가능)
  4. 사용자는 투표 결과를 퍼센테이지 값으로 조회 할 수 있다.
  5. 투표결과 확인후 사용자는 해당 투표에 대한 토론을 위해 토론 게시판으로 이동할 수 있다.
  6. 각각의 토론 게시판은 하나의 주제를 가지고 댓글을 이용해 각자의 생각을 표현.
  7. 사용자는 자신의 댓글, 투표내역을 삭제할 수 있다.


실제 구현 결과...

  1. 사용자는 투표 목록을 조회할 수 있다.
  2. 사용자는 특정 투표를 조회할 수 있다.
  3. 사용자는 투표를 할 수 있다.
  4. 사용자는 투표 결과를 확인할 수 있다.
  5. 관리자는 투표를 생성할 수 있다.

많은 기능을 담은 멋진 서버를 구현하고 싶었으나 능력의 한계를 느껴 기능 간소화...

원래 투표웹사이트의 목적에 충실해지기로 방향전환..


API.md

구현에 필요한 api들을 CRUD가 가능하도록 설계했다. 그리고 엔트포인트들은 최대한 직관적으로 보이게 즉, RESTful하게 하려고 노력했다. :)

ERD 구성도

USER

  • 사용자는 user라는 데이터베이스에 저장하도록 만들었다.
  • 사용자는 admin이라는 요소가 있는데 만약 admin이라는 권한이 주어지면 투표를 생성하고 삭제할 수 있다.

candidate

  • admin권한을 가진 사용자만이 후보자 정보를 등록할 수 있다.
  • 후보자 정보는 투표ID와 연결되어 고유한 값을 가지게 된다.
  • 후보자 정보에는 이름, 사진, 설명, 투표된 값(count)을 가지게 된다.

vote

  • admin권한을 가진 사용자만이 투표를 등록할 수 있다.
  • 투표 내용에는 투표명과 후보자들의 목록을 포함한다.

user_candidate, candidate_vote

  • user, candidate, vote의 조인 테이블로써 중간 정보를 저장하여 각각 데이터베이스에 연결 시키는 역할을 한다.

이번 프로젝트에서는 조인 테이블을 연동시키는 개념이 어려웠다. 그래서 구현하지 못하였다... ㅠㅠ
조만간 구현 해 봐야겠다.


mongodb를 연결

이 프로젝트에서는 몽고디비를 이용하여 NoSQL데이터베이스를 이용했다.

mongodb Atlas에서 myFirstDatabase라는 데이터베이스를 만든 후
candidate와 vote라는 콜렉션을 만들었다.

  fastify.register(require('fastify-mongodb'), {
    forceClose: true,
    
    //dotenv로 설정된 몽고디비 URL을 불러온다.
    url: process.env.MONGODB_URL
  })

다음과 같은 코드를 app.js에 추가하여 몽고디비와 연결시켜 준다.
여기서 필요한 부분은
npm i fastify-mongodb --save , npm i dotenv 를 입력하여 환경변수와 몽고디비를 세팅해 줘야 한다.


시나리오 예상 구현

포스트맨으로 api를 전송하며 결과값을 얻었다.

#1 사용자가 홈페이지에 접속하여 투표목록 조회

response code(200)

현재 2개의 투표가 생성되어 있다. 나는 여기서 "트로트의 왕은 누구인가" 라는 투표를 클릭하여 GET하고 싶다.


#2 사용자가 특정 투표를 조회

현재 4명의 후보가 등록이 되어있다.
응답 body는 다음과 같다.

응답body에는 네개의 후보자 아이디가 나오게 된다. 이제 후보자의 정보를 조회 해보자.


#3 사용자가 특정 투표의 특정 후보자 정보를 조회


조금 허접한 예시이지만.. 너그러히 봐주십쇼...

응답body는 위와 같이 나오게 된다. 이제 후보자를 투표 해 보자.


#4 사용자가 특정 후보를 선택하여 투표

  • 이때는 특이한 점이 투표(vote) 데이터베이스에 count값이 쌓이지 않고 후보자(candidate) 데이터베이스에 쌓인다.

이 과정은 다음과 같이 구현 되었다.


module.exports = async function (fastify, opts) {
  fastify.put('/:id', async function (request, reply){
    const Candidate = this.mongo.db.collection('Candidate')//candidate 데이터베이스를 이용
    const id = this.mongo.ObjectId(request.params.id)
    const filter = {'_id' : id}
    const body = await Candidate.findOne(filter)
    const replacement = {'v_id' : body.v_id, 'c_name' : body.c_name, 'image' : body.image, 'desc' : body.desc, 'count' : parseInt(body.count) + 1}

 
    const result = await Candidate.findOneAndReplace(filter, replacement)
    

      reply
        .code(200)
        .header('content-type','application/json')
        .send({'c_name' : result.value.c_name})
    

  })
}

#5 관리자가 만료된 투표를 삭제

admin권한을 가진 관리자가 해당 투표를 삭제할 수 있다.

삭제된 vote의 내용과 ok 싸인을 응답body로 담았다.

#6 투표와 관련된 후보를 삭제


여기까지가 실제로 구현된 내용들이다.

정말 처음엔 추가하고 싶은 기능들이 참 많았었는데 구현하지 못해서 약간 한이 남았다.

하지만
이것마저도 구현하는 과정에서 힘든점이 몇몇 있었다..

어려웠던 점

1. 우분투 프리징 현상....

진짜 이것때문에 멘탈이 약간 흔들렸지만 다행히 차근차근 해결할 수 있었다.

해결과정

  • 없다...
    그냥...
    우분투를 다시 깔았다. ㅠㅠ

    많은 구글링을 통해 프리징 현상이 일어나는 이유들이 몇몇 있었다.

  1. 리눅스와 인텔의 하드웨어 호환성 문제

  2. grub 파일 값 변경

  3. 그래픽카드 드라이버 변경

    1번과 2번을 시도했음에도 불구하고 계속 화면이 멈추는 현상이 반복되었다.
    그래서 대망의 3번 방법을 시도했는데..
    화면이 아예 안켜졌다..

    그래서 우분투를 다시 깔았다 ^^

    2. 예상보다 어려운 구현

    해결과정

  • 기획 단계에서 하고싶었던 기능들을 거의 쳐내고 필요한 기능만을 구현하려고 노력
  • ER diagram 작성시 실제 시나리오 단계를 만들면서 진행
  • 자바스크립트에 대한 부족한 지식을 무한 구글링을 통해 해결..

우선 위와같은 어려움을 겪게 된 이유는 생각한 큰 그림을 한번에 그리려다가 머릿속이 복잡해졌기 때문인 것 같다.

부트캠프 코치님들이 그렇게 써가면서 진행 하라고 했지만 나와 우리팀은 근거없는 자신감으로 신나게 diagram을 만지작 거렸다.

작성을 하다보니 미처 고려하지 못한 ID값들의 연결, 일대일, 일대다 관계들의 설정을 하다가 뇌정지가 와버렸다.
그래서 팀원들과 같이 시나리오 순서대로 api문서를 작성해가며 과정을 이해하려고 노력했다.

다행히 하나하나 맞춰가며 만들다 보니 하나 둘 맞춰지게 되었다.

✍후기

맨날 자동차를 만지고 컴퓨터를 쓰는 일 이라고는 유튜브 시청과 게임할 때 뿐이었지만 직접 서비스를 기획하고 만든다는 과정 자체가 백앤드 업무를 찍먹 해 볼수 있었다.

덕분에 내가 배웠던 서버와 api, 비즈니스 로직의 구현 등을 활용해 볼 수 있었고 비록 원하는 형태의 서버를 100% 구현하지 못했지만 그 과정을 많이 생각 해볼수 있는 시간을 가졌던 것 같다.
덕분에 나의 목표가 하나 만들어지게 되었다.

앞으로의 목표

한달동안 열심히 고민해서 게시판을 만들어 보고 싶다.

정확히 말하자면 커뮤니티 사이트를 제작 해 보고 싶다.

그래서 구현 할 사항은 다음과 같다.

  1. 사용자가 자유롭게 게시글을 작성할 수 있다.
  2. 사용자가 자유롭게 게시글을 삭제할 수 있다.
  3. 사용자가 자유롭게 댓글을 작성할 수 있다.
  4. 사용자가 자유롭게 댓글을 삭제할 수 있다.
  5. 사용자가 자유롭게 게시글당 하나의 좋아요와 싫어요를 누를 수 있다.
  6. 좋아요가 많은 글 순서대로 나타내는 탭을 생성

우선은 프론트까지 html, css, js로 구현을 해 보도록 노력할 예정이다.
:)

profile
Better Than Yesterday

0개의 댓글