board, comment 인증 로직 적용하기 + 추가구현React+REST API 게시판 구현/BE - TypeORM2021. 9. 26. 04:07
Table of Contents
엔티티 변경하기
- 사용자는 여러개의 게시판을 쓸 수 있으므로 user와 board는 one to many 관계를 설정한다.
- comment도 마찬가지로 user와 one to many 관계이다!
- 따라서 board, comment와 user 는 many to one 관계이다.
- User, Board, Comment 엔티티를 아래처럼 관계를 적용하여 변경하자.
User 엔티티
src/entity/User.ts
- board와 one to many, comment와 one to many 관계 설정
import {
Column,
CreateDateColumn,
Entity,
JoinTable,
ManyToMany, OneToMany,
PrimaryGeneratedColumn,
Unique,
UpdateDateColumn
} from "typeorm";
import {Role} from "./Role";
import {Board} from "./Board";
import {Comment} from "./Comment";
@Entity()
@Unique(['email'])
export class User {
@PrimaryGeneratedColumn({type: "bigint"})
id: number;
@Column({length: 255})
email: string;
@Column({length: 255})
password: string;
@Column({length: 255})
username: string;
@CreateDateColumn()
created: Date;
@UpdateDateColumn()
updated: Date;
@ManyToMany(() => Role, role => role.users)
@JoinTable({
name: "user_role",
joinColumn: {name: "user_id", referencedColumnName: "id"},
inverseJoinColumn: {name: "role_id", referencedColumnName: "id"}
})
roles: Role[];
@OneToMany(type => Board, board => board.user)
boards: Board[];
@OneToMany(type => Comment, comment => comment.user)
comments: Comment[];
}
Board 엔티티
src/entity/Board.ts
- user와 many to one 관계 추가
- 또한 join 없이 user의 id를 가져오기 위해 userId Column 추가! user가 작성한 게시물을 가져올 때 사용!
- 이름을 camel case로 만들면 알아서 fk인 user_id가 userId라는 Column에 매핑된다!!
import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn
} from "typeorm";
import {Comment} from './Comment';
import {User} from "./User";
@Entity()
export class Board {
@PrimaryGeneratedColumn()
id: number;
@Column({length: 100})
title: string;
@Column("text")
content: string;
@CreateDateColumn()
created: Date;
@UpdateDateColumn()
updated: Date;
@OneToMany(type => Comment, comment => comment.board)
comments: Comment[];
// user와 관계 설정
@ManyToOne(type => User, user => user.boards)
user: User;
// join 없이 user의 id 가져오기
@Column()
userId: number;
}
Comment 엔티티
src/entity/Comment.ts
import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
UpdateDateColumn
} from "typeorm";
import {Board} from "./Board";
import {User} from "./User";
@Entity()
export class Comment {
@PrimaryGeneratedColumn()
id: number;
@Column("text")
content: string;
@CreateDateColumn()
created: Date;
@UpdateDateColumn()
updated: Date;
@ManyToOne(type => Board, board => board.comments, {onDelete: 'CASCADE', onUpdate: "CASCADE"})
board: Board;
@ManyToOne(type => User, user => user.comments)
user: User;
}
Controller에 User 정보 적용하기
- board의 작성자를 표시하기 위해서는 controller에 사용자 정보를 포함해야 한다.
- 또한 comment의 작성자를 표시하기 위해서는 controller에 사용자 정보를 포함해야 한다!
Board 추가 컨트롤러에 User 정보 적용하기
- board를 처리하는 controller에 user 정보를 적용하자.
src/controller/BoardController.ts
// board entity
import {Board} from "../entity/Board";
// user entity
import {User} from "../entity/User";
// image Entity
import {Image} from "../entity/Image";
import {getConnection} from "typeorm";
export class BoardController {
...
/// board 추가 컨트롤러
static addBoard = async (req, res) => {
// board 저장
// body에서 user_id를 추가로 받아옴
const {title, content, user_id} = req.body;
// user_id에 해당하는 user를 찾아옴
const user = await getConnection().getRepository(User).findOne({id: user_id});
const board = new Board();
board.title = title;
board.content = content;
// board에 user 추가
board.user = user;
const result = await getConnection().getRepository(Board).save(board)
// image 저장 one-to-one 관계인 board 저장
let image: Image = new Image();
image.data = req.file.buffer;
image.original_name = req.file.originalname;
image.mimetype = req.file.mimetype;
image.board = result;
await getConnection().getRepository(Image).save(image);
res.send({"message": "success!"})
}
...
}
user가 작성한 Board 목록, 갯수 리턴하는 컨트롤러 추가하기
- 쿼리 파라미터로 user의 id를 넘기면 해당 유저가 작성한 글을 리턴하는 컨트롤러 추가.
- page_number와 page_size도 쿼리 파라미터로 받을 수 있고 만약 둘 중 하나라도 없으면 user가 작성한 전체 글 목록 리턴
- user가 작성한 board 갯수를 리턴하는 이유는 페이지네이션을 구현하기 위해서이다!
src/controller/BoardController.ts
// board entity
import {Board} from "../entity/Board";
// user entity
import {User} from "../entity/User";
// image Entity
import {Image} from "../entity/Image";
import {getConnection} from "typeorm";
export class BoardController {
...
// user가 등록한 board 가져오기
static findAllUserBoard = async (req, res) => {
const {user_id, page_number, page_size} = req.query;
const options = {};
options['select'] = ["id", "title", "content", "created", "updated"];
options['order'] = {id: 'DESC'};
options['relations'] = ['user'];
options['where'] = {userId: user_id};
// page_number와 page_size 둘 중하나라도 입력하지 않으면 전체 목록 리턴
if (page_number && page_size) {
options['skip'] = (page_number - 1) * page_size;
options['take'] = page_size;
}
const boards = await getConnection().getRepository(Board).find(options);
res.send(boards);
}
// user가 등록한 board 갯수
static countUserBoard = async (req, res) => {
const {user_id} = req.params;
const total = await getConnection().getRepository(Board).find({
where: {userId: user_id},
})
res.send({total: total.length});
}
...
}
Comment 컨트롤러 전체에 User 정보 적용하기 + 페이지 네이션 추가
- comment를 처리하는 controller에 user 정보를 적용하자.
- 쿼리문을 생성하는 부분을 createQueryBuilder로 수정했다!
- 기존에 board의 id에 해당하는 전체 comment를 가져오는 부분을 페이지네이션으로 변경
- 클라이언트에서 페이지네이션을 구현하기 위해 board의 id에 해당하는 전체 comment 갯수를 리턴하는 로직 추가
src/controller/CommentController.ts
import {getConnection} from "typeorm";
import {Comment} from "../entity/Comment";
import {Board} from "../entity/Board";
import {User} from "../entity/User";
export class CommentController {
static addComment = async (req, res) => {
const {board_id, content, user_id} = req.body;
const board = await getConnection().getRepository(Board).findOne({id: board_id});
const user = await getConnection().getRepository(User).findOne({id: user_id});
const comment = new Comment();
comment.content = content;
comment.board = board;
comment.user = user;
await getConnection().getRepository(Comment).save(comment);
res.send(comment);
}
// comment를 가져오는 부분을 페이지네이션으로 변경
static findAllComment = async (req, res) => {
const {board_id, page_number, page_size} = req.query;
const options = {};
options['select'] = ["id", "content", "created", "updated"];
options['order'] = {id: 'DESC'};
options['relations'] = ['user', 'board']
options['where'] = [{boardId: board_id}]
// page_number와 page_size 둘 중하나라도 입력하지 않으면 전체 목록 리턴
if (page_number && page_size) {
options['skip'] = (page_number - 1) * page_size;
options['take'] = page_size;
}
const comments = await getConnection().getRepository(Comment).find(options);
res.send(comments);
}
// board의 전체 comment 갯수
static countBoardComment = async (req, res) => {
const {board_id} = req.query;
const total = await getConnection().getRepository(Comment).find({
where: {boardId: board_id},
})
res.send({total: total.length});
}
static findOneComment = async (req, res) => {
const {id} = req.query;
const comment = await getConnection().getRepository(Comment).findOne({id});
console.log(comment);
res.send(comment);
}
static modifyComment = async (req, res) => {
const {id, content} = req.body;
const result = await getConnection().createQueryBuilder().update(Comment)
.set({content})
.where("id = :id", {id})
.execute();
res.send(result);
}
static removeComment = async (req, res) => {
const {id} = req.query;
const result = await getConnection()
.createQueryBuilder()
.delete()
.from(Comment)
.where("id = :id", {id})
.execute();
res.send(result);
}
}
꼭 읽어라!
- 앞으로 board 추가, comment 추가할 때 헤더에 토큰을 넣고 body에 user_id를 추가로 넣어야 한다!!
'React+REST API 게시판 구현 > BE - TypeORM' 카테고리의 다른 글
미들웨어 설정 + 추가 라우팅 (0) | 2021.09.26 |
---|---|
회원가입, 로그인 구현 (0) | 2021.09.24 |
인증과 권한 설계 (0) | 2021.09.24 |
commet CRUD API (0) | 2021.09.24 |
board에 image 추가하기 (0) | 2021.09.24 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!