1. DDL 작성하기 (게시글 조회 VIEW)

CREATE OR REPLACE VIEW board_list_view AS
SELECT
    B.board_number AS board_number
  , B.title AS title
  , B.content AS content
  , I.image AS image
  , B.favorite_count AS favorite_count
  , B.comment_count AS comment_count
  , B.view_count AS view_count
  , B.write_datetime AS write_datetime
  , B.writer_email AS writer_email
  , U.nickname AS writer_nickname
  , U.profile_image AS writer_profile_image
FROM board AS B
INNER JOIN user AS U
ON B.writer_email = U.email
LEFT JOIN (SELECT board_number, ANY_VALUE(image) AS image FROM image GROUP BY board_number) AS I
ON B.board_number = I.board_number;

 

2. API 기반 DML 작성하기

-- Active: 1725368211487@@localhost@3306@board
-- 회원가입
INSERT INTO user VALUES ('email@email.com', 'P!ssw0rd', 'nickname', '01012345678', '서울특별시 종로구', '그랑서울', null);

-- 로그인
SELECT * FROM user WHERE email = 'email@email.com';

-- 게시물 작성
INSERT INTO board (title, content, write_datetime, favorite_count, comment_count, view_count, writer_email)
VALUES ('제목', '내용', '2024-09-06 23:25:54', 0, 0, 0, 'email@email.com');

INSERT INTO image
VALUES (2, 'url');

-- 댓글 작성
INSERT INTO comment (content, write_datetime, user_email, board_number)
VALUES ('반갑습니다', '2024-09-06 23:28:50', 'email@email.com', 3);

UPDATE board
SET comment_count = comment_count + 1
WHERE board_number = 2;

-- 좋아요 등록, 취소
INSERT INTO favorite
VALUES ('email@email.com', 2);

UPDATE board
SET favorite_count = favorite_count + 1
WHERE board_number = 2;

DELETE FROM favorite
WHERE user_email = 'email@email.com'
AND board_number = 2;

UPDATE board
SET favorite_count = favorite_count - 1
WHERE board_number = 2;

-- 게시물 수정
UPDATE board
SET title = '수정 제목'
  , content = '수정 내용'
WHERE board_number = 2;

DELETE FROM image
WHERE board_number = 2;

INSERT INTO image
VALUES (2, 'url');

INSERT INTO image
VALUES (3, 'url3');

-- 게시물 삭제
DELETE FROM comment WHERE board_number = 2;
DELETE FROM favorite WHERE board_number = 2;
DELETE FROM image WHERE board_number = 2;
DELETE FROM board WHERE board_number = 2;

-- 상세 게시물 불러오기
SELECT
    B.board_number AS board_number
  , B.title AS title
  , B.content AS content
  , B.write_datetime AS write_datetime
  , B.writer_email AS writer_email
  , U.nickname AS nickname
  , U.profile_image AS profile_image
FROM board AS B
INNER JOIN user AS U
ON B.writer_email = U.email
WHERE board_number = 2;

SELECT image
FROM image
WHERE board_number = 2;

SELECT
    U.email AS email
  , U.nickname AS nickname
  , U.profile_image AS profile_image
FROM favorite AS F
INNER JOIN user AS U
ON F.user_email = U.email
WHERE F.board_number = 2;

SELECT
    U.nickname AS nickname
  , U.profile_image AS profile_image
  , C.write_datetime AS write_datetime
  , C.content AS content
FROM comment AS C
INNER JOIN user AS U
ON C.user_email = U.email
WHERE C.board_number = 2
ORDER BY write_datetime DESC;

-- 최신 게시물 리스트 불러오기

SELECT *
FROM board AS B
INNER JOIN user AS U
ON B.writer_email = U.email
LEFT JOIN image AS I
ON B.board_number = I.board_number;

-- 최신 게시물 리스트 불러오기 (image row 중복 제거)
-- SELECT
--     B.board_number AS board_number
--   , B.title AS title
--   , B.content AS content
--   , I.image AS image
--   , B.favorite_count AS favorite_count
--   , B.comment_count AS comment_count
--   , B.view_count AS view_count
--   , B.write_datetime AS write_datetime
--   , U.nickname AS writer_nickname
--   , U.profile_image AS writer_profile_image
-- FROM board AS B
-- INNER JOIN user AS U
-- ON B.writer_email = U.email
-- LEFT JOIN (SELECT board_number, ANY_VALUE(image) AS image FROM image GROUP BY board_number) AS I
-- ON B.board_number = I.board_number
SELECT * FROM board_list_view
ORDER BY write_datetime DESC
-- LIMIT 0, 5; -- (페이지 - 1) * 5
LIMIT 5, 5;

-- 검색어 리스트
-- SELECT
--     B.board_number AS board_number
--   , B.title AS title
--   , B.content AS content
--   , I.image AS image
--   , B.favorite_count AS favorite_count
--   , B.comment_count AS comment_count
--   , B.view_count AS view_count
--   , B.write_datetime AS write_datetime
--   , U.nickname AS writer_nickname
--   , U.profile_image AS writer_profile_image
-- FROM board AS B
-- INNER JOIN user AS U
-- ON B.writer_email = U.email
-- LEFT JOIN (SELECT board_number, ANY_VALUE(image) AS image FROM image GROUP BY board_number) AS I
-- ON B.board_number = I.board_number
SELECT * FROM board_list_view
WHERE title LIKE '%수정%' OR content LIKE '%수정%'
ORDER BY write_datetime DESC;

-- 검색어 주간 상위 TOP 3 불러오기
-- SELECT
--     B.board_number AS board_number
--   , B.title AS title
--   , B.content AS content
--   , I.image AS image
--   , B.favorite_count AS favorite_count
--   , B.comment_count AS comment_count
--   , B.view_count AS view_count
--   , B.write_datetime AS write_datetime
--   , U.nickname AS writer_nickname
--   , U.profile_image AS writer_profile_image
-- FROM board AS B
-- INNER JOIN user AS U
-- ON B.writer_email = U.email
-- LEFT JOIN (SELECT board_number, ANY_VALUE(image) AS image FROM image GROUP BY board_number) AS I
-- ON B.board_number = I.board_number
SELECT * FROM board_list_view
WHERE write_datetime BETWEEN '2024-09-02 00:00:00' AND '2024-09-08 23:59:59'
ORDER BY favorite_count DESC, comment_count DESC, view_count DESC, write_datetime DESC
LIMIT 3; -- 3개만

-- 특정 유저 게시물 리스트 불러오기
-- SELECT
--     B.board_number AS board_number
--   , B.title AS title
--   , B.content AS content
--   , I.image AS image
--   , B.favorite_count AS favorite_count
--   , B.comment_count AS comment_count
--   , B.view_count AS view_count
--   , B.write_datetime AS write_datetime
--   , U.nickname AS writer_nickname
--   , U.profile_image AS writer_profile_image
-- FROM board AS B
-- INNER JOIN user AS U
-- ON B.writer_email = U.email
-- LEFT JOIN (SELECT board_number, ANY_VALUE(image) AS image FROM image GROUP BY board_number) AS I
-- ON B.board_number = I.board_number
SELECT * FROM board_list_view
WHERE writer_email = 'email@email.com'
ORDER BY write_datetime DESC, board_number DESC;

-- 인기 검색어 리스트
SELECT search_word, count(search_word) AS count -- search_word를 기준으로 count를 친다.
FROM search_log
WHERE relation IS FALSE -- 관계형이 아닌 것
GROUP BY search_word;   -- search_word로 group by 해준다.
ORDER BY count DESC
LIMIT 15;

-- 관련 검색어 리스트
SELECT relation_word, count(relation_word) AS count
FROM search_log
WHERE search_word = '검색어'
GROUP BY relation_word
ORDER BY count DESC
LIMIT 15;

-- 유저 정보 불러오기 / 로그인 유저 정보 불러오기
SELECT *
FROM user
WHERE email = 'email@email.com';

-- 닉네임 수정하기
UPDATE user
SET nickname = '수정 닉네임'
WHERE email = 'email@email.com';

-- 프로필 이미지 수정
UPDATE user
SET profile_image = 'new_profile_url'
WHERE email = 'email@email.com';

 


출처 : 
https://www.youtube.com/@jiraynorprogramming1589

1. VSCode에서 ERD Editor 설치

 

 

2. API를 기반으로 ERD 작성

 

 

3. DDL 추출

-- Active: 1725368211487@@localhost@3306@board
CREATE TABLE board
(
  board_number   INT         NOT NULL AUTO_INCREMENT COMMENT '게시물 번호',
  title          TEXT        NOT NULL COMMENT '게시물 제목',
  content        TEXT        NOT NULL COMMENT '게시물 내용',
  write_datetime DATETIME    NOT NULL COMMENT '게시물 작성 날짜 및 시간',
  favorite_count INT         NOT NULL DEFAULT 0 COMMENT '게시물 좋아요 수',
  comment_count  INT         NOT NULL DEFAULT 0 COMMENT '게시물 댓글 수',
  view_count     INT         NOT NULL DEFAULT 0 COMMENT '게시물 조회 수',
  writer_email   VARCHAR(50) NOT NULL COMMENT '게시물 작성자 이메일',
  PRIMARY KEY (board_number)
) COMMENT '게시물 테이블';

CREATE TABLE comment
(
  comment_number INT         NOT NULL COMMENT '댓글 번호',
  content        TEXT        NOT NULL COMMENT '댓글 내용',
  write_datetime DATETIME    NOT NULL COMMENT '작성 날짜 및 시간',
  user_email     VARCHAR(50) NOT NULL COMMENT '사용자 이메일',
  board_number   INT         NOT NULL COMMENT '게시물 번호',
  PRIMARY KEY (comment_number)
) COMMENT '댓글 테이블';

CREATE TABLE favorite
(
  user_email   VARCHAR(50) NOT NULL COMMENT '사용자 이메일',
  board_number INT         NOT NULL COMMENT '게시물 번호',
  PRIMARY KEY (user_email, board_number)
) COMMENT '좋아요 테이블';

CREATE TABLE image
(
  board_number INT  NOT NULL COMMENT '게시물 번호',
  image        TEXT NOT NULL COMMENT '게시물 이미지 URL'
) COMMENT '게시물 이미지 테이블';

CREATE TABLE search_log
(
  sequence      INT     NOT NULL AUTO_INCREMENT COMMENT '시퀀스',
  search_word   TEXT    NOT NULL COMMENT '검색어',
  relation_word TEXT    NULL     COMMENT '관련 검색어',
  relation      BOOLEAN NOT NULL COMMENT '관련 검색어 여부',
  PRIMARY KEY (sequence)
) COMMENT '검색 기록 테이블';

CREATE TABLE user
(
  email          VARCHAR(50)  NOT NULL COMMENT '사용자 이메일',
  password       VARCHAR(100) NOT NULL COMMENT '사용자 비밀번호',
  nickname       VARCHAR(20)  NOT NULL UNIQUE COMMENT '사용자 닉네임',
  tel_number     VARCHAR(15)  NOT NULL UNIQUE COMMENT '사용자 휴대전화번호',
  address        TEXT         NOT NULL COMMENT '사용자 주소',
  address_detail TEXT         NULL     COMMENT '사용자 상세 주소',
  profile_image  TEXT         NULL     COMMENT '사용자 프로필 사진 URL',
  PRIMARY KEY (email)
) COMMENT '사용자 테이블';

ALTER TABLE image
  ADD CONSTRAINT FK_board_TO_image
    FOREIGN KEY (board_number)
    REFERENCES board (board_number);

ALTER TABLE board
  ADD CONSTRAINT FK_user_TO_board
    FOREIGN KEY (writer_email)
    REFERENCES user (email);

ALTER TABLE favorite
  ADD CONSTRAINT FK_user_TO_favorite
    FOREIGN KEY (user_email)
    REFERENCES user (email);

ALTER TABLE favorite
  ADD CONSTRAINT FK_board_TO_favorite
    FOREIGN KEY (board_number)
    REFERENCES board (board_number);

ALTER TABLE comment
  ADD CONSTRAINT FK_user_TO_comment
    FOREIGN KEY (user_email)
    REFERENCES user (email);

ALTER TABLE comment
  ADD CONSTRAINT FK_board_TO_comment
    FOREIGN KEY (board_number)
    REFERENCES board (board_number);

 

 

4. developer 사용자 생성 및 권한 부여

CREATE USER 'developer'@'*' IDENTIFIED BY 'P!ssw0rd';

# grant to 'developer'@'*'
GRANT SELECT, UPDATE, DELETE, INSERT
ON board.*
TO 'developer'@'*';

 

출처 : https://www.youtube.com/@jiraynorprogramming1589

1. 프로젝트 주제 : 블로그형 게시판 만들기

 

   [화면 미리보기]

 

2. 기술 스택

 

[백엔드]

 - Java 17

 - Gradle

 

[프론트]

 - React.js

 

[DB]

 - MySQL

 

[IDE]
 - Visual Studio Code

 

3. API 설계

========================================

signIn (로그인)

- request
{
    이메일주소 : 문자열,
    비밀번호 : 문자열
}

- response

성공
{
    코드: 문자열,
    메시지: 문자열
}

실패

- 로그인 실패
Http Status - 401 (인증 실패 Unauthorized)
{
    code: "SF",
    message: "Sign In Failed."
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "Database Error."
}

========================================

signUp (회원가입)

- request

{
    "email: String,
    "password: String,
    "nickname: String,
    "telNumber: String, (0을 처음에 받으면 정수로 못받음, 그래서 문자열로 받음)
    "address: String,
    "addressDetail: String
}

- response

성공
Http Status - 200
{
    code: "SU",
    message: "Success.",
    token: "jwt ... token..",
    expiredDate: 123456789
}

실패

- 필수 정보 미입력
Http Status - 400 (Bad Request)
{
    code: "SU",
    message: "Existed Email",
}

- 이메일 중복

Http Status - 400 (Bad Request)
{
    code: "SU",
    message: "Existed Email",
}

- 필수 정보 미입력 / 이메일 포맷 불일치 / 비밀번호 8자 미만 / 전화번호 포맷 불일치
Http Status - 400 (Bad Request)
{
    code: "SU",
    message: "Existed Email",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "Existed Email",
}

========================================

weeklyTop3List (주간 상위 3 게시물 리스트)

- response
Http Status - 200 (OK)
성공
{
    code: "SU",
    message: "Success.",
    top3List: boardListItem[]
}

BoardListItem
{
    boardNumber: int,
    title: String,
    content: String,
    boardTitleImage: string(url),
    favoriteCount: int,
    commentCount: int,
    viewCount: int,
    writeDatetime: String,
    writerNickname: String,
    writerProfileImage: String(url)
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

currentList (최신 게시물 리스트)

- response
Http Status - 200 (OK)
성공
{
    code: "SU",
    message: "Success.",
    top3List: boardListItem[]
}

BoardListItem
{
    boardNumber: int,
    title: String,
    content: String,
    boardTitleImage: string(url),
    favoriteCount: int,
    commentCount: int,
    viewCount: int,
    writeDatetime: String,
    writerNickname: String,
    writerProfileImage: String(url)
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

popularWordList (인기 검색어 리스트)

- response
Http Status - 200 (OK)
성공
{
    code: "SU",
    message: "Success.",
    popularWordList: String[]
}

실패
- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}
========================================

searchList (검색 게시물 리스트)

- response

성공
Http Status - 200 (OK)
{
    code: "SU",
    message: "Success.",
    searchList: boardListItem[]
}

BoardListItem
{
    boardNumber: int,
    title: String,
    content: String,
    boardTitleImage: string(url),
    favoriteCount: int,
    commentCount: int,
    viewCount: int,
    writeDatetime: String,
    writerNickname: String,
    writerProfileImage: String(url)
}

실패
- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

relativeWordList (관련 검색어 리스트)

- response
Http Status - 200 (OK)
성공
{
    code: "SU",
    message: "Success.",
    relativeWordList: String[]
}

실패
- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}
========================================

boardDetail (게시물 상세 보기)

- response
성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success.",
    boardNumber: int,
    title: String,
    content: String,
    boardImage: string[],
    writeDatetime: String,
    writerEmail: String,
    writerNickname: String,
    writerProfileImage: String
}

실패
- 존재하지 않는 게시물
Http Status - 400 (Bad Request)
{
    code: "NB",
    message: "No Exist Board Number",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

favoriteList (좋아요 리스트)

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success.",
    favoriteList: FavoriteListItem[]
}

FavoriteListItem
{
    email: String,
    nickname: String,
    profileImage: String,
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

putFavorite (좋아요 기능)

- request

{
    boardNumber: int
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

commentList (댓글 리스트)

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success.",
    commentList: CommentListItem[]
}

CommentListItem
{
    email: String,
    nickname: String,
    writeDatetime: String,
    content: String
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

postComment (댓글 쓰기)

- request

{
    content: String
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 게시물

Http Status - 400 (Bad Request)
{
    code: "NB",
    message: "No Existed Board",
}

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

boardDelete (게시물 삭제)

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 권한 없음
Http Status - 403 (Forbidden)
{
    code: "NP",
    message: "No Permission",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

boardWrite (게시물 쓰기)
- request

{
    "title": String,
    "title": String,
    boardImageList: string[]
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

boardUpdate (게시물 수정)

- request

{
    "title": String,
    "title": String,
    boardImageList: string[]
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 권한 없음
Http Status - 403 (Forbidden)
{
    code: "NP",
    message: "No Permission",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

getUser (유저 정보 불러오기)

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success.",
    email: String,
    nickname: String,
    profileImage: String
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

userBoardList (특정 유저 게시물 리스트)

- response

성공
Http Status - 200 (OK)
{
    code: "SU",
    message: "Success.",
    boardList: boardListItem[]
}

BoardListItem
{
    boardNumber: int,
    title: String,
    content: String,
    boardTitleImage: string(url),
    favoriteCount: int,
    commentCount: int,
    viewCount: int,
    writeDatetime: String,
    writerNickname: String,
    writerProfileImage: String(url)
}

실패
- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

patchNickname (닉네임 수정)

- request

{
    nickname: String
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

patchProfileImage (유저 프로필 이미지 수정)

- request

{
    profileImage: String
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 존재하지 않는 유저

Http Status - 400 (Bad Request)
{
    code: "NU",
    message: "No Existed User",
}

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

fileUpload (파일 업로드)
- request

{
    boardNumber: int
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

getFile (파일 불러오기)
- request

{
    boardNumber: int
}

- response

성공

Http Status - 200 (OK)

{
    code: "SU",
    message: "Success."
}

실패

- 데이터베이스 에러
Http Status - 500 (Internal Server Error)
{
    code: "DE",
    message: "",
}

========================================

 

출처 : https://www.youtube.com/@jiraynorprogramming1589

+ Recent posts