개발환경
- mac, vscode
- language : typescript
- framework: react,node
- database : mongodb
- library : mongoose,express,jwt,bcrypt 등
깃허브 레파지토리 : https://github.com/jdy0120/doyeonpedia
인스타그램같은 소셜 서비스를 만들기 위해 시작했습니다.
full stack으로 개발을 진행했으며
front-end : react
back-end : node
database : mongodb
를 사용했습니다.
(배포는 하지 않았습니다.)
프론트엔드 디자인부분은 material-ui를 사용하였으며 백엔드의 api는 express를 사용하여 개발을 진행했습니다.
테이블 구조
user | posts |
_id
firstName
lastName
email
password
picturePath
friends
location
occupation
impressions
createdAt
updatedAt
|
_id
userId
firstName
lastName
location
description
picturePath
userPicturePath
likes
comments
createdAt
updatedAt
|
User 스키마
import mongoose from "mongoose";
const UserSchema = new mongoose.Schema(
{
firstName: {
type: String,
required: true,
min: 2,
max: 50,
},
lastName: {
type: String,
required: true,
min: 2,
max: 50,
},
email: {
type: String,
required: true,
max: 50,
unique: true,
},
password: {
type: String,
required: true,
max: 50,
},
picturePath: {
type: String,
default: "",
},
friends: {
type: Array,
default: [],
},
location: String,
occupation: String,
viewdProfile: Number,
impressions: Number,
},
{ timestamps: true }
);
const User = mongoose.model("User", UserSchema);
export default User;
Posts스키마
import mongoose from "mongoose";
const postSchema = new mongoose.Schema(
{
userId: {
type: String,
require: true,
},
firstName: {
type: String,
require: true,
},
lastName: {
type: String,
require: true,
},
location: String,
description: String,
picturePath: String,
userPicturePath: String,
likes: {
type: Map,
of: Boolean,
},
comments: {
type: Array,
default: [],
},
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
export default Post;
인증을 위한 미들웨어
import jwt from "jsonwebtoken";
import { Request, Response, NextFunction } from "express";
export const verifyToken = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
let token = req.header("Authorization");
if (!token) {
return res.status(403).send("Access Denied");
}
if (token.startsWith("Doyeon ")) {
token = token.slice(7, token.length).trim();
}
const secretKey = process.env.JWT_SECRET;
const verified = secretKey
? jwt.verify(token, secretKey)
: new Error("Cannot find JWT_SECRETKEY");
req.body.user = verified;
next();
} catch (err) {
res.status(500).json({ error: err.message });
}
};
주요기능은 다음과 같습니다.
1. 로그인
/** LOGGING IN */
export const login = async (req: Request, res: Response) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email: email });
if (!user) return res.status(400).json({ msg: "User does not exist. " });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ msg: "Invalid credentials. " });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET);
delete user.password;
res.status(200).json({ token, user });
} catch (err) {
res.status(500).json({ error: err.message });
}
};
2. 글쓰기
/** CREATE */
export const createPost = async (req: Request, res: Response) => {
try {
const { userId, description, picturePath } = req.body;
const user = await User.findById(userId);
const newPost = new Post({
userId,
firstName: user.firstName,
lastName: user.lastName,
location: user.location,
description,
userPicturePath: user.picturePath,
picturePath,
likes: {},
comments: [],
});
await newPost.save();
const post = await Post.find();
res.status(201).json(post);
} catch (err) {
res.status(409).json({ message: err.message });
}
};
3. 글 출력
/** READ */
export const getFeedPosts = async (req: Request, res: Response) => {
try {
const post = await Post.find();
res.status(200).json(post);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
이번 프로젝트를 진행하면서 많은 것을 배웠습니다.
1. 이미지들을 서버에 저장하는 방법
2. 인증된 사용자에게만 api를 제공하는 방법(미들웨어)
3. 몽고디비를 사용하는 방법
등 문제를 해결하면서 많은 배움이 있었던 프로젝트였습니다.
지금은 로그인, 포스팅 과 같은 단순한 기능만 있지만 좀 더 고도화하여 포스트를 출력해주는 알고리즘에 대해 고민할 수도 있겠으며 녹음 파일을 포스팅하거나 지도 위치를 포스팅하는 기능도 추가할 수 있을 것 같습니다.
기회가 된다면 꾸준히 유지보수 해 완벽에 가까운 서비스를 만들어야 겠습니다.
'프로젝트' 카테고리의 다른 글
[리액트 따라하며 배우기] 스도쿠 프로젝트 1편 (0) | 2023.06.19 |
---|---|
간단한 로그인 프로젝트 (redux-toolkit, sessiontStorage) (0) | 2023.06.06 |
운동 선수 순위권 출력 프로젝트 (0) | 2022.12.13 |
Figma -> React 프로젝트 로그인 페이지 퍼블리싱 (0) | 2022.12.12 |
Figma -> React 프로젝트 대쉬보드 퍼블리싱 (0) | 2022.12.12 |