Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
260 changes: 260 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,262 @@
# powerBoost Study
## 이화여대 파워부스트 스터디

### API Endpoints

#### 1. User Registration
회원가입 기능을 제공합니다.

- **Endpoint**: `/register`
- **Method**: `POST`
- **Request Body**:
```json
{
"username": "username",
"password": "password",
"nickname": "nickname"
}
- **Response**: 201 Created

#### 2. User Login
로그인 기능을 제공합니다.

- **Endpoint**: `/login`
- **Method**: `POST`
- **Request Body**:
```json
{
"username": "username",
"password": "password"
}
```
- **Response**:
```json
{
"auth": true,
"token": "jwt_token",
"refreshToken": "refresh_jwt_token" // 3주차 추가
}
```
#### 3. Token Refresh // 3주차 추가
리프레시 토큰을 사용하여 새로운 액세스 토큰을 발급받는 기능을 제공합니다.

- **Endpoint**: `/token`
- **Method**: `POST`
- **Request Body**:
```json
{
"refreshToken": "refresh_jwt_token"
}
```
- **Response**:
```json
{
"token": "new_jwt_token"
}
```

- **Method**: `클라이언트 측에서 JWT 토큰 삭제`
#### 4. Create a Post
글 작성 기능을 제공합니다.

- **Endpoint**: `/posts`
- **Method**: `POST`
- **Headers**: `x-access-token`: `jwt_token`
- **Request Body**:
```json
{
"title": "Post Title",
"content": "Post Content"
}
```
- **Response**: 201 Created
#### 5. Update a Post
글 수정 기능을 제공합니다.

- **Endpoint**: `/posts/:id`
- **Method**: `PUT`
- **Headers**: `x-access-token`: `jwt_token`
- **Request Body**:
```json
{
"title": "Updated Title",
"content": "Updated Content"
}
```
- **Response**: 200 OK
#### 6. Delete a Post
글 삭제 기능을 제공합니다.

- **Endpoint**: `/posts/:id`
- **Method**: `DELETE`
- **Headers**: `x-access-token`: `jwt_token`
- **Response**: 200 OK
#### 7. Get All Posts
모든 게시글을 조회하는 기능을 제공합니다.

- **Endpoint**: `/posts`
- **Method**: `GET`
- **Response**:
```json
[
{
"id": 1,
"user_id": 1,
"title": "Post Title",
"content": "Post Content",
"likes": 0
}
]
```
#### 8. Get a Post
특정 게시글을 조회하는 기능을 제공합니다.

- **Endpoint**: `/posts/:id`
- **Method**: `GET`
- **Response**:
```json
{
"id": 1,
"user_id": 1,
"title": "Post Title",
"content": "Post Content",
"likes": 0
}
```
#### 9. Like a Post
게시글에 좋아요를 추가하는 기능을 제공합니다.

- **Endpoint**: `/posts/:id/like`
- **Method**: `POST`
- **Headers**: `x-access-token`: `jwt_token`
- **Response**: 200 OK
#### 10. Add a Comment
댓글 작성 기능을 제공합니다.

- **Endpoint**: `/posts/:postId/comments`
- **Method**: `POST`
- **Headers**: `x-access-token`: `jwt_token`
- **Request Body**:
```json
{
"content": "Comment Content"
}
```
- **Response**: 201 Created
#### 11. Get Comments for a Post
특정 게시글의 댓글을 조회하는 기능을 제공합니다.

- **Endpoint**: `/posts/:postId/comments`
- **Method**: `GET`
- **Response**:
```json
[
{
"id": 1,
"post_id": 1,
"user_id": 1,
"content": "Comment Content",
"userNick": "nickname" // 3주차 추가
}
]
```
#### 12. Scrap a Post // 3주차 추가
게시글을 스크랩하는 기능을 제공합니다.

- **Endpoint**: `/posts/:id/scrap`
- **Method**: `POST`
- **Headers**: `x-access-token`: `jwt_token`
- **Response**: 200 OK

#### 13. Unscrap a Post // 3주차 추가
게시글을 스크랩하는 기능을 제공합니다.

- **Endpoint**: `/posts/:id/scrap`
- **Method**: `DELETE`
- **Headers**: `x-access-token`: `jwt_token`
- **Response**: 200 OK

#### 14. Get Scrapped Posts // 3주차 추가
스크랩한 게시글들을 조회하는 기능을 제공합니다.

- **Endpoint**: `/scraps`
- **Method**: `GET`
- **Headers**: `x-access-token`: `jwt_token`
- **Response**:
```json
[
{
"id": 1,
"user_id": 1,
"title": "Post Title",
"content": "Post Content",
"likes": 0
}
]
```

#### 15. Search Posts // 3주차 추가
게시물을 검색하는 기능을 제공합니다.

- **Endpoint**: `/search`
- **Method**: `GET`
- **Query Parameters**: `query`: 검색어
- **Response**:
```json
[
{
"id": 1,
"user_id": 1,
"title": "Post Title",
"content": "Post Content",
"likes": 0
}
]
```

### 3주차 DB 캡쳐본
![Post](https://github.com/huipadyam/powerBoost/blob/chaeeun/images/db_post.png?raw=true)
![Comment](https://github.com/huipadyam/powerBoost/blob/chaeeun/images/db_comment.png?raw=true)
![Scrap](https://github.com/huipadyam/powerBoost/blob/chaeeun/images/db_scrap.png?raw=true)

### 알게 된 점
#### 1. 비밀번호 해싱
db 저장 전에 bcrypt로 해싱

const hashedPassword = bcrypt.hashSync(password, 8);
- 'password' : 해싱할 비밀번호
- '8' : 해시 알고리즘의 비용 인자. 값이 클수록 보안 강화, 해싱 오래걸림

#### 2. 비밀번호 검증
로그인 시 '입력된 비밀번호'와 'db에 저장된 해시된 비밀번호' 비교

const passwordIsValid = bcrypt.compareSync(password, user.password);
- 'password' : 입력된 비밀번호
- 'user.password' : db에 저장된 해시된 비밀번호

#### 3. JWT(JSON Web Token) 생성
비밀번호 검증 후 JWT 생성하여 사용자 세션, 인증 관리
const token = jwt.sign({ id: user.id, nickname: user.nickname }, JWT_SECRET, {
expiresIn: 86400 // 24시간 동안 유효
});
- '{ id: user.id, nickname: user.nickname }' : JWT의 payload - JWT에 사용될 사용자 정보
- 'JWT_SECRET' : 토큰을 sign하는 데 사용되는 비밀 키(토큰의 무결성과 진위 검증)
- 'expiresIn: 86400' : 유효기간. 86400초 = 24시간
- sign 함수는 생성된 JWT를 반환

#### 4. JWT 검증
사용자가 제공한 JWT의 유효성 검증, 사용자 정보 추출하여 라우트 보호
jwt.verify(token, JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(500).send('토큰 인증 실패'); // 토큰 인증 실패 시 500 응답
}

req.userId = decoded.id; // 검증된 토큰에서 사용자 ID 추출
req.nickname = decoded.nickname; // 검증된 토큰에서 사용자 닉네임 추출
next(); // 다음 미들웨어로 이동
});
- token: 사용자가 제공한 JWT
- JWT_SECRET: 토큰을 검증하는 데 사용되는 비밀 키
- 검증에 실패한 경우, 500 상태 코드와 '토큰 인증 실패' 메시지를 반환
- 검증에 성공하면, 사용자 ID와 닉네임을 추출하여 req 객체에 저장 -> 이후 미들웨어나 라우트 핸들러에서 req.userId와 req.nickname 사용 가능
- next(): 다음 미들웨어로 제어 넘김
33 changes: 33 additions & 0 deletions boardDB.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- CREATE DATABASE mydatabase;

-- USE mydatabase;

-- CREATE TABLE users (
-- id INT AUTO_INCREMENT PRIMARY KEY,
-- username VARCHAR(255) NOT NULL,
-- password VARCHAR(255) NOT NULL,
-- nickname VARCHAR(255) NOT NULL
-- );

-- CREATE TABLE posts (
-- id INT AUTO_INCREMENT PRIMARY KEY,
-- user_id INT,
-- title VARCHAR(255) NOT NULL,
-- content TEXT NOT NULL,
-- likes INT DEFAULT 0,
-- FOREIGN KEY (user_id) REFERENCES users(id)
-- );

-- CREATE TABLE comments (
-- id INT AUTO_INCREMENT PRIMARY KEY,
-- post_id INT,
-- user_id INT,
-- content TEXT NOT NULL,
-- FOREIGN KEY (post_id) REFERENCES posts(id),
-- FOREIGN KEY (user_id) REFERENCES users(id)
-- );

-- select * from users;
-- select * from posts;
-- select * from comments;

Binary file added dev.db
Binary file not shown.
1 change: 1 addition & 0 deletions images/create_images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Binary file added images/db_comment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/db_post.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/db_scrap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions migrations/20240723081200_init/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- CreateTable
CREATE TABLE "User" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" TEXT NOT NULL,
"password" TEXT NOT NULL,
"nickname" TEXT NOT NULL
);

-- CreateTable
CREATE TABLE "Post" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" INTEGER NOT NULL,
"title" TEXT NOT NULL,
"content" TEXT NOT NULL,
"likes" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "Post_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);

-- CreateTable
CREATE TABLE "Comment" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"postId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"content" TEXT NOT NULL,
CONSTRAINT "Comment_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);

-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Warnings:

- Added the required column `userNick` to the `Comment` table without a default value. This is not possible if the table is not empty.

*/
-- CreateTable
CREATE TABLE "Scrap" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" INTEGER NOT NULL,
"postId" INTEGER NOT NULL,
CONSTRAINT "Scrap_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Scrap_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);

-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Comment" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"postId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"content" TEXT NOT NULL,
"userNick" TEXT NOT NULL,
CONSTRAINT "Comment_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Comment" ("content", "id", "postId", "userId") SELECT "content", "id", "postId", "userId" FROM "Comment";
DROP TABLE "Comment";
ALTER TABLE "new_Comment" RENAME TO "Comment";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
3 changes: 3 additions & 0 deletions migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"
16 changes: 16 additions & 0 deletions node_modules/.bin/semver

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading