해결된 질문
작성
·
135
·
수정됨
0
질문입니다!
상황 1 .
우선 NetworkClientExceptionV5는 RuntimeException을 상속 받은 상태입니다.
public class NetworkClientExceptionV5 extends RuntimeException {
public NetworkClientExceptionV5(String message) {
super(message);
}
}
그러면 NetworkClientExceptionV5를 상속받은 ConnectException과 SendException도 RuntimeException이 되는 거구요.
public class ConnectExceptionV5 extends NetworkClientExceptionV5 {
private final String address;
public ConnectExceptionV5(String address, String message) {
super(message);
this.address = address;
}
public String getAddress() {
return address;
}
}
public class SendExceptionV5 extends NetworkClientExceptionV5 {
private final String data;
public SendExceptionV5(String data, String message) {
super(message);
this.data = data;
}
public String getData() {
return data;
}
}
상황 2 .
그리고 NetworkClientV5는 AutoCloseable을 구현했습니다.
import exception.ex5.exception.ConnectExceptionV5;
import exception.ex5.exception.SendExceptionV5;
public class NetworkClientV5 implements AutoCloseable {
private final String address;
private boolean connectError;
private boolean sendError;
public NetworkClientV5(String address) {
this.address = address;
}
public void connect() {
if (connectError) {
throw new ConnectExceptionV5(address, address + " 서버 연결 실패");
}
// 연결 성공
System.out.println(address + " 서버 연결 성공");
}
public void send(String data) {
if (sendError) {
throw new SendExceptionV5(data, address + " 서버에 데이터 전송 실패 : " + data);
}
// 전송 성공
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() throws Exception {
System.out.println("NetworkClientV5.close");
disconnect();
}
}
==질문입니다!!==
NetworkServiceV5에서
public class NetworkServiceV5 {
public void sendMessage(String data) {
String address = "http://example.com";
try (NetworkClientV5 client = new NetworkClientV5(address)) {
client.initError(data); // 추가
client.connect();
client.send(data);
}
}
}
try (NetworkClientV5 client = new NetworkClientV5(address))에서 컴파일 오류가 납니다.
client에서 올라오는 예외들은 다 RuntimeException이므로 따로 throws를 안 해줘도 되는데 왜 해결하려고 하면 throws를 선언하거나 catch를 해야한다고 하는 건가요?
RuntimeException은 예외를 throws 선언없이 자동으로 밖으로 던지기에 catch를 안 해도 상관이 없을텐데 왜 alt + enter을 누르면 throws 선언과 catch를 해야만 된다고 하는 건지 이해가 가지 않습니다.
제가 생각하는 건 이런식으로 흘러간다고 생각했습니다.
main()에서 (error1 | error2)를 입력 받음 -> sendMessage를 호출 -> sendMessage에서 코드 진행 -> (client.connect | client.send)를 만나서 NetworkClientV5에 들어감 -> (ConnectException | SendException)을 터트림 -> NetworkClientV5에서 예외를 밖으로 던짐 (런타임이라서 throws 선언 안 해도 던져짐) -> NetworkService로 예외가 날라옴 -> 여기서도 처리가 불가능 하니, 예외를 밖으로 던짐 (여기서 throws 선언을 안해도 던져져야 한다고 생각함. 날아온 예외는 RuntimeException이기 때문에) -> main으로 예외가 넘어옴 -> main에는 catch (Exception e)가 있어서 예외를 잡고 정상흐름으로 돌아옴.
마지막은 메인메서드 입니다!
import exception.ex5.exception.SendExceptionV5;
import java.util.Scanner;
public class NetworkmainV5 {
public static void main(String[] args) {
NetworkServiceV5 service = new NetworkServiceV5();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("전송할 문자 : ");
String input = scanner.nextLine();
if (input.equals("exit")) {
break;
}
try {
service.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);
// 스택 트레이스 출력 System.err
//e.printStackTrace();
// 필요하면 예외별로 별도의 추가 처리 가능
if (e instanceof SendExceptionV5 sendEx) {
System.out.println("[전송 오류] 전송 데이터 = " + sendEx.getData());
}
}
}
답변 1
2
안녕하세요, 인프런 AI 인턴입니다.
님의 질문에 대한 답변입니다.
try (NetworkClientV5 client = new NetworkClientV5(address))
에서 컴파일 오류가 발생하는 이유는 NetworkClientV5
클래스의 close()
메소드 때문입니다. close()
메소드가 Exception
을 throw 하도록 선언되어 있습니다. 이는 곧 close()
메소드가 RuntimeException
이 아닌, 체크 예외(check exception)을 발생시킬 수 있다는 것을 의미합니다. AutoCloseable
인터페이스의 close()
메소드는 체크 예외를 던질 수 있으며, 이로 인해 try-with-resources 블록을 사용할 때 해당 예외를 처리하도록 강제되는 것입니다.
따라서, 님이 직접 처리한 RuntimeException
들(예: ConnectExceptionV5
, SendExceptionV5
)과는 별개로, close()
메소드의 예외 처리를 위해 try
블록 밖에 throws Exception
선언을 하거나, catch
블록을 추가하여 해당 예외를 처리해야 합니다. NetworkClientV5
의 close()
메소드가 체크 예외를 던질 가능성이 있기 때문에 컴파일러는 예외 처리를 요구하는 것입니다.
이와 관련된 예외 처리 방식을 코드에 반영하려면, NetworkServiceV5
클래스 내에서 sendMessage
메소드를 다음과 같이 업데이트할 수 있습니다:
public class NetworkServiceV5 {
public void sendMessage(String data) {
String address = "http://example.com";
try (NetworkClientV5 client = new NetworkClientV5(address)) {
client.initError(data);
client.connect();
client.send(data);
} catch (RuntimeException e) {
// RuntimeException 처리
} catch (Exception e) {
// AutoCloseable의 close() 메서드로 인한 Exception 처리
}
}
}
이렇게하면 try
블록 내에서 발생할 수 있는 RuntimeException
과 AutoCloseable
의 close()
메서드로 인해 발생할 수 있는 체크 예외 모두를 처리할 수 있습니다.