프로그래머스 풀스택 31

  • programmers

posted on 08 Oct 2024 under category programmers in series programmers

프로그래머스 풀스택 31

프로젝트: Node.js 기반의 REST API 구현(8)

🌊 좋아요 DB 설계

💫 좋아요 DB 설계

<dbdiagram 설계>
alt text

alt text

  • likes 테이블 생성 및 외래키 설정


<좋아요 추가 API 설계 수정>
alt text

  • 누가 좋아요 눌렀는지 알 수 있는 방법? : 로그인한 상태여야 좋아요가 가능, 로그인 토큰으로 유저가 누군지 파악하기
  • 따라서 Request Body를 수정해줌

🌊 좋아요 추가 구현

💫 좋아요 추가 구현

alt text

  • 처음에 const {id} = req.params;가 아닌 const {liked_book_id} = req.params; 했더니 오류가 났음
  • 이유 : URL 파라미터의 이름과 일치하지 않기 때문
  • 라우트 정의가 /likes/:id로 되어 있다면, URL 파라미터 이름이 :id로 정의되어 있기 때문에 req.params에서 값을 가져올 때에도 id라는 이름을 사용해야 함.

<POSTMAN 실행결과>
alt text

<Workbench 결과>
alt text

  • 잘 작동하는 걸 확인!

🌊 좋아요 삭제 구현

💫 좋아요 삭제 구현

alt text

<POSTMAN 실행결과>
alt text

  • 잘 작동함!

🌊 count(), AS, 서브쿼리의 등장

💫 count()
Workbench에서는 PK가 없으면 무조건 Read Only 테이블이 됨!!

alt text
alt text

SELECT count(*) FROM likes WHERE liked_book_id = 1;
  • count()를 사용하면 조건을 만족하는 행 개수 출력!!

💫 AS

alt text

SELECT *, (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes FROM books;
  • 조인이 되지 않은 두 개의 테이블을 엮어서 출력하기

💫 서브쿼리의 등장

좋아요 개수 세서 books 테이블에 컬럼 추가해서 출력해주기
도서 테이블 전체 조회

  • SELECT * FROM books;
  • SELECT 컬럼명1, 컬럼명2, … FROM 테이블명;

도서 테이블 전체 조회 + 컬럼 1개 추가하기
SELECT *,
  값 AS 새로 추가할 컬럼명
  FROM books;

SELECT *,
  (각 행마다 likes 테이블에 liked_book_id로 가지고 있는 행 수) AS likes
  FROM books;

SELECT *,
  (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes
  FROM books; 👉 서브 쿼리!!


🙌 서브(sub) 쿼리 : 쿼리 안에 쿼리

  • 데이터의 양이 많다면, JOIN과 GROUP BY를 사용하는 것이 더 효율적!!

🙌 count() : 행 개수

🙌 AS : 컬럼 별칭

✨백엔드 심화 SQL 접기/펼치기✨
  1. “Board”스키마 생성
     CREATE DATABASE Board;
     USE Board;
    

    alt text

  2. 사용자 테이블 생성
    • 테이블 이름은 기본적으로 복수형 추천(테이블 안에 여러 개가 들어가므로)!
    • AUTO_INCREMENT : 자동 숫자 증가(기입 기능)
       CREATE TABLE users (
         id INT NOT NULL AUTO_INCREMENT,
         name VARCHAR(30) NOT NULL,
         job VARCHAR(100),
         birth DATE,
         PRIMARY KEY (id)
       );
      

      alt text

  3. 사용자 데이터 삽입
    • VALUES (“haerin”, “idol”,”100101”);을 해도 위의 2번에서 birth DATE덕분에 자동으로 적혀짐! 그래도 입력할 때 맞춰서 입력해주는 게 좋음!
    • NOT NULL -> 무조건 값을 넣기!(이름이 null이여도 X)
       INSERT INTO users (name, job, birth)
       VALUES ("haerin", "idol","20060515");
      
       INSERT INTO users (name, job, birth)
       VALUES ("haerin", "student","2006-07-15");
      
       INSERT INTO users (name, job, birth)
       VALUES ("danielle", "idol","2005-04-11");
      
       INSERT INTO users (name, job, birth)
       VALUES ("minji", "idol","2004-05-07");
      
       INSERT INTO users (name, job, birth)
       VALUES ("hanni", "idol","2004-10-06");
      

      alt text

  4. 게시글 테이블 생성
    • 작성 일자 : created_at(보편적으로 사용)
    • 수정 일자 : updated_at(보편적으로 사용)
       CREATE TABLE posts (
         id INT NOT NULL AUTO_INCREMENT,
         title VARCHAR(100) NOT NULL,
         content VARCHAR(2000),
         created_at TIMESTAMP DEFAULT NOW(),
         PRIMARY KEY (id)
       );
      

      alt text

  5. 게시글 데이터 삽입
    • TIMESTAMP DEFAULT NOW()을 통해 created_at 값을 적지 않아도 자동입력됨!
       INSERT INTO posts (title, content)
       VALUES ("title1", "content1");
      

      alt text

  6. 게시글 테이블에 수정일자 추가
    • ALTER을 통해 수정일자를 추가하기
       ALTER TABLE posts
       ADD COLUMN updated_at DATETIME
       DEFAULT NOW()
       ON UPDATE NOW();
      

      alt text

  7. 게시글 테이블 id 2 수정
    • UPDATE를 이용하여 update된 시간 갱신해보기
       UPDATE posts
       SET content="updated!"
       WHERE id = 2;
      

      alt text

  8. 게시글 테이블에 작성자 컬럼 FK 추가
    • MUL(MULTIPLE) : 기본키 값을 가져다 쓰고 있는 외래키지만 중복이 가능하므로 MUL!
       ALTER TABLE posts
       ADD COLUMN user_id INT;
      
       ALTER TABLE posts
       ADD FOREIGN KEY(user_id)
       REFERENCES users(id);
      

      alt text

  9. ✨조인(정규화)✨
    • SELECT 할 때만 보기 편하라고 해주는 것임!!(실제로 테이블을 생성하진 않음!!)
      (가상의 테이블을 임시로 돌려주는 것)
    • 게시글의 사용자 번호와 사용자의 사용자 번호가 같으면 붙이는 조건
       SELECT * FROM posts LEFT
       JOIN users ON posts.user_id = users.id;
      
       SELECT posts.id, title, content, created_at, updated_at, name, job, birth  FROM posts LEFT
       JOIN users ON posts.user_id = users.id;
      

      alt text

  10. 조건을 만족하는 행 개수
    • count()를 쓰면 조건을 만족하는 행 개수 출력 가능
      SELECT count(*) FROM likes WHERE liked_book_id = 1;
      

      alt text

  11. 좋아요 개수가 포함된 books 테이블 조회
    • 서브 쿼리를 사용해 출력하기
      SELECT *, (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes FROM books;
      

      alt text

  12. 개별 도서 조회 시, 사용자가 좋아요를 했는지 여부를 포함
    • 특정 책의 상세 정보를 가져오는 동시에
    • 좋아요 수(likes)를 계산하고
    • 특정 유저가 좋아요를 눌렀는지 여부(liked)를 확인
    • 또한 해당 책의 카테고리 정보도 함께 가져옴
    • 결론 : 사용자 인터페이스에서 책의 상세 페이지를 보여줄 때 유저가 좋아요를 눌렀는지 여부와 좋아요 수를 함께 표시
      SELECT *, 
        (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
        (SELECT EXISTS (SELECT * FROM likes WHERE user_id=1 AND liked_book_id=1)) AS liked 
        FROM books 
        LEFT JOIN category 
        ON books.category_id = category.category_id
        WHERE books.id=1;
      

      alt text




🌊 나는 개발한다 고로 나는 EXISTS 한다.

💫 나는 개발한다 고로 나는 EXISTS 한다.

alt text

<POSTMAN 실행결과>
alt text

  • 서브 쿼리를 이용해 잘 작동하는 걸 확인


alt text

SELECT EXISTS (SELECT * FROM likes WHERE user_id=1 AND liked_book_id=1);

alt text

SELECT count(*) FROM likes WHERE user_id=1 AND liked_book_id=1;
  • 두 sql문이 같은 의미임을 알 수 있음!

🌊 좋아요 했는지 여부도 알려주기

💫 좋아요 했는지 여부도 알려주기

alt text

  • likes와 liked로 좋아요 여부 표시 가능하게 함

alt text

alt text

<POSTMAN 실행결과>
alt text

  • 그런데 출력에서 id값이 왜 0이지!?

🌊 category_id? id?!

💫 category_id? id?!

category_id : 0 값이 POSTMAN에서 출력할 때 덮어쓰기되어 id : 0으로 나오는 것

alt text
alt text

<POSTMAN 실행결과>
alt text

SELECT *, 
	(SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
	(SELECT EXISTS (SELECT * FROM likes WHERE user_id=1 AND liked_book_id=1)) AS liked 
    FROM books 
    LEFT JOIN category 
    ON books.category_id = category.category_id
    WHERE books.id=1;
  • category 테이블에서 id를 category_id로 이름을 변경해줌. 잘 작동됨!

🌊 느낀 점(YWT)

Y 일을 통해 명확히 알게 되었거나 이해한 부분(한 일)에 대해 정리 :
count(), AS, 서브쿼리

W 배운 점과 시사점 :
🙌 서브(sub) 쿼리 : 쿼리 안에 쿼리

  • 데이터의 양이 많다면, JOIN과 GROUP BY를 사용하는 것이 더 효율적!!

🙌 count() : 행 개수

🙌 AS : 컬럼 별칭

T 응용하여 배운 것을 어디에 어떻게 적용할지:
항상 출력을 할 때 테이블을 수정하지 않고도 원하는 데이터를 출력할 수 있는 방법이 있다는 걸 잊지 말기!