Skip to content

Commit 4f118c5

Browse files
authored
refactor: Task 도메인 수정 (#76)
1 parent 3c6275b commit 4f118c5

File tree

6 files changed

+79
-70
lines changed

6 files changed

+79
-70
lines changed

back/src/main/java/com/back/domain/roadmap/task/controller/TaskController.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.back.global.rq.Rq;
1010
import com.back.global.rsData.RsData;
1111
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
1213
import jakarta.validation.Valid;
1314
import lombok.RequiredArgsConstructor;
1415
import org.springframework.data.domain.Page;
@@ -23,6 +24,7 @@
2324
@RestController
2425
@RequestMapping("/tasks")
2526
@RequiredArgsConstructor
27+
@Tag(name = "TaskController", description = "Task 컨트롤러")
2628
public class TaskController {
2729
private final TaskService taskService;
2830
private final Rq rq;

back/src/main/java/com/back/domain/roadmap/task/entity/Task.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,31 @@
44
import jakarta.persistence.*;
55
import lombok.Getter;
66
import lombok.NoArgsConstructor;
7-
import lombok.Setter;
87

8+
import java.util.ArrayList;
99
import java.util.List;
1010

1111
@Entity
1212
@Table(name = "task")
13-
@Getter @Setter
13+
@Getter
1414
@NoArgsConstructor
1515
public class Task extends BaseEntity {
1616
@Column(name = "name", nullable = false, unique = true)
1717
private String name;
1818

1919
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL)
20-
private List<TaskAlias> aliases;
20+
private List<TaskAlias> aliases = new ArrayList<>();
2121

2222
public Task(String name) {
2323
this.name = name;
24+
this.aliases = new ArrayList<>();
2425
}
2526

2627
public void addAlias(TaskAlias alias) {
28+
if (aliases == null) {
29+
aliases = new ArrayList<>();
30+
}
2731
aliases.add(alias);
28-
alias.setTask(this);
32+
alias.linkToTask(this);
2933
}
3034
}

back/src/main/java/com/back/domain/roadmap/task/entity/TaskAlias.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
import jakarta.persistence.*;
55
import lombok.Getter;
66
import lombok.NoArgsConstructor;
7-
import lombok.Setter;
87

98
@Entity
109
@Table(name = "task_alias")
11-
@Getter @Setter
10+
@Getter
1211
@NoArgsConstructor
1312
public class TaskAlias extends BaseEntity {
1413
@Column(name = "name", nullable = false, unique = true)
@@ -22,4 +21,12 @@ public TaskAlias(String name) {
2221
this.name = name;
2322
this.task = null; // 기본적으로 연결된 Task가 없음 (pending 상태)
2423
}
24+
25+
public void linkToTask(Task task) {
26+
this.task = task;
27+
}
28+
29+
public boolean isPending() {
30+
return this.task == null;
31+
}
2532
}

back/src/main/java/com/back/domain/roadmap/task/service/TaskService.java

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public Task create(String name) {
3434
@Transactional
3535
public TaskAlias createAlias(Task task, String aliasName) {
3636
TaskAlias alias = new TaskAlias(aliasName);
37-
alias.setTask(task);
37+
alias.linkToTask(task);
3838
return taskAliasRepository.save(alias);
3939
}
4040

@@ -46,24 +46,10 @@ public List<Task> searchByKeyword(String keyword){
4646

4747
@Transactional
4848
public TaskAlias createPendingAlias(String taskName){
49-
// 1. 먼저 Alias가 존재하는지 확인 (Pending 포함)
50-
Optional<TaskAlias> existingAliasOpt = taskAliasRepository.findByNameIgnoreCase(taskName);
51-
if (existingAliasOpt.isPresent()) {
52-
TaskAlias existingAlias = existingAliasOpt.get();
53-
if (existingAlias.getTask() != null) {
54-
throw new ServiceException("400", "이미 등록된 task의 별칭입니다.");
55-
} else {
56-
throw new ServiceException("400", "이미 제안된 task입니다.");
57-
}
58-
}
49+
// Task나 TaskAlias에 이미 존재하는 이름인지 검증
50+
validateNewPendingAliasName(taskName);
5951

60-
// 2. Alias가 없다면, Task 테이블에 직접 존재하는지 확인
61-
Optional<Task> existingTaskOpt = taskRepository.findByNameIgnoreCase(taskName);
62-
if(existingTaskOpt.isPresent()){
63-
throw new ServiceException("400", "이미 등록된 task입니다.");
64-
}
65-
66-
// 3. 모두 해당 없으면 새로운 pending alias 생성
52+
// 모든 검증 통과 시 새로운 pending alias 생성
6753
TaskAlias pendingAlias = new TaskAlias(taskName);
6854
return taskAliasRepository.save(pendingAlias);
6955
}
@@ -80,41 +66,26 @@ public Page<TaskAliasDto> getPendingTaskAliases(Pageable pageable) {
8066
// Pending alias를 기존 Task와 연결
8167
@Transactional
8268
public TaskAlias linkPendingAlias(Long aliasId, Long taskId) {
83-
TaskAlias pendingAlias = taskAliasRepository.findById(aliasId)
84-
.orElseThrow(() -> new ServiceException("404", "해당 별칭이 존재하지 않습니다."));
69+
TaskAlias pendingAlias = findPendingAliasById(aliasId);
70+
Task task = findTaskById(taskId);
8571

86-
if (pendingAlias.getTask() != null) {
87-
throw new ServiceException("400", "이미 연결된 별칭입니다.");
88-
}
89-
90-
Task task = taskRepository.findById(taskId)
91-
.orElseThrow(() -> new ServiceException("404", "해당 Task가 존재하지 않습니다."));
92-
93-
pendingAlias.setTask(task);
72+
pendingAlias.linkToTask(task);
9473
return taskAliasRepository.save(pendingAlias);
9574
}
9675

9776
// Pending alias를 새로운 Task로 생성
9877
@Transactional
9978
public Task createTaskFromPending(Long aliasId) {
100-
TaskAlias pendingAlias = taskAliasRepository.findById(aliasId)
101-
.orElseThrow(() -> new ServiceException("404", "해당 별칭이 존재하지 않습니다."));
102-
103-
if (pendingAlias.getTask() != null) {
104-
throw new ServiceException("400", "이미 연결된 별칭입니다.");
105-
}
79+
TaskAlias pendingAlias = findPendingAliasById(aliasId);
10680

10781
// 동일한 이름의 Task가 이미 존재하는지 확인
108-
Optional<Task> existingTask = taskRepository.findByNameIgnoreCase(pendingAlias.getName());
109-
if (existingTask.isPresent()) {
110-
throw new ServiceException("400", "이미 존재하는 Task 이름입니다.");
111-
}
82+
validateTaskNameForCreation(pendingAlias.getName());
11283

11384
// 새 Task 생성
11485
Task newTask = create(pendingAlias.getName());
11586

11687
// pending alias를 새 Task와 연결
117-
pendingAlias.setTask(newTask);
88+
pendingAlias.linkToTask(newTask);
11889
taskAliasRepository.save(pendingAlias);
11990

12091
return newTask;
@@ -123,13 +94,52 @@ public Task createTaskFromPending(Long aliasId) {
12394
// Pending alias 삭제
12495
@Transactional
12596
public void deletePendingAlias(Long aliasId) {
126-
TaskAlias pendingAlias = taskAliasRepository.findById(aliasId)
97+
TaskAlias pendingAlias = findPendingAliasById(aliasId);
98+
taskAliasRepository.delete(pendingAlias);
99+
}
100+
101+
// === 검증 로직 메서드들 ===
102+
103+
// TaskAlias를 ID로 조회하고 Pending 상태인지 검증
104+
private TaskAlias findPendingAliasById(Long aliasId) {
105+
TaskAlias alias = taskAliasRepository.findById(aliasId)
127106
.orElseThrow(() -> new ServiceException("404", "해당 별칭이 존재하지 않습니다."));
128107

129-
if (pendingAlias.getTask() != null) {
130-
throw new ServiceException("400", "연결된 별칭은 삭제할 수 없습니다.");
108+
if (!alias.isPending()) {
109+
throw new ServiceException("400", "이미 연결된 별칭입니다.");
131110
}
132111

133-
taskAliasRepository.delete(pendingAlias);
112+
return alias;
113+
}
114+
115+
// Task를 ID로 조회
116+
private Task findTaskById(Long taskId) {
117+
return taskRepository.findById(taskId)
118+
.orElseThrow(() -> new ServiceException("404", "해당 Task가 존재하지 않습니다."));
119+
}
120+
121+
// Task와 TaskAlias 모두 중복 검증 (새로운 pending alias 생성 시 사용)
122+
private void validateNewPendingAliasName(String taskName) {
123+
// 1. TaskAlias 테이블에서 중복 확인 (Pending 포함)
124+
Optional<TaskAlias> existingAliasOpt = taskAliasRepository.findByNameIgnoreCase(taskName);
125+
if (existingAliasOpt.isPresent()) {
126+
TaskAlias existingAlias = existingAliasOpt.get();
127+
if (!existingAlias.isPending()) {
128+
throw new ServiceException("400", "이미 등록된 Task의 별칭입니다.");
129+
} else {
130+
throw new ServiceException("400", "이미 제안된 Task명입니다.");
131+
}
132+
}
133+
134+
// 2. Task 테이블에서 중복 검증
135+
validateTaskNameForCreation(taskName);
136+
}
137+
138+
// 동일한 이름의 Task가 이미 존재하는지 확인 (pending alias를 새 Task로 등록할 때 사용)
139+
private void validateTaskNameForCreation(String taskName) {
140+
Optional<Task> existingTaskOpt = taskRepository.findByNameIgnoreCase(taskName);
141+
if (existingTaskOpt.isPresent()) {
142+
throw new ServiceException("400", "이미 등록된 Task명입니다.");
143+
}
134144
}
135145
}

back/src/test/java/com/back/domain/roadmap/task/controller/TaskControllerTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ void t12() throws Exception {
303303
.andExpect(handler().methodName("createPendingAlias"))
304304
.andExpect(status().isBadRequest())
305305
.andExpect(jsonPath("$.resultCode").value("400"))
306-
.andExpect(jsonPath("$.msg").value("이미 등록된 task입니다."));
306+
.andExpect(jsonPath("$.msg").value("이미 등록된 Task명입니다."));
307307
}
308308

309309
@Test
@@ -328,7 +328,7 @@ void t13() throws Exception {
328328
.andExpect(handler().methodName("createPendingAlias"))
329329
.andExpect(status().isBadRequest())
330330
.andExpect(jsonPath("$.resultCode").value("400"))
331-
.andExpect(jsonPath("$.msg").value("이미 등록된 task의 별칭입니다."));
331+
.andExpect(jsonPath("$.msg").value("이미 등록된 Task의 별칭입니다."));
332332
}
333333

334334
@Test
@@ -356,7 +356,7 @@ void t14() throws Exception {
356356
.andExpect(handler().methodName("createPendingAlias"))
357357
.andExpect(status().isBadRequest())
358358
.andExpect(jsonPath("$.resultCode").value("400"))
359-
.andExpect(jsonPath("$.msg").value("이미 제안된 task입니다."));
359+
.andExpect(jsonPath("$.msg").value("이미 제안된 Task명입니다."));
360360
}
361361

362362
@Test

back/src/test/java/com/back/domain/roadmap/task/service/TaskServiceTest.java

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void t7() {
124124
// When & Then
125125
assertThatThrownBy(() -> taskService.createPendingAlias(existingTaskName))
126126
.isInstanceOf(ServiceException.class)
127-
.hasMessage("400 : 이미 등록된 task입니다.");
127+
.hasMessage("400 : 이미 등록된 Task명입니다.");
128128
}
129129

130130
@Test
@@ -136,7 +136,7 @@ void t8() {
136136
// When & Then
137137
assertThatThrownBy(() -> taskService.createPendingAlias(existingAliasName))
138138
.isInstanceOf(ServiceException.class)
139-
.hasMessage("400 : 이미 등록된 task의 별칭입니다.");
139+
.hasMessage("400 : 이미 등록된 Task의 별칭입니다.");
140140
}
141141

142142
@Test
@@ -149,7 +149,7 @@ void t9() {
149149
// When & Then
150150
assertThatThrownBy(() -> taskService.createPendingAlias(aliasName))
151151
.isInstanceOf(ServiceException.class)
152-
.hasMessage("400 : 이미 제안된 task입니다.");
152+
.hasMessage("400 : 이미 제안된 Task명입니다.");
153153
}
154154

155155
@Test
@@ -274,20 +274,6 @@ void t17() {
274274
.hasMessage("400 : 이미 연결된 별칭입니다.");
275275
}
276276

277-
@Test
278-
@DisplayName("Pending Alias를 새로운 Task로 생성 실패 - 동일한 이름의 Task 이미 존재")
279-
void t18() {
280-
// Given
281-
TaskAlias pendingAlias = taskService.createPendingAlias("중복 task"); // 먼저 pending alias 생성
282-
taskService.create("중복 task"); // 그 다음에 동일한 이름의 Task 생성
283-
284-
285-
// When & Then
286-
assertThatThrownBy(() -> taskService.createTaskFromPending(pendingAlias.getId()))
287-
.isInstanceOf(ServiceException.class)
288-
.hasMessage("400 : 이미 존재하는 Task 이름입니다.");
289-
}
290-
291277
@Test
292278
@DisplayName("Pending Alias 삭제 - 성공")
293279
void t19() {
@@ -322,7 +308,7 @@ void t21() {
322308
// When & Then
323309
assertThatThrownBy(() -> taskService.deletePendingAlias(pendingAlias.getId()))
324310
.isInstanceOf(ServiceException.class)
325-
.hasMessage("400 : 연결된 별칭은 삭제할 수 없습니다.");
311+
.hasMessage("400 : 이미 연결된 별칭입니다.");
326312
}
327313

328314
@Test

0 commit comments

Comments
 (0)