예외처리_최종_최종_진짜진짜최종(Optional)

eland·2024년 7월 28일

이번엔 진짜진짜임

예외 처리에 대해서는 배워도 배워도 끝이 없는 것 같다.

당장 배우는 것만 해도 3일째 걸린걸 보면 내가 스스로 학습해야 되는 것 까지 합한다면 아직 반의반도 안왔을 거라는 생각이 들곤한다.

저번엔 코드상으로 에러를 처리할 때 쓰는 try-catch,throw,throws에 대해 포스팅을 했다면 이번에는 학습했던 내용을 총괄적으로 담아보려한다.

Optional

Optional은 Null을 처리 하기에 용이하게 사용되는 클래스로 코드의 안정성을 보장하고 가독성 증가시킨다. 예외 발생을 미리 처리할 수 있다는 장점이 있다.

우리가 언제나 완벽한 코드를 작성할 것이라는 보장이 없으니 null이 예상치 못한 상황에서 발생하는 것을 방지해 주는 역할이라고 할 수 있다.

하지만 메모리 사용량이 많고 남발했다가는 부작용이 발생하기 때문에 Null 이 발생할 가능성이 있는 곳에 적절히 사용하는 것이 좋다

추가적으로 주의할 점은 Optional에서 값을 가져오거나 참조할 때 get, ispresent와 같은 메소드를 쓰면 wrapper처리한 의미가 사라지게 되므로 값을 쓸 때는 orElse,OrElseThrow 등등을 써서 처리하는 식으로 접근 해야할 것이다.

orElseGet - null이면 내부적으로 새로운 객체를 만들어서 반환

orElseThrow - null이면 사용자가 정의한 예외 처리를 던져 주는 애


**Optional은 왜 필드에는 사용을 못할까?**

⇒ 직렬화가 어렵다. Optional은 의도치 않은 null을 대체하기 위해 사용한 것(return null을 대체, 반환 타입)인데 
이게 애초에 필드를 대체하기 위해 고안된 값이 아니기 때문에 설계 자체의 차이가 있다고 나는 생각했다.

*직렬화 : 객체,data를 바이트 스트림으로 바꾸는 거


프로젝트를 하면서 JPA를 사용할 때는 Optional을 사용하라고 배웠고, 참고 자료에도 Optional로 짠 코드들이 다수였기에 그냥 사용했었는데 실제 수업을 진행하며 생각해보니 굳이 내가 Optional을 사용할까? 라는 생각이 들기도 했다.
차라리 나였다면 nullpointerexception을 포함해서 다른 에러 상태일때를 나눠서 구분해놓는게 더 좋지 않을까 라는 생각이 들었었다.

Optional이 대중적으로 쓰게 된 이유는 내가 사용했던 JPA의 도입으로 대중적으로 사용하게 되었고 이는 JPA에서 가장 많이 사용하는 DB상에서 조회하는 경우에 엔티티를 제대로 찾지 못하는 경우가 많이 발생할 수 있기에 도입되었다고 생각했다.

Java Persistence API(JPA) 는 말 그대로 자바(객체)가 원히 지 되도록 사용하는 API(영속성)이므로 jpa관점에서 객체가 null인 것을 차단하기 위해 optional사용 한것 같다고 생각했다.

Opional의 메소드들

get()

기본: Optional 객체의 값을 가져옴.

(만약 값이 존재하지 않는 경우, NoSuchElementException이 발생)

리턴 값:

isPresent()/ifPresent()

기능: Optional 객체가 있는지 확인.

리턴 값: boolean

orElse((기존에 있는)T other)

기능: Optional 객체가 비어 있다면, 전달된 기본값 other를 반환.

리턴 값: 사용자 지정 제네릭

orElseGet(Supplier<? Extends T> supplier)

기능: Optional 객체가 비어 있다면, 내부 함수를 실행하여 생성된 기본값을 반환.

리턴 값: 사용자 지정 제네릭

orElseThrow()/orElseThrow(Supplier<? Extends X> exceptionSupplier)

기능: Optional 객체가 비어 있다면, Exception을 발생.

리턴 값: 사용자 지정 제네릭


Optional에 이어서 저번시간에 그렇다면 결국 에러 처리를 Controller, Service, Respository 단 중 어디서 처리할 것인가냐는 얘기를 다시 한번 해보자.

레포지는 단순히 db랑 로직을 하는 곳일 뿐. 아무런 다른 게 들어가면 안되기 때문에 throws를 서비스에서 판정해 컨트롤러에서 처리하고 ResponseEntity를 통해 status를 반환해주는 게 용이하다고 생각했었다.

나는 이런식으로 생각했었고 실제대로 Controller단에서 에러를 받아서 처리하는 식으로 코드를 작성했었는데

단순히 상태를 반환하는 것 뿐만 아니라 예외를 캐치했을 때 추가적인 로직의 수정이나 추가가 필요하다면 Service단에서 에러를 처리하는 것도 좋다. 즉 때에 따라 다르다는 친구의 말을 듣자 그 또한 맞는 것 같았다.

이는 내가 복잡한 서비스를 개발해 보지 못해서 Controller에서만 예외처리를 해야한다고 생각하는 편견이라고 생각했고 토의를 통해 덕분에 좋은 정보를 안 것 같았다.

적다보니 ExceptionHandler와 advise, log , DB에 관한 내용을 담으려 했는데

너무많이 적다보면 가뜩이나 사진도 없는데 글을 읽는데에 지루함이 많을 것 같아 차라리 여러개를 적는게 나을 것 같아 추가적으로 포스팅을 적어야겠다.

ㅎㅎ

profile
더 이상 핑계를 댈 때가 아니다.

1개의 댓글

comment-user-thumbnail
2025년 6월 2일

인간의 창의력은 무궁무진하고 늘 새로운 오류를 만들어내지

답글 달기