728x90
Controller
JAVA 컨트롤러
@RestController
@RequestMapping("/api/todos")
public class TodoController {
private final TodoService todoService;
public TodoController(TodoService todoService) {
this.todoService = todoService;
}
@GetMapping
public ResponseEntity<TodoListResponse> getAll() {
List<Todo> todos = todoService.findAll();
return ResponseEntity.ok(TodoListResponse.of(todos));
}
@GetMapping("/{id}")
public ResponseEntity<TodoResponse> get(@PathVariable Long id) {
Todo todo = todoService.findById(id);
return ResponseEntity.ok(TodoResponse.of(todo));
}
@PostMapping
public ResponseEntity<TodoResponse> create(@RequestBody TodoRequest request) {
Todo todo = todoService.create(request);
return ResponseEntity.ok(TodoResponse.of(todo));
}
@PutMapping("/{id}")
public ResponseEntity<TodoResponse> update(@PathVariable Long id,
@RequestBody TodoRequest request) {
Todo todo = todoService.update(id, request);
return ResponseEntity.ok(TodoResponse.of(todo));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
todoService.delete(id);
return ResponseEntity.noContent().build();
}
}
Kotlin 컨트롤러
@RestController
@RequestMapping("/api/todos")
class TodoController(
private val todoService: TodoService,
) {
@GetMapping
fun getAll() = ok(TodoListResponse.of(todoService.findAll()))
@GetMapping("/{id}")
fun get(@PathVariable id: Long) =
ok(TodoResponse.of(todoService.findById(id)))
@PostMapping
fun create(@RequestBody request: TodoRequest) =
ok(TodoResponse.of(todoService.create(request)))
@PutMapping("/{id}")
fun update(@PathVariable id: Long, @RequestBody request: TodoRequest) =
ok(TodoResponse.of(todoService.update(id, request)))
@DeleteMapping("/{id}")
fun delete(@PathVariable id: Long): ResponseEntity<Unit> {
todoService.delete(id)
return noContent().build()
}
}
- 자바 코드처럼 블록을 사용하지 않고 바로 리턴하도록 작성할 수 있다.
- 생성자에 빈으로 주입받을 서비스를 쓴다.
- delete 같은 경우 Java에서는 Void를 반환했지만, Kotlin에서는 Unit을 반환하면 된다.
Dto
TodoListReponse
JavaCode
@Data
public class TodoListResponse {
private final List<TodoResponse> items;
private TodoListResponse(List<TodoResponse> items) {
this.items = items;
}
public int size() {
return items.size();
}
public TodoResponse get(int index) {
return items.get(index);
}
public static TodoListResponse of(List<Todo> todoList) {
List<TodoResponse> todoListResponse = todoList.stream()
.map(TodoResponse::of)
.collect(Collectors.toList());
return new TodoListResponse(todoListResponse);
}
}
KotlinCode
data class TodoListResponse(
val items: List<TodoResponse>,
) {
val size: Int
@JsonIgnore //Jackson Json에서 size를 프로퍼티로 내려주기 떄문에 해당 애노테이션을 추가해주어야 한다.
get() = items.size //유틸리티성 프로퍼티를 만들어 함수를 만들지 않고 size를 반환한다.
fun get(index: Int) = items[index]
companion object {
fun of(todoList: List<Todo>) =
//TodoListResponse(todoList.map { TodoResponse.of(it) })
TodoListResponse(todoList.map(TodoResponse::of))
}
}
- size 같은경우 프로퍼티로 만들어 커스텀 getter를 통해 원하는 값을 반환하도록 하는 것이 좋다.
- Jackson의 Json에서 프로퍼티로 내려주기 때문에 @JsonIgnore 애노테이션을 통해 제외 처리를 해야 한다.
- of 같은 경우 static 함수로 companion으로 동반 객체를 만들어 내부에 함수로 사용하고, 스트림 같은 경우 람다 레퍼런스와 인라인 함수(map)를 통해 JAVA보다 간결하게 작성할 수 있다.
TodoResponse
JavaCode
@Data
@Builder
public class TodoResponse {
private Long id;
private String title;
private String description;
private Boolean done;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public static TodoResponse of(Todo todo) {
Assert.notNull(todo, "Todo is null");
return TodoResponse.builder()
.id(todo.getId())
.title(todo.getTitle())
.description(todo.getDescription())
.done(todo.getDone())
.createdAt(todo.getCreatedAt())
.updatedAt(todo.getUpdatedAt())
.build();
}
}
KotlinCode
data class TodoResponse(
val id: Long,
val title: String,
val description: String,
val done: Boolean,
val createdAt: LocalDateTime,
val updatedAt: LocalDateTime
) {
companion object {
fun of(todo: Todo?): TodoResponse {
checkNotNull(todo) { "Todo is null" }
return TodoResponse(
id = todo.id,
title = todo.title,
description = todo.description,
done = todo.done,
createdAt = todo.createdAt,
updatedAt = todo.updatedAt,
)
}
}
}
- Null이 올 수도 있기 때문에 ?연산자를 통해 Nullable임을 컴파일러에 알려준다.
- checkNotNull 함수를 통해 해당 데이터가 널 인지 확인한다.
TodoRequest
JavaCode
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TodoRequest {
private String title;
private String description;
private Boolean done = false;
}
KotlinCode
data class TodoRequest(
val title: String,
val description: String,
val done: Boolean = false,
)728x90
'실무 프로젝트로 배우는 Kotlin & Spring > 자바 프로젝트(ToDo프로젝트) 코틀린으로 리팩토링 하기' 카테고리의 다른 글
| 테스트 코드 리펙토링 (0) | 2022.11.05 |
|---|---|
| 도메인(Domain, Repository) 리펙토링 (0) | 2022.11.05 |
| Service 리펙토링 (0) | 2022.11.05 |
| JAVA 프로젝트에 코틀린 설정 적용 (0) | 2022.11.05 |