Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking โ€œSign up for GitHubโ€, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor be #13 #418

Closed
Closed
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0dc0e39
refactor: ์—๋””ํ„ฐ unsaved ๋ฑƒ์ง€ ์ œ๊ฑฐ
pkh0106 Jan 8, 2025
7aa8272
refactor: websocket ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€ setField ๋ชจ๋‘ setFields๋กœ ๋ณ€๊ฒฝ
mssak Jan 8, 2025
72d1bb7
refactor: redis ํŠธ๋žœ์ ์…˜ ๋ฐฉ์‹ ๋ณ€๊ฒฝ
mssak Jan 8, 2025
1bd2153
refactor: useCanvas ๋ฏธ์‚ฌ์šฉ์šฉ ๋ฐ˜ํ™˜๊ฐ’ ์ œ๊ฑฐ
pkh0106 Jan 8, 2025
3fe4308
refactor: ๋นˆ ๋ฌธ์ž์—ด ์‚ฌ์šฉ ์ œ๊ฑฐ๊ฑฐ
pkh0106 Jan 8, 2025
d5e2e07
refactor: ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ export ์ œ๊ฑฐ๊ฑฐ
pkh0106 Jan 8, 2025
860d156
refactor: page ๊ด€๋ จ ๋ฏธ์‚ฌ์šฉ API ์ œ๊ฑฐ๊ฑฐ
pkh0106 Jan 8, 2025
af7ca2a
refactor: Separator default ๋ณ€๊ฒฝ
pkh0106 Jan 8, 2025
10b4644
refactor: useEffect ์ค‘๋ณต ๋กœ์ง ์ œ๊ฑฐ
pkh0106 Jan 8, 2025
eff8680
refactor: TODO ์ฃผ์„ ์‚ญ์ œ
baegyeong Jan 8, 2025
bc6a568
refactor: ํ•„์š”์—†๋Š” ์ฃผ์„ ์‚ญ์ œ
baegyeong Jan 8, 2025
c9a832a
fix: ์Šค์ผ€์ฅด๋Ÿฌ ๋Œ๋•Œ redis ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ์‚ญ์ œ๋˜์ง€ ์•Š๋Š” ์˜ค๋ฅ˜ ์ˆ˜์ •์ •
mssak Jan 9, 2025
ea4f324
chore: ์ฃผ์„ ์ œ๊ฑฐ
mssak Jan 9, 2025
f475ef8
chore: ์ž„์‹œ๋กœ edge delete ๊ธฐ๋Šฅ ๋น„ํ™œ์„ฑํ™”
mssak Jan 9, 2025
40d14f0
Merge pull request #10 from boostcampwm-2024/refactor-be-#4
ezcolin2 Jan 9, 2025
5feffd9
refactor: EditorView์˜ ์Šค์ผˆ๋ ˆํ†ค UI ์ถ”๊ฐ€
baegyeong Jan 9, 2025
6b8db17
refactor: ๋„์ปค ์ตœ์ ํ™” - ์ค‘๋ณต๋˜๋Š” ๋ณผ๋ฅจ ์ฒ˜๋ฆฌ
mssak Jan 9, 2025
1b3a74e
refactor: editorView์— lazy loading ์ ์šฉ
baegyeong Jan 9, 2025
e9b183b
fix: ์Šค์ผˆ๋ ˆํ†ค UI์—์„œ prop์œผ๋กœ ์Šคํƒ€์ผ์„ ๋ฐ›๋„๋ก ์ˆ˜์ •
baegyeong Jan 9, 2025
5fa6292
refactor: ์Šค์ผˆ๋ ˆํ†ค UI๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๋„๋ก ์„ค์ •
baegyeong Jan 9, 2025
47cbcb7
fix: ์Šค์ผˆ๋ ˆํ†ค ์ปดํฌ๋„ŒํŠธ ๋‚ด์˜ padding ์ œ๊ฑฐ
pkh0106 Jan 9, 2025
a611c67
Merge pull request #11 from boostcampwm-2024/refactor-be-#4
ezcolin2 Jan 9, 2025
972f836
refactor: ์›Œํฌ์ŠคํŽ˜์ด์Šค ํŒจ๋„ ๋ถ„๋ฆฌ ๋ฐ lazy loading ์ ์šฉ
pkh0106 Jan 9, 2025
fd6eb9a
Merge pull request #6 from boostcampwm-2024/refactor-fe-#2
pkh0106 Jan 9, 2025
77ba38f
refactor: ํŽ˜์ด์ง€ ๋ชฉ๋ก ํŒจ๋„ ๋ถ„๋ฆฌ ๋ฐ lazy loading ์ ์šฉ
pkh0106 Jan 9, 2025
0d9a0b3
refactor: ์‚ฌ์šฉ์ž ์ •๋ณด ๊ด€๋ฆฌ ํŒจ๋„ lazy loading ์ ์šฉ
pkh0106 Jan 9, 2025
374837f
fix: cn์„ ์ด์šฉํ•˜์—ฌ Skeleton ์ปดํฌ๋„ŒํŠธ ๋‚ด div ํ†ตํ•ฉ
pkh0106 Jan 9, 2025
3fa0411
refactor: ๋…ธ๋“œ ์ƒ‰์ƒ ๊ด€๋ฆฌ ํŒจ๋„ lazy loading ์ ์šฉ
pkh0106 Jan 9, 2025
5446971
Merge pull request #12 from boostcampwm-2024/refactor-fe-#9
pkh0106 Jan 9, 2025
94414c0
refactor: red lock ์ œ๊ฑฐ ํ›„ redis ๋‚™๊ด€์  ๋ฝ ์ ์šฉ
ezcolin2 Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/backend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -22,4 +22,10 @@ module.exports = {
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
};
2 changes: 0 additions & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -20,7 +20,6 @@ import { WorkspaceModule } from './workspace/workspace.module';
import { RoleModule } from './role/role.module';
import { TasksModule } from './tasks/tasks.module';
import { ScheduleModule } from '@nestjs/schedule';
import { RedLockModule } from './red-lock/red-lock.module';

@Module({
imports: [
@@ -54,7 +53,6 @@ import { RedLockModule } from './red-lock/red-lock.module';
WorkspaceModule,
RoleModule,
TasksModule,
RedLockModule,
],
controllers: [AppController],
providers: [AppService],
2 changes: 0 additions & 2 deletions apps/backend/src/page/page.module.ts
Original file line number Diff line number Diff line change
@@ -6,14 +6,12 @@ import { Page } from './page.entity';
import { PageRepository } from './page.repository';
import { NodeModule } from '../node/node.module';
import { WorkspaceModule } from '../workspace/workspace.module';
import { RedLockModule } from '../red-lock/red-lock.module';

@Module({
imports: [
TypeOrmModule.forFeature([Page]),
forwardRef(() => NodeModule),
WorkspaceModule,
RedLockModule,
],
controllers: [PageController],
providers: [PageService, PageRepository],
57 changes: 18 additions & 39 deletions apps/backend/src/page/page.service.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@ import { UpdatePageDto } from './dtos/updatePage.dto';
import { UpdatePartialPageDto } from './dtos/updatePartialPage.dto';
import { PageNotFoundException } from '../exception/page.exception';
import { WorkspaceNotFoundException } from '../exception/workspace.exception';
import Redlock from 'redlock';

const RED_LOCK_TOKEN = 'RED_LOCK';

@@ -18,20 +17,13 @@ export class PageService {
private readonly pageRepository: PageRepository,
private readonly nodeRepository: NodeRepository,
private readonly workspaceRepository: WorkspaceRepository,
@Inject(RED_LOCK_TOKEN) private readonly redisLock: Redlock,
) {}
/**
* redis์— ์ €์žฅ๋œ ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ๋‹ค์Œ ๊ณผ์ •์„ ํ†ตํ•ด ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜ํ•œ๋‹ค.
*
* 1. redis์—์„œ ํ•ด๋‹น ํŽ˜์ด์ง€์˜ title๊ณผ content๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
* 2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํ•ด๋‹น ํŽ˜์ด์ง€์˜ title๊ณผ content๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค.
* 3. redis์—์„œ ํ•ด๋‹น ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
*
* ๋งŒ์•ฝ 1๋ฒˆ ๊ณผ์ •์„ ์ง„ํ–‰ํ•œ ์ƒํƒœ์—์„œ page๊ฐ€ ์‚ญ์ œ๋œ๋‹ค๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
* ์œ„ ๊ณผ์ •์„ ์ง„ํ–‰ํ•˜๋Š” ๋™์•ˆ page ์ •๋ณด ์ˆ˜์ •์„ ๋ง‰๊ธฐ ์œ„ํ•ด lock์„ ์‚ฌ์šฉํ•œ๋‹ค.
*
* ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ๊ธฐ์กด ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜์—ฌ ์ˆ˜์ •ํ•˜๋Š” ๋กœ์ง์€ RedLock ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ†ตํ•ด ๋ฝ์„ ํš๋“ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๋งŒ ์ˆ˜ํ–‰ํ•œ๋‹ค.
* ๊ธฐ์กด ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜์—ฌ ์—ฐ์‚ฐํ•˜๋Š” ๋กœ์ง์˜ ๊ฒฝ์šฐ RedLock ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์‹œ ์ ‘๊ทผ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.
*/
async createPage(dto: CreatePageDto): Promise<Page> {
const { title, content, workspaceId, x, y, emoji } = dto;
@@ -62,42 +54,29 @@ export class PageService {
}

async deletePage(id: number): Promise<void> {
// ๋ฝ์„ ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
const lock = await this.redisLock.acquire([`user:${id.toString()}`], 1000);
try {
// ํŽ˜์ด์ง€๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
const deleteResult = await this.pageRepository.delete(id);

// ๋งŒ์•ฝ ์‚ญ์ œ๋œ ํŽ˜์ด์ง€๊ฐ€ ์—†์œผ๋ฉด ํŽ˜์ด์ง€๋ฅผ ์ฐพ์ง€ ๋ชปํ•œ ๊ฒƒ
if (!deleteResult.affected) {
throw new PageNotFoundException();
}
} finally {
// ๋ฝ์„ ํ•ด์ œํ•œ๋‹ค.
await lock.release();
// ํŽ˜์ด์ง€๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
const deleteResult = await this.pageRepository.delete(id);

// ๋งŒ์•ฝ ์‚ญ์ œ๋œ ํŽ˜์ด์ง€๊ฐ€ ์—†์œผ๋ฉด ํŽ˜์ด์ง€๋ฅผ ์ฐพ์ง€ ๋ชปํ•œ ๊ฒƒ
if (!deleteResult.affected) {
throw new PageNotFoundException();
}
}

async updatePage(id: number, dto: UpdatePageDto): Promise<Page> {
// ๋ฝ์„ ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
const lock = await this.redisLock.acquire([`user:${id.toString()}`], 1000);
try {
// ๊ฐฑ์‹ ํ•  ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ๋‹ค.
// ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ๋‹ค.
const page = await this.pageRepository.findOneBy({ id });

// ํŽ˜์ด์ง€๊ฐ€ ์—†์œผ๋ฉด NotFound ์—๋Ÿฌ
if (!page) {
throw new PageNotFoundException();
}
// ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค.
const newPage = Object.assign({}, page, dto);

// ๋ณ€๊ฒฝ๋œ ํŽ˜์ด์ง€๋ฅผ ์ €์žฅ
return await this.pageRepository.save(newPage);
} finally {
await lock.release();
// ๊ฐฑ์‹ ํ•  ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ๋‹ค.
// ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ๋‹ค.
const page = await this.pageRepository.findOneBy({ id });

// ํŽ˜์ด์ง€๊ฐ€ ์—†์œผ๋ฉด NotFound ์—๋Ÿฌ
if (!page) {
throw new PageNotFoundException();
}
// ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค.
const newPage = Object.assign({}, page, dto);

// ๋ณ€๊ฒฝ๋œ ํŽ˜์ด์ง€๋ฅผ ์ €์žฅ
return await this.pageRepository.save(newPage);
}

async updateBulkPage(pages: UpdatePartialPageDto[]) {
27 changes: 0 additions & 27 deletions apps/backend/src/red-lock/red-lock.module.ts

This file was deleted.

5 changes: 2 additions & 3 deletions apps/backend/src/redis/redis.module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Module, forwardRef } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisService } from './redis.service';
import Redis from 'ioredis';
import { RedLockModule } from '../red-lock/red-lock.module';

// ์˜์กด์„ฑ ์ฃผ์ž…ํ•  ๋•Œ redis client๋ฅผ ์‹๋ณ„ํ•  ํ† ํฐ
const REDIS_CLIENT_TOKEN = 'REDIS_CLIENT';

@Module({
imports: [ConfigModule, forwardRef(() => RedLockModule)], // ConfigModule ์ถ”๊ฐ€
imports: [ConfigModule], // ConfigModule ์ถ”๊ฐ€
providers: [
RedisService,
{
32 changes: 6 additions & 26 deletions apps/backend/src/redis/redis.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import { Inject } from '@nestjs/common';
import Redis from 'ioredis';
import Redlock from 'redlock';
const REDIS_CLIENT_TOKEN = 'REDIS_CLIENT';
const RED_LOCK_TOKEN = 'RED_LOCK';

@@ -18,16 +17,15 @@ export type RedisNode = {
};

export type RedisEdge = {
fromNode: number;
toNode: number;
type: 'add' | 'delete';
fromNode?: number;
toNode?: number;
type?: 'add' | 'delete';
};

@Injectable()
export class RedisService {
constructor(
@Inject(REDIS_CLIENT_TOKEN) private readonly redisClient: Redis,
@Inject(RED_LOCK_TOKEN) private readonly redisLock: Redlock,
) {}

async getAllKeys(pattern) {
@@ -46,32 +44,14 @@ export class RedisService {
}

async set(key: string, value: object) {
// ๋ฝ์„ ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
const lock = await this.redisLock.acquire([`user:${key}`], 1000);
try {
await this.redisClient.hset(key, Object.entries(value));
} finally {
lock.release();
}
await this.redisClient.hset(key, Object.entries(value));
}

async setField(key: string, field: string, value: string) {
// ๋ฝ์„ ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
const lock = await this.redisLock.acquire([`user:${key}`], 1000);
try {
return await this.redisClient.hset(key, field, value);
} finally {
lock.release();
}
return await this.redisClient.hset(key, field, value);
}

async delete(key: string) {
// ๋ฝ์„ ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
const lock = await this.redisLock.acquire([`user:${key}`], 1000);
try {
return await this.redisClient.del(key);
} finally {
lock.release();
}
return await this.redisClient.del(key);
}
}
Loading