From 58c0b9510d5e71e1a5a1a29ef955e8e204f96557 Mon Sep 17 00:00:00 2001 From: ttipo Date: Sat, 20 Jun 2026 21:39:48 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=20=EA=B3=B5=EA=B0=9C=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84(visibility)=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 불필요한 프로젝트 공개 범위 데이터를 백엔드·프론트에서 일괄 제거(저장소 Repo 의 visibility 는 Gitea 연동용이라 유지). 백엔드: - Project 엔티티 visibility 컬럼·ProjectVisibility 타입 제거(dev synchronize 가 컬럼 DROP) - create/update DTO, ProjectResponse, create/update/ensureUnassigned/toResponse 에서 제거 - ai.service 프로젝트 컨텍스트 문자열에서 공개범위 표기 제거 - activity 타입 project.visibility_changed 제거 프론트: - types/project·project.store·mock Project 에서 visibility 제거 - ProjectCreatePage·ProjectSettingsPage 공개 범위 입력 폼+CSS 제거 - ProjectListPage 공개여부 세그먼트 필터+배지 제거, ProjectHeader 배지 제거 - activity 타입/스토어 project.visibility_changed 케이스 제거 런타임 검증: DB projects.visibility 컬럼 DROP, 생성/목록 응답에 visibility 없음, CRUD 정상. 백엔드 build/lint 0·14 tests, 프론트 type-check/lint/build 0. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../activity/entities/activity.entity.ts | 1 - backend/src/modules/ai/ai.service.ts | 5 +- .../modules/project/dto/create-project.dto.ts | 18 +-- .../modules/project/dto/update-project.dto.ts | 12 +- .../project/entities/project.entity.ts | 7 - .../src/modules/project/project.service.ts | 7 +- frontend/src/components/ProjectHeader.vue | 34 ---- frontend/src/mock/relay.mock.ts | 1 - .../src/pages/relay/ProjectCreatePage.vue | 100 +----------- frontend/src/pages/relay/ProjectListPage.vue | 72 +-------- .../src/pages/relay/ProjectSettingsPage.vue | 148 +----------------- frontend/src/stores/activity.store.ts | 7 - frontend/src/stores/project.store.ts | 1 - frontend/src/types/activity.ts | 1 - frontend/src/types/project.ts | 4 - 15 files changed, 10 insertions(+), 408 deletions(-) diff --git a/backend/src/modules/activity/entities/activity.entity.ts b/backend/src/modules/activity/entities/activity.entity.ts index 3538156..f8d8da0 100644 --- a/backend/src/modules/activity/entities/activity.entity.ts +++ b/backend/src/modules/activity/entities/activity.entity.ts @@ -16,7 +16,6 @@ export type ActivityType = // 프로젝트(설정) | 'project.created' | 'project.renamed' - | 'project.visibility_changed' // 저장소 연동 | 'repo.linked' | 'repo.unlinked' diff --git a/backend/src/modules/ai/ai.service.ts b/backend/src/modules/ai/ai.service.ts index 7052f40..f7114f0 100644 --- a/backend/src/modules/ai/ai.service.ts +++ b/backend/src/modules/ai/ai.service.ts @@ -395,10 +395,7 @@ export class AiService { lines.push('- (없음)'); } else { for (const p of projects.items) { - const vis = p.visibility === 'private' ? '비공개' : '공개'; - lines.push( - `- ${p.name} — ${vis}, 업무 ${p.doneCount}/${p.totalCount}건`, - ); + lines.push(`- ${p.name} — 업무 ${p.doneCount}/${p.totalCount}건`); } if (projects.total > projects.items.length) { lines.push(`- … 외 ${projects.total - projects.items.length}개`); diff --git a/backend/src/modules/project/dto/create-project.dto.ts b/backend/src/modules/project/dto/create-project.dto.ts index 334f3a5..3c47922 100644 --- a/backend/src/modules/project/dto/create-project.dto.ts +++ b/backend/src/modules/project/dto/create-project.dto.ts @@ -1,12 +1,5 @@ -import { - IsIn, - IsNotEmpty, - IsOptional, - IsString, - MaxLength, -} from 'class-validator'; +import { IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import type { ProjectVisibility } from '../entities/project.entity'; // 프로젝트 생성 DTO export class CreateProjectDto { @@ -24,13 +17,4 @@ export class CreateProjectDto { @IsString() @MaxLength(300) description?: string; - - @ApiProperty({ - description: '공개 범위', - enum: ['private', 'public'], - required: false, - }) - @IsOptional() - @IsIn(['private', 'public'], { message: '공개 범위를 선택해 주세요.' }) - visibility?: ProjectVisibility; } diff --git a/backend/src/modules/project/dto/update-project.dto.ts b/backend/src/modules/project/dto/update-project.dto.ts index 77622dc..4b10a40 100644 --- a/backend/src/modules/project/dto/update-project.dto.ts +++ b/backend/src/modules/project/dto/update-project.dto.ts @@ -1,6 +1,5 @@ -import { IsIn, IsOptional, IsString, MaxLength } from 'class-validator'; +import { IsOptional, IsString, MaxLength } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import type { ProjectVisibility } from '../entities/project.entity'; // 프로젝트 수정 DTO — 제공된 필드만 갱신 export class UpdateProjectDto { @@ -15,13 +14,4 @@ export class UpdateProjectDto { @IsString() @MaxLength(300) description?: string; - - @ApiProperty({ - description: '공개 범위', - enum: ['private', 'public'], - required: false, - }) - @IsOptional() - @IsIn(['private', 'public'], { message: '공개 범위를 선택해 주세요.' }) - visibility?: ProjectVisibility; } diff --git a/backend/src/modules/project/entities/project.entity.ts b/backend/src/modules/project/entities/project.entity.ts index df4709f..ff13b58 100644 --- a/backend/src/modules/project/entities/project.entity.ts +++ b/backend/src/modules/project/entities/project.entity.ts @@ -9,9 +9,6 @@ import { } from 'typeorm'; import { ProjectMember } from './project-member.entity'; -// 프로젝트 공개 범위 -export type ProjectVisibility = 'private' | 'public'; - // 프로젝트 엔티티 — 작업의 기본 단위(우선). 저장소(Repo)는 프로젝트에 0~N개 연동된다. @Entity('projects') export class Project { @@ -27,10 +24,6 @@ export class Project { @Column({ type: 'varchar', nullable: true }) description!: string | null; - // 공개 범위 - @Column({ type: 'varchar', default: 'private' }) - visibility!: ProjectVisibility; - // 시스템 예약 프로젝트 여부 — "미분류"(Gitea import 기본 버킷)는 true. 삭제/이름변경 보호. @Column({ name: 'is_system', default: false }) isSystem!: boolean; diff --git a/backend/src/modules/project/project.service.ts b/backend/src/modules/project/project.service.ts index 46c8ed5..69189bb 100644 --- a/backend/src/modules/project/project.service.ts +++ b/backend/src/modules/project/project.service.ts @@ -13,7 +13,7 @@ import { resolvePage, type PaginatedResult, } from '../../common/pagination/pagination'; -import { Project, type ProjectVisibility } from './entities/project.entity'; +import { Project } from './entities/project.entity'; import { ProjectMember } from './entities/project-member.entity'; import { Repo } from '../repo/entities/repo.entity'; import { Task } from '../task/entities/task.entity'; @@ -28,7 +28,6 @@ export interface ProjectResponse { id: string; name: string; description: string | null; - visibility: ProjectVisibility; isSystem: boolean; members: PublicUser[]; memberCount: number; @@ -120,7 +119,6 @@ export class ProjectService implements OnApplicationBootstrap { this.projectRepo.create({ name: dto.name, description: dto.description ?? null, - visibility: dto.visibility ?? 'private', isSystem: false, }), ); @@ -155,7 +153,6 @@ export class ProjectService implements OnApplicationBootstrap { } if (dto.name !== undefined) project.name = dto.name; if (dto.description !== undefined) project.description = dto.description; - if (dto.visibility !== undefined) project.visibility = dto.visibility; await this.projectRepo.save(project); return this.findOne(project.id, userId); } @@ -187,7 +184,6 @@ export class ProjectService implements OnApplicationBootstrap { this.projectRepo.create({ name: UNASSIGNED_PROJECT_NAME, description: 'Gitea 에서 가져온, 아직 프로젝트에 배정되지 않은 저장소', - visibility: 'private', isSystem: true, }), ); @@ -275,7 +271,6 @@ export class ProjectService implements OnApplicationBootstrap { id: project.id, name: project.name, description: project.description, - visibility: project.visibility, isSystem: project.isSystem, members: members .filter((m) => m.user) diff --git a/frontend/src/components/ProjectHeader.vue b/frontend/src/components/ProjectHeader.vue index 2132736..f5b03e5 100644 --- a/frontend/src/components/ProjectHeader.vue +++ b/frontend/src/components/ProjectHeader.vue @@ -37,40 +37,6 @@ const extra = computed(() => props.moreCount ?? props.repo.moreCount)
{{ repo.name }} - - - - - - - - {{ repo.visibility === 'private' ? '비공개' : '공개' }} -
{{ repo.desc }} diff --git a/frontend/src/mock/relay.mock.ts b/frontend/src/mock/relay.mock.ts index 0f14f50..aa03bc2 100644 --- a/frontend/src/mock/relay.mock.ts +++ b/frontend/src/mock/relay.mock.ts @@ -77,7 +77,6 @@ export interface Project { id: string name: string desc: string - visibility: Visibility /** "미분류" 시스템 프로젝트 */ isSystem: boolean members: User[] diff --git a/frontend/src/pages/relay/ProjectCreatePage.vue b/frontend/src/pages/relay/ProjectCreatePage.vue index 05f2c09..bc9d15a 100644 --- a/frontend/src/pages/relay/ProjectCreatePage.vue +++ b/frontend/src/pages/relay/ProjectCreatePage.vue @@ -1,17 +1,15 @@ @@ -69,26 +61,6 @@ const filteredRepos = computed(() => placeholder="프로젝트 검색…" >
-
- - - -
v-if="repo.isSystem" class="repo-slug" >시스템 - - - - - - - - - - {{ repo.visibility === 'private' ? '비공개' : '공개' }} -
{{ repo.desc }} diff --git a/frontend/src/pages/relay/ProjectSettingsPage.vue b/frontend/src/pages/relay/ProjectSettingsPage.vue index 5b1b301..45ea477 100644 --- a/frontend/src/pages/relay/ProjectSettingsPage.vue +++ b/frontend/src/pages/relay/ProjectSettingsPage.vue @@ -6,7 +6,7 @@ import AppShell from '@/layouts/AppShell.vue' import ProjectHeader from '@/components/ProjectHeader.vue' import ProjectTabs from '@/components/ProjectTabs.vue' import { useProjectStore } from '@/stores/project.store' -import { type Project, type Visibility } from '@/mock/relay.mock' +import { type Project } from '@/mock/relay.mock' const route = useRoute() const router = useRouter() @@ -26,7 +26,6 @@ const memberCount = computed(() => // 폼 상태(초기값은 프로젝트 데이터) const displayTitle = ref('') const description = ref('') -const visibility = ref('private') const saving = ref(false) // 프로젝트 로드 + 폼 초기화 @@ -45,7 +44,6 @@ async function loadRepo() { } displayTitle.value = repo.value.name description.value = repo.value.desc - visibility.value = repo.value.visibility } watch(projectId, loadRepo, { immediate: true }) @@ -57,7 +55,6 @@ async function save() { repo.value = await projectStore.update(projectId.value, { name: displayTitle.value.trim(), description: description.value.trim(), - visibility: visibility.value, }) window.alert('변경 사항을 저장했습니다.') } catch { @@ -170,67 +167,6 @@ async function removeRepo() { />
-
-
- 공개 범위 -
-
- 프로젝트와 그 안의 업무를 누가 볼 수 있는지 결정합니다. -
-
- - -
-
-