[Pre-Project] westagram API 서버 구축하기

Youngseo Lee·2022년 11월 7일
0

어느덧 3주차 🍂

어느덧 부트캠프 3주차가 지났다. 시간이 너무 빨라 하루 하루 정신없이 지나가는 듯 하다. 이번 주에는 Node.jsExpress API 그리고 MySQL 을 활용한 Westagram API를 구축하는 실습을 진행했다. 그 과정을 회고해 보려고 한다.

나의 한 주를 요약한 MEME🙃


실습 목표 ⚓️

MySQL, Express API를 활용해서 Westagram API 구축하기

기술스택 🔨

  • Data Base: MySQL
  • Node.js, Express API
  • JavaScript

학습 및 실습 진행 순서 ➿

  1. MySQL 설치 및 SQL 문법 학습
  2. Express 초기 환경 세팅
  3. TypeORM과 DB connection
  4. Westagram CRUD API Server 만들기
  5. API Documentation 생성

1. Database : MySQL and SQL

사용자, 게시물, 댓글과 같은 데이터들을 영구적으로 보존하기 위해서 데이터베이스 시스템을 사용해서 저장해야 한다. MySQL은 대표적인 RDBMS(관계형 데이터베이스 시스템)로, SQL 쿼리문등을 추가로 학습했다.

과제 4. MySQL의 DQL(Data Query Language)를 사용하여, 아래 결과가 출력될 수 있는 쿼리문을 작성해서 제보세요.

+----------+--------------+-------------------------+--------+-----------+
| post_id  | title        | content                 | author | like_user |
+----------+--------------+-------------------------+--------+-----------+
|  4       | 자료구조 1번    | BigO Notation이란 무엇인가?| Fabian | Rebekah   |
|  6       | 프론트 개발 입문 | 프론트 입문 HTML이란 무엇인가?| Elenor | Rebekah   |
+----------+--------------+-------------------------+--------+-----------+

My Answer ‼️

SELECT posts.id as post_id, posts.title as title, posts.content as content, 
users1.name as author, users2.name as like_user
FROM likes
INNER JOIN posts ON posts.id = likes.post_id
INNER JOIN users as users1 ON users1.id = posts.id
INNER JOIN users as users2 ON users2.id = likes.user_id;

해당 풀이에 대한 해설은 개인 노션에 기록해둬서 회고록에는 생략

다양한 SQL 문제를 풀어가면서 내가 어느 포인트에서 혼란을 겪고 있는지 찾아낼 수 있었다.

  1. ON 의 역할은 데이터를 연결해 주는 장치의 역할이다. 주로, ON 다음에는 데이터 간의 연결성 (PK-FK)을 설명한다.

  2. WHERE 가 조건문의 역할을 수행한다.


2. Express 초기 환경 세팅

백엔드 API 개발의 생산성과 효율성 향상을 위해 별도의 프레임워크를 사용해야한다. 내가 사용한 프레임 워크는 Node.js 기반의 Express

Express를 사용할 때, 다양한 npm 패키지 모듈이 필요하다.

  • nodemon : 코드의 수정시 서버를 계속 다시 켜줘야 하는 점을 보완해주는 패키지
  • cors : 백엔드와 프론트 서버가 서로 다른 도메인에서 데이터를 주고 받을 수 있도록 지원
  • dotenv. : 환경변수 관리
  • morgan : 로그 관리 패키지

express 초기 환경 세팅 예시

// 코드 가독성을 위해 환경변수 설정에 필요한 'dotenv' 모듈은 최상단에 불러온다
require("dotenv").config();

const { DataSource } = require('typeorm');

// .env 파일에 저장해놓은 환경변수들을 불러와 db와의 커넥션 환경 세팅을 완료
const appDataSource = new DataSource({
    type: process.env.TYPEORM_CONNECTION,
    host: process.env.TYPEORM_HOST,
    port: process.env.TYPEORM_PORT,
    username: process.env.TYPEORM_USERNAME,
    password: process.env.TYPEORM_PASSWORD,
    database: process.env.TYPEORM_DATABASE
})

//실제 연결 완료 : then()과 catch()를 사용해서 에러를 핸들링
appDataSource.initialize()
    .then(() => {
        console.log("Data Source has been initialized!")
    })
    .catch((err) => {
        console.error("Error during Data Source initialization", err)
    });

3. TypeORM 과 DB connection

TypeORM 이라는 라이브러리가 제공하는 데이터베이스 연결(Pooling)기능을 사용해 데이터베이스에 영구 저장

.env 파일에 TypeORM 환경 병수 정보를 저장해서 DB Connectio을 실행해서 사용

// .env Sample 
// .env 파일은 보안에 민감한 정보를 포함하고 있기 때문에 .gitignore 파일에 포함시켜 관리

DATABASE_URL = "db_type://username:password@127.0.0.1:db_port/database_name"

PORT = YOUR PORT NUMBER SHOULD BE HERE!

TYPEORM_CONNECTION = db_type
TYPEORM_HOST = HOST NUMBER
TYPEORM_USERNAME = root
TYPEORM_PASSWORD = myPassword
TYPEORM_DATABASE = myDB
TYPEORM_PORT = db_port
TYPEORM_LOGGING =TRUE

4. Westagram CRUD API Server 만들기

다양한 endpoint에 맞는 기능별 API 서버를 구축했지만, 그 중에서 가장 기억에 남겨두고 싶은 두 가지 예시를 간단히 남겨둔다.

Westagram Backend Project - 유저의 게시글 조회하기🔖

app.get("/users/:userId/posts", async (req, res) => {
    const userId = req.params.userId

    const [user] = await appDataSource.query(
        `SELECT 
            users.id AS userId,
            users.profile_image AS userProfileImage
        FROM users
        WHERE users.id = ?
        `, [userId]
    );
    
    const posts = await appDataSource.query(
        `SELECT 
            posts.id AS postingId,
            posts.content_image AS postingImageUrl,
            posts.content AS postigContent
        FROM posts
        INNER JOIN users ON users.id = posts.user_id
        WHERE users.id = ?
        `, [userId]
     );

    user['postings'] = posts;

    return res.status(200).json({ data: user })
});

멘토님께 PR을 받아가면서 수정한 POINT ✔️

  • Placeholder : sql query문을 작성할 때, 보안상의 문제로 ${value} 가 아닌 ?를 사용할 것
  • RESTful 하게 설계된 엔드포인트 작성하기 app.get("/users/:userId/posts"
    • 서버의 유저들 중, 1번 유저의, 게시글들을 get(가져오는) 엔드포인트

Westagram Backend Project - 좋아요 누르기 ❤️

app.post("/likes", async (req, res) => {
    const {user_id, post_id} = req.body

    try {
        await appDataSource.query(
        `INSERT INTO likes(
            user_id,
            post_id
        ) VALUES (?,?);
        `, [user_id, post_id]
    );
  return res.status(201).json({ message: "likeCreated" })
} catch (err) {
    return res.status(409).json({ error: err.sqlMessage });
}
});

멘토님께 PR을 받아가면서 수정한 POINT ✔️

  • CONSTRAINT unique_likes UNIQUE (user_id, post_id) SQL 추가
    • 하나의 유저가 동일한 포스트에 대해 like를 눌러 똑같은 데이터가 여러개가 생길 수 없기 때문!!
      - try ~ catch 구문을 사용해 에러 처리

5. API Documentation 생성

필수 과제는 아니였지만, postman 을 사용해서 API Documentation을 생성했다.

👇 API Documentation 링크
https://documenter.getpostman.com/view/18295633/2s8YYJr3Rd


느낀점

🌱 성장하고 있음을 느낀 한 주!
일주일 정도 Express API 서버를 구축하면서 낯선 이론도 공부하고 실습도 진행했다. 처음에는 어려웠지만 이내 익숙해 지면서 어떤 방식으로 전체 API 구동되는지에 대한 이해를 높일 수 있는 시간이었다. 앞으로 진행하게될 프로젝트 등을 통해 더욱 익숙해 질것이라 기대한다.

아쉬운점

🤔 MySQL 개인 공부 필요
TypeORM 풀링 기능을 활요해 mysql db를 활용했다. 그리고 실제로는 raw query문들을 작성해서 사용했는데, 부트캠프에서 제공해준 내용 이상의 SQL 공부가 필요하다는 점을 몸소 느꼈다.

⛔️ 에러와의 사투
TypeORM에서 raw query문을 작성하는데 , 때문에 3시간을 낭비한 경험이 있다. 예민한 친구인 만큼 조금 더 꼼꼼히 코드를 작성할 필요성을 느꼈다. 또한! 에러 메세지를 꼼꼼히 읽는 습관도 필요할듯 하다.

profile
백엔드 개발자 영서뤼

0개의 댓글