1. Kotlin : runCatching
runCatching 은 try-catch 를 대체할 수 있는 코틀린의 문법이다.
결론부터 말하면, try-catch 문은 실패시의 핸들링을 처리할 수 있었다면, runCatching 은 성공시, 실패시 둘 다 처리할 수 있다.
@InlineOnly
@SinceKotlin("1.3")
public inline fun <T, R> T.runCatching(block: T.() -> R): Result<R> {
return try {
Result.success(block())
} catch (e: Throwable) {
Result.failure(e)
}
}
보다시피, 리턴 타입은 Result 라는 객체이며,
전달받은 내용을 실행해서,
성공한다면 Result.success() 를 통해 성공했다는 내용을 담은 Result 객체,
실패한다면 Result.failure() 를 통해 에러 내용을 담은 Result 객체를 반환한다.
기본 문법
- runCatching { } : 중괄호 안에 try 하고자 하는 구문을 작성
- onSuccess { } : 위 runCatch 구문이 성공시 매핑할 구문을 작성. it 은 위 구문의 결과.
- onFailure { } : 위 runCatch 구문이 실패시 매핑할 구문을 작성. it 은 위 구문에서 던진 Throwable 객체.
- also { } : 기존 try-catch-finally 에서 finally 에서 작성하던 구문을 작성할 수 있음.
복잡한 상황
- map { } : 성공한 값에 대해 한번더 가공이 가능. 여기서 예외가 발생하면 runCatching 구문 밖으로 예외를 던짐.
- mapCatching { } : 성공한 값에 대해 한번더 가공이 가능. 여기서 예외가 발생하면 runCatching 구문 밖으로 예외를 던지지 않고, 그 예외를 담은 Result 객체 반환. 이후 onFailure 등으로 다시 잡아서 처리가능.
- recover { } : 실패한 값에 대해 한번더 핸들링이 가능. 여기서 예외가 발생하면 runCatching 구문 밖으로 예외를 던짐.
- recoverCatching { } :실패한 값에 대해 한번더 핸들링이 가능. 여기서 예외가 발생하면 runCatching 구문 밖으로 예외를 던지지 않고, 그 예외를 담은 Result 객체 반환. 이후 onFailure 등으로 다시 잡아서 처리가능.
runCatching 구문의 return 값이 필요할때
- getOrNull() : 위에서 반환된 Result 객체가 성공객체 일 때 값 반환. 실패면 null
- getOrDefault(~) : 위에서 반환된 Result 객체가 성공객체 일 때 값 반환. 실패면 뒤에 정의한 값 반환.
- getOrThrow() : 위에서 반환된 Result 객체가 성공객체 일 때 값 반환. 실패면 Result 객체의 예외 throw.
- getOrElse { } : 위에서 반환된 Result 객체가 성공객체 일 때 값 반환. 실패면 뒤에 정의한 구문 실행.
Result 객체는 함수의 반환형으로 쓰일 수 없다.
https://rannte.tistory.com/entry/kotlinruncatching
2. DTO/Entity 작성 팁
Entity
- DB 에 걸려있는 제약조건과 같이 맞춰준다. (nullable, unique ... )
- 객체 생성 제약
- @NoArgsConstructor(access = AccessLevel.PROTECTED) 과 같은 롬복 에너테이션으로 객체의 직접 생성을 외부에서 하지 못하게 제약할 수 있다.
- 직접 생성을 하지 못하고, 빌더패턴이나 정적 팩터리 메서드 패턴을 사용해서 생성할 수 있게 할 수 있다.
- 빌더패턴과 정적 팩터리 메서드 패턴의 장점은 이펙티브 자바 1, 2장에 자세히 나와 있다.
Dto
- RequestBody / ResponseBody 를 Entity 객체로 바로 받지 말고, DTO 로 받자.
- 해당 요청에 필요한 정보만 취급하는 것이 안전하다. 예를 들어 User 객체의 이름을 바꾸는 API 에는 id 값과 비밀번호, 바꿀 이름만 필요할 것이다.
- 응답도 마찬가지.
- setter 를 이용한 변경보단 dto 를 이용한 변경.
- JPA 를 사용하면 setter 로 객체의 값을 바꾸면 값이 변경된다.
- 모든 setter 가 있는 필드들이 변경가능한 상태가 된다. -> 추적할 포인트가 많아진다.
- 기획의도상 변경가능하지 못하는 필드도 변경가능한 상태가 된다.
- DTO를 통해 값을 변경하자.
- 엔티티 객체에 DTO 를 받아서 자기 값을 수정하는 메서드를 작성한다
- -> 객체지향적 관점에서도 객체의 상태를 바꾸는 동작은 객체 자신에게 있는게 맞다.
- 원하는 값을 수정하는 특정 메서드를 만듦으로서 객체의 수정 포인트를 한정지을 수 있다.
- 엔티티 객체에 DTO 를 받아서 자기 값을 수정하는 메서드를 작성한다
- JPA 를 사용하면 setter 로 객체의 값을 바꾸면 값이 변경된다.
// Entity 클래스에 DTO 를 이용해서 변환 메서드 추가
fun updateName(dto: UserDto) {
this.name = dto.name
}
// 서비스 로직
fun updateName(dto: UserDto): User {
val user = findById(dto.id)
user.updateName(dto) // 위 메서드를 이용
return user
}
https://cheese10yun.github.io/spring-jpa-best/
'TIL' 카테고리의 다른 글
TIL) 필드vs프로퍼티, backing field, backing property (0) | 2021.11.05 |
---|---|
TIL) Requset Wrapping, ContentCachingRequestWrapper , RequestBodyAdviceAdapter (Header/Body 의 차이와 성능이슈) (0) | 2021.10.23 |
TIL) JPA 페이징, Json 응답시 Null 필드 제외, Envers (0) | 2021.10.18 |
TIL) 깃 충돌, 예외 처리 전략, @CreatedDate vs @CreationTimeStamp (0) | 2021.10.17 |
TIL) 트래킹 브랜치, @RequestParam 디폴트, Kotlin any() (0) | 2021.10.15 |