진행 과정
- 기획
- 버튼 생성
- 틀 구성
- table 작성
- post 객체 정의
- post 조회
- post 작성
- prisma-express 설정
- editor에 title 넣는 곳
- post 객체 재정의
- REST API 설계
- REST API 작성
- frontend - backend 연결 - (part 2 에서 계속)
기획
이동 방법:
- navbar 에 있는 햄버거 버튼 클릭 메뉴 중 게시판 주제 버튼 클릭 클릭
게시판 화면:
- 다른 사이트 참고
버튼 생성
생성 방법:
- 기존 mui 사용 (Menu 아래 MenuItem 하나 더 추가)
틀 구성
틀 위치:
- 테이블이 보여질 <div> 와 </div> 사이
버튼 액션:
- 분기에 사용할 boolean state 값 필요
const [news, setNews] = useState(false);
{
news === true ?
<Box>
</Box>
:
<Box>
</Box>
}
table 작성
테이블 틀:
- https://mui.com/material-ui/react-table/#system-BasicTable.js 참고
글 작성 버튼:
- https://mui.com/material-ui/react-button/#system-BasicButtons.js 참고
pagination 틀:
- https://mui.com/material-ui/react-table/#system-CustomPaginationActionsTable.js 참고
- Table Pagination component customize 가능
-- 예) 생성 버튼을 추가하고 싶으면, ActionsComponent 에 대응되는 component에 추가하면 됨
post 객체 정의
attributes:
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[]
}
post 조회
틀 작성:
import * as React from 'react';
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Chip from '@mui/material/Chip';
const Post = ({ post }) => {
return (
<Card sx={{ margin: 2 }}>
<CardContent>
<Typography variant="h5" component="div">
{post.title}
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
Written by {post.author}
</Typography>
<Typography variant="body2">
{post.content}
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
Posted on {new Date(post.dateCreated).toLocaleDateString()}
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
{post.views} views
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
{post.likes} likes
</Typography>
<Box sx={{ '& > :not(style)': { m: 0.5 } }}>
{post.tags.map((tag, index) => (
<Chip key={index} label={tag} variant="outlined" />
))}
</Box>
</CardContent>
</Card>
);
};
export default Post;
데이터 전달:
<Post post={myPostData} />
post 작성
WYSIWYG editor 적용:
- open source 선택: 가장 쉬운 react-quill 사용
import React, { useState } from 'react';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
function MyComponent() {
const [value, setValue] = useState('');
return <ReactQuill theme="snow" value={value} onChange={setValue} />;
}
- action 설정:
"NEW" 버튼 클릭 시 editor가 호출 되도록 함
- POST 버튼 틀 작성:
추후 "POST" 버튼 클릭 시 작성한 내용이 서버에 저장 될 수 있도록
- CANCEL 버튼 틀 작성:
추후 "CANCEL" 버튼 클릭 시 작성 취소하고 되돌아 갈 수 있도록
prisma-express 설정
prisma-express 설치:
npx try-prisma@latest --template typescript/rest-express
cd rest-express
npm install
MariaDB 연결:
- prisma/schema.prisma 수정
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
- .env 수정
DATABASE_URL="mysql://yourid:yourpassword@localhost:3306/iamsolo_db"
- DDL 실행
CREATE USER 'yourid'@'localhost' IDENTIFIED BY 'yourpassword';
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD, INDEX on *.* TO 'yourid'@'localhost' WITH GRANT OPTION;
CREATE DATABASE iamsolo_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- dummy data 생성
npx prisma migrate dev --name init
- 서버 실행
npm run dev
post 객체 재정의
react-quill content 저장 시 데이터 구조:
- content 값은 delta라는 JSON으로 저장됨. 이 값을 db에 write하면 됨.
// const editorRef = useRef(null);
// <ReactQuill ref={editorRef} theme="snow" value={value} onChange={setValue} />
const getDataModel = () => {
if (editorRef.current) {
const quill = editorRef.current.getEditor();
const delta = quill.getContents();
return delta;
}
return null;
};
const dataModel = getDataModel();
const jsonData = dataModel ? dataModel.ops : [];
console.log(JSON.stringify(jsonData));
post 틀에서 필요한 정보:
- title
- author
- content
- dateCreated
- views
- likes
- tags
post 객체 재정의:
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
content String?
published Boolean @default(false)
views Int @default(0)
likes Int @default(0)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
prisma model 작성:
- schema.prisma 수정
db update:
npx prisma migrate dev --name updated_post_object
REST API 설계
post 생성 API:
- path: /post
- method: POST
- request body:
- title
- content
- response body:
- post 객체의 attribute. prisma 에서 자동 생성
post 조회 API:
- path: /post
- method: GET
- request body: 없음
- response body:
- post 객체 list
REST API 작성
index.ts 수정:
app.post(`/post`, async (req, res) => {
const { title, content } = req.body
const result = await prisma.post.create({
data: {
title,
content,
},
})
res.json(result)
})
app.get(`/post`, async (req, res) => {
const posts = await prisma.post.findMany()
res.json(posts)
})
'웹' 카테고리의 다른 글
nodejs) getRandomItem - 임의로 1개 선택해서 반환하기 - 개발 기록 1 (0) | 2024.05.26 |
---|---|
[mui][nextjs][prisma] 게시판 만들기 - part 2 (reactjs를 nextjs로 포팅) (0) | 2023.11.01 |
react, figma 사용해서 webview 앱 용 icon.png 생성 (0) | 2023.10.18 |
[react-native] react 로 만든 web 사이트를 android / ios 앱으로 만들기 (webview 이용) (0) | 2023.10.18 |
[ML][React] 카카오 애드핏 - 나는 솔로 테스트 를 통한 수익화 (Kakao Adfit 연동) (2) | 2023.10.11 |