์๋ก
๋ณดํต ํ๋ก์ ํธ๋ฅผ ์งํํ ๋, ์๋์ ๊ฐ์ ์ฅ์ ๋๋ฌธ์ ์๋ฐ์์ ์ ๊ณตํ๋ ์์ธ ํด๋์ค ์ธ์ ๊ฐ๋ฐ์๊ฐ ์ง์ Custom Exception ํด๋์ค๋ฅผ ์ ์ํ์ฌ ์์ฃผ ์ฌ์ฉํฉ๋๋ค.
- ์๋ฌ ์ฒ๋ฆฌ์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ ์ฑ ์ ์ง: ๊ฐ๋ฐ์๊ฐ ์ง์ ์์ ํด๋์ค๋ฅผ ์ ์ํ๋ฏ๋ก, ์๋ฌ ๋ฉ์์ง๋ฅผ ๋ณด๋ค ๋ช ํํ๊ฒ ์ ์ํ ์ ์๊ณ , ๊ฐ๋ฐ์๊ฐ ์ง์ ์ผ๊ด์ฑ ์๊ฒ ์๋ฌ์ฒ๋ฆฌ๋ฅผ ์ ์ํ ์ ์๋ค.
- ๋ก๊น ๋ฐ ๋๋ฒ๊น ์ ์ฉ์ด: ๊ฐ๋ฐ์๊ฐ ์์ธ ํด๋์ค์ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ์ถ๊ฐํ์ฌ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋๋ฒ๊น ์ ์ฉ์ดํ๊ฒ ํ ์ ์๋ค.
- ์์ธ ์ฒ๋ฆฌ์ ์ ์ฐ์ฑ: ์์ธ ํด๋์ค๋ฅผ ์์ํ์ฌ ์ฌ์ฉํ๋ ๋ฑ ๋ค์ํ ์์ธ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ ์ฉํ ์ ์๋ค.
ํ์ง๋ง ์ด๋ฌํ ์ฅ์ ์ธ์๋, ์๋ฐ์์๋ Exception์ ์ฒ๋ฆฌ ๋น์ฉ์ด ๋งค์ฐ ๋น์ธ๋ค๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด๋ฒ ๊ฒ์๊ธ์์๋ JVM์์ Exception์ด ์ฒ๋ฆฌ๋๋ ์์์ Exception์ ์์ฑ ๋น์ฉ์ด ๋น์ผ ์ด์ , ๊ทธ๋ฆฌ๊ณ ๋น์ฉ์ ์ค์ด๋ ๋ฐฉ๋ฒ์ ๋ํด ์ ๋ฆฌํด ๋ณด๊ฒ ์ต๋๋ค.
๋ชฉ์ฐจ
- JVM์ Exception ์ฒ๋ฆฌ ์์
- Exception ๋น์ฉ์ด ์๊ธฐ๋ ์์ธ
- ๋น์ฉ์ ์ค์ด๋ ๋ฐฉ๋ฒ
JVM์ Exception ์ฒ๋ฆฌ ์์
๋จผ์ JVM์์ Exception์ ์ํํ๋ ๊ณผ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
- ์์ธ ๋ฐ์: ์์ธ๊ฐ ๋ฐ์ํ๋ฉด JVM์ ์์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์์ธ๋ฅผ ๋ฐ์์ํจ ๋ฉ์๋์ ํธ์ถ ์คํ์ ์ถ์ ํ๋ค.
- ์์ธ ๊ฐ์ฒด ์ ํ: JVM์ ํด๋น ์์ธ๋ฅผ ๋ฐ์์ํจ ๋ฉ์๋์์ ์์ธ ์ฒ๋ฆฌ ์ฝ๋๋ฅผ ์ฐพ๊ณ , ์์ธ ์ฒ๋ฆฌ ์ฝ๋๊ฐ ์๋ ๊ฒฝ์ฐ ์์ธ ๊ฐ์ฒด๋ฅผ ํธ์ถ ์คํ์ ์์ ๋ฉ์๋๋ก ์ ํ์ํจ๋ค.
- ์์ธ ์ฒ๋ฆฌ: ์์ธ ๊ฐ์ฒด๊ฐ ์์ ๋ฉ์๋๋ก ์ ํ๋๋ฉด, ํด๋น ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ catch ๋ธ๋ก์ ์ฐพ๊ณ , ์๋ค๋ฉด ์์ธ๋ ๋ค์ ์์ ๋ฉ์๋๋ก ์ ํ๋๋ค.
- ์์ธ ์ฒ๋ฆฌ ์คํจ: ์์ธ ๊ฐ์ฒด๊ฐ ์ต์์ ๋ฉ์๋๊น์ง ์ ํ๋์ด๋, ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ catch๋ธ๋ก์ด ์๋ ๊ฒฝ์ฐ JVM์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํ ๊ฒ์ผ๋ก ํ๋จํ์ฌ ํด๋น ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ Default Exception Handler๋ฅผ ์ฌ์ฉํ์ฌ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ค.
- Default Exception Handler ์คํ: Default Exception Handler๋ ์์ธ ๊ฐ์ฒด์ ๋ํ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๊ณ , ํด๋น ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ์์ธ ๊ฐ์ฒด์ ๋ํ ์ค๋ ์ท ์ ๋ณด๋ฅผ ์์งํ์ฌ ๋๋ฒ๊น ์ ์ํ ์ ๋ณด๋ก ์ ๊ณตํ๋ค.
์์ธ๊ฐ ๋ฐ์ํ ๋ฉ์๋์์ ๋ฐ๋ก ์ฒ๋ฆฌ๊ฐ ๋๋ค๋ฉด ๊ฐ์ฅ ์ข์ง๋ง, ๋ฐ๋ก ์ฒ๋ฆฌ๋์ง ๋ชปํ๋ฉด JVM์ ํด๋น ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ๋ฉ์๋๋ฅผ ์ฐพ์ ๋ ๊น์ง ๊ณ์ํด์ ์์ ๋ฉ์๋๋ก ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉด์ ๋ฉ๋ชจ๋ฆฌ์ ํธ์ถ ์คํ(call stack)์ ํ์ํ๊ฒ ๋ฉ๋๋ค.
๋น์ฉ์ด ์๊ธฐ๋ ์์ธ
๋จผ์ ํธ์ถ ์คํ์ ํ์ํ๋ ๊ณผ์ ์์ฒด๋ ๋น์ฉ์ด์ง๋ง, fillInStackTrace() ๋ฉ์๋๊ฐ ํธ์ถ ์คํ์ ์ํํ๋ฉฐ ํด๋์ค๋ช , ๋ฉ์๋๋ช , ์ฝ๋ ์ค ๋ฒํธ ๋ฑ์ ์ ๋ณด๋ฅผ ๋ชจ์ stacktrace๋ก ๋ง๋๋ ๊ณผ์ ๋ํ ๋น์ฉ ์ฆ๊ฐ์ ์์ธ์ ๋๋ค.
fillInStackTrace()๋ Throwable ํด๋์ค์ ์ ์๋ ๊ตฌํ ๋ฉ์๋๋ก ์์ฑ์์์ ํธ์ถ๋๋๋ก ๋์ด์๋ฉฐ, ๋ชจ๋ Exception์ Throwable์ ์์๋ฐ๋๋ก ๋์ด์๊ธฐ ๋๋ฌธ์ fillInStackTrace() ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก StackTrace๋ฅผ ์์ฑํ๋ ์๊ฐ์ ๋ช ๋ฐ๋ฆฌ์ด์์ ๋ช ์ด๊น์ง ๋ค์ํฉ๋๋ค. ํ์ง๋ง ์ด๋ ์์ธ๊ฐ ๋ฐ์ํ ํ๊ฒฝ, StackTrace์ ๊น์ด, StackFrame์ ๋ฉ์๋ ํธ์ถ ์, JVM์ ๋ฒ์ ๋ฐ ์ค์ ๋ฑ์ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์๊ฐ์ ์ ์ํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
- https://sudonull.com/post/72142-Everything-you-wanted-to-know-about-stack-traces-and-hip-dumps-Part-1-JUG-Ru-Group-Blog
- https://shipilev.net/blog/2014/exceptional-performance/
- https://segmentfault.com/a/1190000040373647/en
ํ์ง๋ง ์์ ๋ช๋ช ๋ธ๋ก๊ทธ๋ฅผ ๋ณด๋ฉด, Stack Trace๊ฐ ๊น์์๋ก ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค๋ ๊ฒ์ ๋ถ๋ช
ํฉ๋๋ค.
๋น์ฉ์ ์ค์ด๋ ๋ฐฉ๋ฒ
- fillInStackTrace() ๋ฉ์๋ ์ฌ์ ์
- ์์ธ ์บ์ฑ
1. fillInStackStrace ์ฌ์ ์
๋ณดํต NullPointException์ด๋ OutOfMemory์ ๊ฐ์ด ์๋ฐ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ์์ธ๋ฅผ ์ ์ธํ, ์ฐ๋ฆฌ๊ฐ ๋ง๋ Custom Exception์ ์๋ฌ์ ์ถ์ ๋ณด๋ค๋ ์ ํจํ์ง ์๋ ๊ฐ์ผ ๋ ํ์ ๋น์ฆ๋์ค ๋ก์ง์ ์ํํ์ง ๋ชปํ๋๋ก ํ๊ธฐ ์ํ ์ฉ๋๋ก ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ณดํตStackTrace๊ฐ ํ์ํ์ง ์์ต๋๋ค.
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
๋๋ฌธ์ ๋จ์ํ Try-Catch๋ก ์ดํ์ Flow๋ฅผ ์ ์ดํ๊ฑฐ๋, Spring ํ๊ฒฝ์์ @ControllerAdvice๋ก ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ์๋ ๋ถํ์ํ ์ฑ๋ฅ ์ ํ๋ฅผ ๋ง๊ธฐ ์ํด ์๋ฌด trace๋ ์ ์ฅํ์ง ์๋๋ก ์ง์ ์ ์ฝ๋์ฒ๋ผ fillInStackTrace()๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์์ ์ฝ๋
public class DuplicateLoginException extends RuntimeException {
public DuplicateLoginException(String message) {
super(message);
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
fillInStackTrace() ์ฌ์ ์ ์ ์๋ฌ ์์
kancho.realestate.comparingprices.exception.DuplicateLoginException: ์ด๋ฏธ ๋ก๊ทธ์ธํ ์ํ์
๋๋ค.
at kancho.realestate.comparingprices.controller.UserController.validateDuplicateLogin(UserController.java:67)
at kancho.realestate.comparingprices.controller.UserController.login(UserController.java:44)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at
... ์๋ต
fillInStackTrace() ์ฌ์ ์ ํ ์๋ฌ ์์
kancho.realestate.comparingprices.exception.DuplicateLoginException: ์ด๋ฏธ ๋ก๊ทธ์ธํ ์ํ์
๋๋ค.
2. ์์ธ ์บ์ฑํ๊ธฐ
static final๋ก ์ ์ธํ์ฌ ์ด์ฉํด ์์ธ๋ฅผ ๋ฏธ๋ฆฌ ์บ์ฑํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ผ์ข ์ ์์ ๊ฐ ํํ๋ก ์์ธ๋ฅผ ์บ์ฑํด ๋๊ณ ์ฐ๋ ๊ฒ์ด ๋งค๋ฒ ๊ฐ์ ์ข ๋ฅ์ ์์ธ๋ก new๋ก ์์ฑํ๋ ๋ฐฉ๋ฒ๋ณด๋ค ํจ์จ์ ์ ๋๋ค.
public class CustomException extends RuntimeException {
public static final CustomException INVALID_NICKNAME = new CustomException(ResponseType.INVALID_NICKNAME);
public static final CustomException INVALID_PARAMETER = new CustomException(ResponseType.INVALID_PARAMETER);
public static final CustomException INVALID_TOKEN = new CustomException(ResponseType.INVALID_TOKEN);
//์๋ต
}
์์ ๊ฐ์ด Exception ํด๋์ค์ ์์ธ ์ํฉ์ ๋ํ ์ ๋นํ ์๋ต ๋ฉ์์ง๋ ์ฝ๋๋ฅผ ๋ด๋๋ก ํ ๋ค, ์๋์ฒ๋ผ ์์ธ ๋ฐ์ ์ํฉ์์ new ํค์๋ ์์ด throw๋ฅผ ์ํํ๋๋ก ํฉ๋๋ค.
if (StringUtils.isBlank(parameter)) {
throw WebtoonCoreException.INVALID_PARAMETER;
}
์ฐธ๊ณ
'BackEnd๐ฑ > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Java์์ assert์ exception (0) | 2023.08.11 |
---|---|
์ผ๊ธ ์ปฌ๋ ์ (First-Class Collection)์ด๋? (0) | 2023.04.12 |
Java์ ๊ธฐ๋ณธ ํจ์ํ ์ธํฐํ์ด์ค (0) | 2023.03.20 |
๋๋ฏธํฐ ๋ฒ์น (Law of Demeter)์ด๋? (2) | 2023.02.01 |
์๋ฐ์์ ๋์์ฑ์ ํด๊ฒฐํ๋ ๋ค์ํ ๋ฐฉ๋ฒ๊ณผ Redis์ ๋ถ์ฐ๋ฝ (5) | 2023.01.08 |
ํด์ ์๋ฃ๊ตฌ์กฐ์, ํด์ ์ถฉ๋ ๊ทธ๋ฆฌ๊ณ Java์ HashMap ๋์ ๋ฐฉ๋ฒ (1) | 2022.12.30 |
๋๊ธ