일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- order by
- JavaScript
- html
- 알고리즘
- 개발자
- 프로그래머스 sql 고득점 kit
- Linux
- 예외처리
- Java
- DML
- SQL
- MySQL
- 형변환
- 백준
- String클래스
- 클래스
- 정보처리기사
- 스프링
- scanner
- 메서드
- 데이터 조회
- select문
- 리눅스
- 프론트엔드
- select
- 백엔드
- Git
- github
- sql문
- 자바
- where
- StringBuilder
- 프로그래밍
- mybatis
- BufferedReader
- 자바스크립트
- 웹개발
- 입출력
- 프로그래머스 SQL
- 정보처리기사필기요약
- Today
- Total
ToBe끝판왕
[ JAVA ] 예외 처리 (2) 본문
예외 처리
• try ~ catch 문을 사용해서 정상 흐름과 예외 흐름을 분리한다.
- 자바 예외 처리 매커니즘을 이해할 수 있다.
- 정상 흐름은 try 블럭에 모아서 처리
- 예외 흐름은 catch 블럭에 모아서 처리
• finally
- catch에서 잡을 수 없는 예외 발생 시, 반드시 호출되어야 하는 코드가 호출되지 않는 문제 해결 가능
- try 블럭이 시작하기만 하면, finally 블럭은 어떤 경우라도 반드시 호출된다.
- try ~ catch 안에서 잡을 수 없는 예외가 발생하더라도 finally는 반드시 호출 된다.
- fianlly 코드 블럭이 끝나고 난 이후 예외가 밖으로 던져진다.
- 주로 try에서 사용한 자원을 해제할 때 사용
• 예외처리 소스 예시
package exception.ex2;
public class NetworkClientExceptionV2 extends Exception {
private String errorCode;
public NetworkClientExceptionV2(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
package exception.ex2;
public class NetworkClientV2 {
private final String address;
public boolean connectError;
public boolean sendError;
public NetworkClientV2(String address) {
this.address = address;
}
public void connect() throws NetworkClientExceptionV2 {
if(connectError) {
throw new NetworkClientExceptionV2("connectError",address + " 서버 연결 실패");
}
// 연결 성공
System.out.println(address + " 서버 연결 성공");
}
public void send(String data) throws NetworkClientExceptionV2 {
if(sendError) {
throw new NetworkClientExceptionV2("sendError",address + " 서버에 데이터 전송 실패");
//중간에 다른 예외가 발생했다고 가정
//throw new RuntimeException("ex");
}
// 전송 성공
System.out.println(address + " 서버에 데이터 전송: " + data);
}
public void disconnect() {
System.out.println(address + " 서버 연결 해제");
}
public void initError(String data) {
if( data.contains("error1")) {
connectError = true;
}
if( data.contains("error2")) {
sendError = true;
}
}
}
package exception.ex2;
public class NetworkServiceV2_5 {
public void sendMessage(String data) {
String address = "http://www.example.com";
NetworkClientV2 client = new NetworkClientV2(address);
client.initError(data); // 추가
try {
// try 블럭안에 하나의 정상적인 흐름을 담는다.
client.connect();
client.send(data);
} catch (NetworkClientExceptionV2 e) {
// 예외부분은 catch 블럭에서 처리
System.out.println("[오류] 코드: " + e.getErrorCode() + ", 메시지: " + e.getMessage());
} finally {
client.disconnect();
}
}
}
package exception.ex2;
import java.util.Scanner;
public class MainV2 {
public static void main(String[] args) throws NetworkClientExceptionV2 {
//NetworkServiceV2_1 networkService = new NetworkServiceV2_1();
//NetworkServiceV2_2 networkService = new NetworkServiceV2_2();
//NetworkServiceV2_3 networkService = new NetworkServiceV2_3();
//NetworkServiceV2_4 networkService = new NetworkServiceV2_4();
NetworkServiceV2_5 networkService = new NetworkServiceV2_5();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("전송할 문자: ");
String input = scanner.nextLine();
if( input.equals("exit") ) {
break;
}
networkService.sendMessage(input);
System.out.println();
}
System.out.println("프로그램을 정상 종료합니다");
}
}
// 실행 결과
전송할 문자: hello
http://www.example.com 서버 연결 성공
http://www.example.com 서버에 데이터 전송: hello
http://www.example.com 서버 연결 해제
전송할 문자: error1
[오류] 코드: connectError, 메시지: http://www.example.com 서버 연결 실패
http://www.example.com 서버 연결 해제
전송할 문자: error2
http://www.example.com 서버 연결 성공
[오류] 코드: sendError, 메시지: http://www.example.com 서버에 데이터 전송 실패
http://www.example.com 서버 연결 해제
전송할 문자: exit
프로그램을 정상 종료합니다
예외처리의 계층화
• NetworkClientExceptionV3 / ConnectExceptionV3 / SendExceptionV3 로 계층화를 시킨다.
package exception.ex3.exception;
public class ConnectExceptionV3 extends NetworkClientExceptionV3{
private final String address;
public ConnectExceptionV3(String address, String message) {
super(message);
this.address = address;
}
public String getAddress() {
return address;
}
}
package exception.ex3.exception;
public class SendExceptionV3 extends NetworkClientExceptionV3{
private final String sendData;
public SendExceptionV3(String sendData, String message) {
super(message);
this.sendData = sendData;
}
public String getSendData() {
return sendData;
}
}
package exception.ex3.exception;
public class NetworkClientExceptionV3 extends Exception{
public NetworkClientExceptionV3(String message) {
super(message);
}
}
• 위에서 정의한 예외들로 예외처리를 하는 소스 예시
- 예외 클래스를 각각의 예외 상황에 맞추어 만들면, 각 필요에 맞는 예외를 잡아서 처리 가능
package exception.ex3;
import exception.ex3.exception.ConnectExceptionV3;
import exception.ex3.exception.NetworkClientExceptionV3;
import exception.ex3.exception.SendExceptionV3;
public class NetworkServiceV3_2 {
public void sendMessage(String data) {
String address = "http://www.example.com";
NetworkClientV3 client = new NetworkClientV3(address);
client.initError(data); // 추가
try {
// try 블럭안에 하나의 정상적인 흐름을 담는다.
client.connect();
client.send(data);
} catch (ConnectExceptionV3 e) {
System.out.println("[연결 오류] 주소: " + e.getAddress() + ", 메시지: " + e.getMessage());
} catch (NetworkClientExceptionV3 e) {
System.out.println("[네트워크 오류] 메시지: " + e.getMessage());
} catch (Exception e) {
System.out.println("[알 수 없는 오류] 메시지: " + e.getMessage());
} finally {
client.disconnect();
}
}
}
package exception.ex3;
import exception.ex3.exception.ConnectExceptionV3;
import exception.ex3.exception.SendExceptionV3;
public class NetworkClientV3 {
private final String address;
public boolean connectError;
public boolean sendError;
public NetworkClientV3(String address) {
this.address = address;
}
public void connect() throws ConnectExceptionV3 {
if(connectError) {
throw new ConnectExceptionV3(address,address + " 서버 연결 실패");
}
// 연결 성공
System.out.println(address + " 서버 연결 성공");
}
public void send(String data) throws SendExceptionV3 {
if(sendError) {
//throw new SendExceptionV3(data,address + " 서버에 데이터 전송 실패: " + data);
throw new RuntimeException("ex");
}
// 전송 성공
System.out.println(address + " 서버에 데이터 전송: " + data);
}
public void disconnect() {
System.out.println(address + " 서버 연결 해제");
}
public void initError(String data) {
if( data.contains("error1")) {
connectError = true;
}
if( data.contains("error2")) {
sendError = true;
}
}
}
// 실행 결과
전송할 문자: hello
http://www.example.com 서버 연결 성공
http://www.example.com 서버에 데이터 전송: hello
http://www.example.com 서버 연결 해제
전송할 문자: error1
[연결 오류] 주소: http://www.example.com, 메시지: http://www.example.com 서버 연결 실패
http://www.example.com 서버 연결 해제
전송할 문자: error2
http://www.example.com 서버 연결 성공
[네트워크 오류] 메시지: http://www.example.com 서버에 데이터 전송 실패: error2
http://www.example.com 서버 연결 해제
전송할 문자: exit
프로그램을 정상 종료합니다
실무에서의 예외 처리
• 처리할 수 없는 예외
- 해당 예외의 경우, 고객에게는 오류 메시지를 보여주고 내부 개발자가 문제 상황을 빠르게 인지할 수 있도록
오류에 대한 로그를 남겨 둬야 한다. ( 오류 메시지 + 오류 로그 )
- 체크 예외의 경우, 최상위 타입인 Exception으로 던지는 개발을 하지 않는다.
( 다른 체크 예외를 체크할 수 있는 기능의 무효화 되어 중요한 체크 예외를 다 놓치게 된다. )
- 언체크 예외의 경우, 예외를 공통으로 처리할 수 있는 곳을 만들어 한곳에서 해결하면 된다.
( 오류메시지와 개발자를 위한 에러 로그를 남기는것은 공통처리로 가능 하다. )
• 코드 예시
package exception.ex4.exception;
public class NetworkClientExceptionV4 extends RuntimeException{
public NetworkClientExceptionV4(String message) {
super(message);
}
}
package exception.ex4.exception;
public class ConnectExceptionV4 extends NetworkClientExceptionV4 {
private final String address;
public ConnectExceptionV4(String address, String message) {
super(message);
this.address = address;
}
public String getAddress() {
return address;
}
}
package exception.ex4.exception;
public class SendExceptionV4 extends NetworkClientExceptionV4 {
private final String sendData;
public SendExceptionV4(String sendData, String message) {
super(message);
this.sendData = sendData;
}
public String getSendData() {
return sendData;
}
}
• 위 소스를 바탕으로 예외 처리
- 실무에서는 System.out 이나 System.err 을 통해 콘솔에 무언가를 출력하기 보다는, 주로 Slf4J, logback 같은 별도의
로그 라이브러리를 사용해서 콘솔과 특정 파일에 함께 결과를 출력한다
package exception.ex4;
import exception.ex4.exception.ConnectExceptionV4;
public class NetworkClientV5 implements AutoCloseable{
private final String address;
public boolean connectError;
public boolean sendError;
public NetworkClientV5(String address) {
this.address = address;
}
public void connect() {
if(connectError) {
throw new ConnectExceptionV4(address,address + " 서버 연결 실패");
}
// 연결 성공
System.out.println(address + " 서버 연결 성공");
}
public void send(String data) {
if(sendError) {
//throw new SendExceptionV3(data,address + " 서버에 데이터 전송 실패: " + data);
throw new RuntimeException("ex");
}
// 전송 성공
System.out.println(address + " 서버에 데이터 전송: " + data);
}
public void disconnect() {
System.out.println(address + " 서버 연결 해제");
}
public void initError(String data) {
if( data.contains("error1")) {
connectError = true;
}
if( data.contains("error2")) {
sendError = true;
}
}
@Override
public void close() {
System.out.println("NetworkClientV5.close");
disconnect();
}
}
package exception.ex4;
public class NetworkServiceV5 {
public void sendMessage(String data) {
String address = "http://www.example.com";
try(NetworkClientV5 client = new NetworkClientV5(address)) {
client.initError(data);
client.connect();
client.send(data);
} catch(Exception e) {
System.out.println("[예외 확인]: " + e.getMessage());
throw e;
}
}
}
package exception.ex4;
import exception.ex4.exception.SendExceptionV4;
import java.util.Scanner;
public class MainV4 {
public static void main(String[] args) {
//NetworkServiceV4 networkService = new NetworkServiceV4();
NetworkServiceV5 networkService = new NetworkServiceV5();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("전송할 문자: ");
String input = scanner.nextLine();
if( input.equals("exit") ) {
break;
}
// 공통 예외 처리 ( 클라이언트에게는 오류메시지, 개발자에게는 로그 )
try {
networkService.sendMessage(input);
} catch(Exception e) {
exceptionHandler(e);
}
System.out.println();
}
System.out.println("프로그램을 정상 종료합니다");
}
// 공통 예외 처리
private static void exceptionHandler(Exception e) {
// 공통 처리
System.out.println("사용자 메시지: 죄송합니다, 알 수 없는 문제가 발생했습니다.");
System.out.println("== 개발자용 디버깅 메시지 ==");
e.printStackTrace(System.out); // 스택 트레이스 출력
//e.printStackTrace();
// 필요하면 예외 별로 별도의 추가 처리 기능
if( e instanceof SendExceptionV4 sendEx ) {
System.out.println("[전송 오류] 전송 데이터: " + sendEx.getSendData());
}
}
}
// 실행 결과
전송할 문자: hello
http://www.example.com 서버 연결 성공
http://www.example.com 서버에 데이터 전송: hello
NetworkClientV5.close
http://www.example.com 서버 연결 해제
전송할 문자: error1
NetworkClientV5.close
http://www.example.com 서버 연결 해제
[예외 확인]: http://www.example.com 서버 연결 실패
사용자 메시지: 죄송합니다, 알 수 없는 문제가 발생했습니다.
== 개발자용 디버깅 메시지 ==
exception.ex4.exception.ConnectExceptionV4: http://www.example.com 서버 연결 실패
at exception.ex4.NetworkClientV5.connect(NetworkClientV5.java:17)
at exception.ex4.NetworkServiceV5.sendMessage(NetworkServiceV5.java:12)
at exception.ex4.MainV4.main(MainV4.java:24)
전송할 문자: error2
http://www.example.com 서버 연결 성공
NetworkClientV5.close
http://www.example.com 서버 연결 해제
[예외 확인]: ex
사용자 메시지: 죄송합니다, 알 수 없는 문제가 발생했습니다.
== 개발자용 디버깅 메시지 ==
java.lang.RuntimeException: ex
at exception.ex4.NetworkClientV5.send(NetworkClientV5.java:27)
at exception.ex4.NetworkServiceV5.sendMessage(NetworkServiceV5.java:13)
at exception.ex4.MainV4.main(MainV4.java:24)
전송할 문자: exit
프로그램을 정상 종료합니다
※ 해당 내용은 인프런 김영한 강사님의 "실전 자바 중급1" 인강의 참고자료와 예시들을 참고하였습니다
'■ 프로그래밍 SKILLS > JAVA' 카테고리의 다른 글
[ JAVA ] 컬렉션 프레임워크 (2) - Set (5) | 2024.10.23 |
---|---|
[ JAVA ] 컬렉션 프레임워크 (1) - List (3) | 2024.10.23 |
[ JAVA ] 예외 처리 (1) (0) | 2024.08.21 |
[ JAVA ] 열거형 ( ENUM ) (0) | 2024.08.20 |
[ JAVA ] 래퍼 클래스 ( Wrapper Class ) (0) | 2024.08.20 |