- 1 1. 소개
- 2 2. Java에서 예외 처리란?
- 3 3. throw란?
- 4 4. throws란?
- 5 5. throw와 throws의 차이점
- 6 6. throws 사용을 위한 모범 사례
- 7 7. 실용적인 예외 처리 패턴
- 7.1 7.1 try-with-resources를 활용한 자원 관리
- 7.2 7.2 Handling Multiple Exceptions Efficiently
- 7.3 7.2 여러 예외를 효율적으로 처리하기
- 7.4 7.3 Performance Considerations for Exception Handling
- 7.5 7.3 예외 처리 성능 고려사항
- 7.6 7.4 Logging and Notifications
- 7.7 7.4 로깅 및 알림
- 7.8 7.5 Implementing Custom Recovery Logic
- 7.9 7.5 사용자 정의 복구 로직 구현
- 8 8. Frequently Asked Questions (FAQ)
- 9 8. 자주 묻는 질문 (FAQ)
- 9.9.1 Q1. What is the main difference between throw and throws?
- 9.9.2 Q1. throw와 throws의 주요 차이점은 무엇인가요?
- 9.9.3 Q2. What should I be careful about when using throws?
- 9.9.4 Q2. throws를 사용할 때 주의해야 할 점은 무엇인가요?
- 9.9.5 Q3. Can throw and throws be used together?
- 9.9.6 Q3. throw와 throws를 함께 사용할 수 있나요?
- 9.9.7 Q4. How do I declare multiple exceptions using throws?
- 9.9.8 Q4. throws를 사용해 여러 예외를 선언하려면 어떻게 하나요?
- 9.9.9 Q5. Should I use throws with unchecked exceptions?
- 9.9.10 Q5. 체크되지 않은 예외에 throws를 사용해야 할까요?
- 9.9.11 Q6. Is it okay to declare Exception or Throwable in a throws clause?
- 9.9.12 Q6. throws 절에 Exception이나 Throwable을 선언해도 괜찮을까요?
- 9.9.13 Q7. Do I always need to catch exceptions declared in throws?
- 9.9.14 Q7. throws에 선언된 예외를 항상 잡아야 하나요?
- 9.9.15 Q8. throws를 쓰는 것을 잊으면 어떻게 되나요?
1. 소개
Java 프로그래밍을 시작하면 반드시 “예외 처리”라는 용어를 접하게 됩니다. 여러 키워드 중에서도 “throw”와 “throws”는 비슷해 보이지만 용도가 달라 초보자에게 특히 혼란스럽습니다.
Java는 안전성과 견고함을 염두에 두고 설계된 언어이며, 오류와 예상치 못한 상황을 적절히 처리할 수 있는 내장 메커니즘을 제공합니다. 이 메커니즘을 “예외 처리”라고 합니다. 예외 처리는 프로그램의 신뢰성과 유지 보수성을 높이는 데 중요한 역할을 합니다.
이 글에서는 “java throws” 사용법에 초점을 맞추어 예외 처리의 기본부터 자주 묻는 질문과 흔히 저지르는 실수까지 다룹니다. “throw”와 “throws”의 차이가 헷갈리거나, throws를 어디서 어떻게 사용해야 할지 궁금한 분들에게 특히 도움이 될 것입니다. 실제 프로젝트에서 자주 보게 되는 실용적인 정보, 팁, 샘플 코드도 함께 제공하니 끝까지 읽어 보시기 바랍니다.
2. Java에서 예외 처리란?
Java 프로그램을 작성하다 보면 런타임 중에 다양한 예상치 못한 상황이 발생할 수 있습니다. 예를 들어 파일을 찾을 수 없거나, 0으로 나누는 오류가 발생하거나, 배열 범위를 벗어난 접근을 시도하는 경우 등이 있습니다. 이러한 상황을 “예외”라고 부릅니다.
2.1 예외 처리의 기본 개념
예외 처리는 프로그램 실행 중에 발생하는 비정상적인 상황(예외)을 감지하고, 개발자가 적절히 대응할 수 있도록 하는 메커니즘입니다. 예외가 발생했을 때 프로그램을 갑자기 종료시키는 대신, Java는 오류의 유형과 내용에 따라 의미 있는 방식으로 응답할 수 있게 해 줍니다. 이를 통해 애플리케이션의 안정성과 사용자 경험이 향상됩니다.
2.2 체크 예외와 언체크 예외
Java 예외는 크게 두 가지 범주로 나뉩니다.
체크 예외
체크 예외는 컴파일 시점에 반드시 처리해야 하는 예외입니다. 파일 작업 중 발생하는 IOException 등이 대표적인 예입니다. 이러한 예외는 try‑catch 블록으로 잡거나, throws 선언을 통해 호출자에게 전파해야 합니다.
try {
FileReader fr = new FileReader("data.txt");
} catch (IOException e) {
e.printStackTrace();
}
언체크 예외
언체크 예외는 컴파일 시점에 강제적으로 처리할 필요가 없는 예외입니다. NullPointerException이나 ArrayIndexOutOfBoundsException처럼 주로 프로그래밍 실수에서 발생합니다. Java는 이러한 예외를 명시적으로 처리하지 않아도 컴파일이 되지만, 필요에 따라 처리하지 않으면 예상치 못한 오류가 발생할 수 있으므로 가능한 한 다루는 것이 좋습니다.
2.3 예외 처리가 필요한 이유
예외 처리를 올바르게 구현하면 다음과 같은 장점이 있습니다.
- 프로그램 안정성 향상: 예상치 못한 오류가 발생해도 프로그램이 적절한 메시지를 표시하거나 복구 로직을 실행하여 강제 종료를 방지합니다.
- 디버깅 용이: 예외 유형과 메시지를 통해 문제 원인을 빠르게 파악할 수 있습니다.
- 사용자 경험 개선: 오류로 인해 갑자기 종료되는 대신, 시스템이 의미 있는 피드백이나 복구 단계를 제공할 수 있습니다.
Java에서 예외 처리는 견고한 애플리케이션을 만들기 위한 필수 기술입니다. 다음 장에서는 “throw”의 기본을 설명합니다.
3. throw란?
Java에서 “throw”는 예외를 의도적으로 발생시킬 때 사용하는 키워드입니다. 예외는 프로그램 실행 중 자동으로 발생하기도 하지만, 특정 조건이 만족될 때 직접 예외를 만들고 발생시키고 싶을 때 “throw”를 사용합니다.
3.1 throw의 기본 사용법
“throw”는 예외 객체를 명시적으로 생성하고 이를 던져서 예외가 발생하도록 합니다. 기본 문법은 다음과 같습니다.
throw new ExceptionClass("Error message");
예를 들어, 잘못된 인수가 전달된 경우 다음과 같이 예외를 발생시킬 수 있습니다.
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Age must be zero or greater");
}
this.age = age;
}
이 예제에서는 나이가 0보다 작을 때 IllegalArgumentException이 발생합니다.
3.2 예외를 던지고 싶을 때
“throw”를 사용하는 주된 목적은 프로그램에 잘못된 상태나 규칙 위반을 즉시 알리는 것입니다. 이를 통해 버그를 조기에 발견하고 의도치 않은 동작을 방지할 수 있습니다. 예시:
- 사용자 입력이 검증에 실패할 때
- 잘못된 매개변수나 설정이 전달될 때
- 비즈니스 로직이 더 이상 처리를 진행할 수 없을 때
3.3 throw 사용 시 주의사항
“throw”로 예외를 발생시키면 해당 예외는 같은 메서드 내에서 try-catch 블록으로 처리되지 않는 한 호출자에게 전파됩니다. 체크 예외(IOException 등)의 경우 메서드 시그니처에 “throws”를 선언해야 합니다. 언체크 예외의 경우 throws 선언은 선택 사항이지만, “throw”와 “throws”의 차이를 이해하는 것이 올바른 사용에 필수적입니다.
4. throws란?
Java 프로그램을 작성할 때 메서드 선언에 “throws” 키워드가 나타날 수 있습니다. throws 키워드는 메서드 실행 중 하나 이상의 예외가 발생할 수 있음을 호출자에게 알리는 역할을 합니다.
4.1 throws의 기본 사용법
메서드 선언에 예외 클래스 이름을 지정하면, throws 키워드는 메서드 내부에서 발생할 수 있는 모든 예외를 호출자에게 전파합니다. 특히 체크 예외는 호출자가 적절히 처리하도록 throws 선언이 필요합니다. 예시:
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
// File reading process
}
이 예제에서는 FileReader 생성자가 IOException을 발생시킬 수 있으므로, 메서드에 throws IOException를 선언해야 합니다.
4.2 메서드 선언에서의 예외 전파
메서드가 throws를 선언하면, 그 안에서 발생하는 모든 예외가 호출자에게 전파됩니다. 호출자는 예외를 직접 잡거나 자신도 throws를 선언해 다시 전파해야 합니다.
public void processFile() throws IOException {
readFile("test.txt"); // readFile throws IOException, so this method must also declare throws
}
4.3 여러 예외 선언하기
메서드가 여러 예외를 발생시킬 수 있다면, throws 키워드 뒤에 콤마로 구분된 리스트로 선언할 수 있습니다.
public void connect(String host) throws IOException, SQLException {
// Network or database operations
}
4.4 throws의 역할과 장점
- 가독성 및 유지보수성 향상: throws 선언을 통해 메서드가 어떤 예외를 발생시킬 수 있는지 즉시 파악할 수 있어 개발자 간 커뮤니케이션이 원활해집니다.
- 오류 처리 책임 명확화: throws는 호출자가 반드시 예외를 처리하도록 강제함으로써 견고하고 구조화된 시스템 설계를 촉진합니다.
- 사용자 정의 예외 지원: 개발자는 throws 선언에 사용자 정의 예외 클래스를 포함시켜 복잡한 오류 상황을 보다 효과적으로 처리할 수 있습니다.
5. throw와 throws의 차이점
종종 혼동되지만, “throw”와 “throws”는 Java 예외 처리 메커니즘에서 매우 다른 역할을 합니다. 이 장에서는 두 키워드의 차이를 명확히 하고, 각각을 언제 어떻게 사용해야 하는지 설명합니다.
5.1 throw와 throws의 기능적 차이
| Item | throw | throws |
|---|---|---|
| Role | Actually generates an exception | Declares that a method may throw exceptions |
| Usage | Used inside methods to throw exception objects | Used in method declarations to specify throwable exceptions |
| Target | Exception objects created with new | Both checked and unchecked exceptions |
| Example | throw new IOException(“Error occurred”); | public void sample() throws IOException |
| When required | When intentionally raising an exception | When a method may throw checked exceptions |
5.2 각각이 사용되는 상황
- throw
- 잘못된 입력이나 규칙 위반을 감지했을 때와 같이 예외를 직접 생성하고 싶을 때 사용합니다.
- 예시: “나이가 0보다 작으면 IllegalArgumentException을 throw한다.”
- throws
- 메서드나 생성자가 예외를 발생시킬 수 있으며, 이를 호출자에게 알려야 할 때 사용합니다.
- 예시: “파일 작업이나 데이터베이스 접근과 같이 예외가 예상되는 메서드에 throws를 사용한다.”

5.3 비교를 위한 코드 예시
throw 예시:
public void setName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
this.name = name;
}
throws 예시:
public void loadConfig(String path) throws IOException {
FileReader reader = new FileReader(path);
// Configuration loading process
}
5.4 요약 표
| Decision Point | throw | throws |
|---|---|---|
| Where it’s used | Inside a method | Method declaration |
| What it does | Generates an exception | Declares exception propagation |
| Who handles it | Thrown at the point of error | Handled by the caller |
| When required | Optional (only when needed) | Required for checked exceptions |
throw와 throws의 역할은 명확히 구분되며, 어떤 상황에서 어느 것을 사용해야 하는지 이해하는 것이 견고한 예외 처리의 첫걸음입니다.
6. throws 사용을 위한 모범 사례
throws를 효과적으로 사용하면 Java 프로그램의 가독성과 유지보수성이 향상되고, 전반적인 예외 처리 품질도 높아집니다. 이 장에서는 실제 개발에서 흔히 사용되는 권장 실천 방법과 중요한 고려 사항을 소개합니다.
6.1 구체적인 예외 클래스 지정
throws 선언에서는 가능한 가장 구체적인 예외 클래스를 지정하십시오.
Exception이나 Throwable을 광범위하게 선언하는 것을 피하세요.
IOException이나 SQLException과 같은 구체적인 예외를 사용하면 호출자가 오류를 어떻게 처리해야 할지 정확히 판단할 수 있습니다.
좋은 예시:
public void saveData() throws IOException {
// File-saving process
}
피해야 할 예시:
public void saveData() throws Exception {
// Too vague: unclear what exceptions may occur
}
6.2 예외 계층 구조 활용
Java 예외 클래스는 계층 구조를 이루고 있기 때문에, 관련된 예외들을 적절히 상위 클래스 아래에 그룹화할 수 있습니다.
하지만 Exception과 같은 상위 수준 예외로 과도하게 일반화하면 가독성이 떨어지고 오류 처리가 어려워집니다.

6.3 Javadoc에 @throws 태그 사용
API나 라이브러리를 제공할 때는 Javadoc 주석에 @throws 태그를 사용해 예외를 문서화해야 합니다.
이렇게 하면 예외가 발생하는 조건을 명확히 설명하여 API 사용자가 올바른 예외 처리를 구현할 수 있습니다.
/**
* Reads a file.
* @param filePath Path of the file to read
* @throws IOException If the file cannot be read
*/
public void readFile(String filePath) throws IOException {
// ...
}
6.4 불필요한 예외 재throw 피하기
가치 없는 재throw를 위해 예외를 잡아두는 것을 피하십시오.
재throw가 필요할 경우 원본 예외를 커스텀 예외로 감싸거나 추가 컨텍스트·로그 정보를 포함시킵니다.
6.5 커스텀 예외 클래스 사용
비즈니스 애플리케이션이나 대규모 시스템에서는 커스텀 예외 클래스를 정의하고 throws 선언에 포함시키는 것이 일반적입니다.
이렇게 하면 오류 원인과 책임이 명확해져 시스템을 유지·확장하기 쉬워집니다.
public class DataNotFoundException extends Exception {
public DataNotFoundException(String message) {
super(message);
}
}
public void findData() throws DataNotFoundException {
// Throw when data is not found
}
throws를 적절히 사용하면 예외 처리 책임을 분산시키고, 문제 해결을 단순화하며, 신뢰성과 보안성이 높은 Java 애플리케이션을 구축할 수 있습니다.
7. 실용적인 예외 처리 패턴
Java에서 예외 처리는 단순한 try-catch 블록이나 throws 선언을 넘어섭니다. 이 장에서는 실제 개발에서 흔히 사용되는 실용적인 패턴과 설계 전략을 소개합니다.
7.1 try-with-resources를 활용한 자원 관리
파일, 네트워크 연결, 데이터베이스 연결 등을 다룰 때는 예외가 발생하더라도 자원을 적절히 해제하는 것이 중요합니다.
Java 7부터 도입된 try-with-resources 구문을 사용하면 자원을 자동으로 닫을 수 있습니다.
try (FileReader reader = new FileReader("data.txt")) {
// File reading process
} catch (IOException e) {
System.out.println("Failed to read file: " + e.getMessage());
}
This syntax ensures that close() is called automatically, preventing resource leaks even if exceptions occur.
이 구문은 close()가 자동으로 호출되도록 보장하여, 예외가 발생하더라도 리소스 누수를 방지합니다.
7.2 Handling Multiple Exceptions Efficiently
7.2 여러 예외를 효율적으로 처리하기
Complex operations may produce multiple types of exceptions.
Since Java 7, you can catch multiple exceptions in a single catch clause using the multi-catch feature.
복잡한 작업은 여러 종류의 예외를 발생시킬 수 있습니다. Java 7부터는 멀티 캐치 기능을 사용하여 하나의 catch 절에서 여러 예외를 동시에 잡을 수 있습니다.
try {
methodA();
methodB();
} catch (IOException | SQLException e) {
// Handle both exceptions here
e.printStackTrace();
}
You can also separate catch blocks to provide customized handling for each exception type.
각 예외 유형에 대해 맞춤형 처리를 제공하려면 catch 블록을 별도로 나눌 수도 있습니다.
7.3 Performance Considerations for Exception Handling
7.3 예외 처리 성능 고려사항
While exceptions are powerful, they should not replace normal control flow.
Generating exceptions requires significant overhead because stack traces must be created, so they should be reserved for truly exceptional cases.
Incorrect usage (not recommended):
예외는 강력하지만 일반적인 제어 흐름을 대체해서는 안 됩니다. 예외를 생성하면 스택 트레이스를 만들기 때문에 상당한 오버헤드가 발생하므로, 정말 예외적인 경우에만 사용해야 합니다. 잘못된 사용법(권장되지 않음):
try {
int value = array[index];
} catch (ArrayIndexOutOfBoundsException e) {
// Bounds checking should be done beforehand
}
Recommended usage:
권장 사용법:
if (index >= 0 && index < array.length) {
int value = array[index];
} else {
// Out-of-range handling
}
7.4 Logging and Notifications
7.4 로깅 및 알림
Proper logging and alerting are essential for troubleshooting when exceptions occur.
Business systems often use logging frameworks (e.g., Log4j, SLF4J) to record detailed exception information.
예외가 발생했을 때 문제 해결을 위해 적절한 로깅과 알림은 필수적입니다. 비즈니스 시스템은 종종 로깅 프레임워크(예: Log4j, SLF4J)를 사용하여 상세한 예외 정보를 기록합니다.
catch (Exception e) {
logger.error("An error has occurred", e);
}
7.5 Implementing Custom Recovery Logic
7.5 사용자 정의 복구 로직 구현
In some cases, it is useful to implement recovery logic such as retrying an operation, reloading configuration files, or notifying users.
Instead of terminating the program immediately, strive to maintain service continuity whenever possible.
By adopting practical exception-handling techniques, you can build Java applications that are both reliable and maintainable.
경우에 따라 작업을 재시도하거나, 설정 파일을 다시 로드하거나, 사용자에게 알리는 등 복구 로직을 구현하는 것이 유용합니다. 프로그램을 즉시 종료하는 대신 가능한 한 서비스 연속성을 유지하도록 노력하십시오. 실용적인 예외 처리 기법을 채택하면 신뢰성과 유지 보수가 모두 뛰어난 Java 애플리케이션을 만들 수 있습니다.
8. Frequently Asked Questions (FAQ)
8. 자주 묻는 질문 (FAQ)
Below are common questions from beginners about Java exception handling, particularly regarding “throws,” along with their answers.
아래는 Java 예외 처리, 특히 “throws”와 관련하여 초보자들이 자주 묻는 질문과 그에 대한 답변입니다.
Q1. What is the main difference between throw and throws?
Q1. throw와 throws의 주요 차이점은 무엇인가요?
throw is a keyword that actually generates an exception during program execution.
throws is used in method declarations to announce the possibility that a method may throw exceptions.
→ A good way to remember this: throw = “execute,” throws = “declare.”
throw는 프로그램 실행 중에 예외를 실제로 발생시하는 키워드입니다. throws는 메서드 선언에서 해당 메서드가 예외를 발생시킬 가능성을 알리기 위해 사용됩니다. → 기억하기 쉬운 방법: throw = “실행”, throws = “선언”.
Q2. What should I be careful about when using throws?
Q2. throws를 사용할 때 주의해야 할 점은 무엇인가요?
Exceptions declared with throws must be either caught by the caller or further propagated using throws.
For checked exceptions, explicit handling is mandatory.
If you do not catch or propagate the exception, the program will not compile.
throws로 선언된 예외는 호출자가 잡거나 다시 throws를 사용해 전파해야 합니다. 체크 예외의 경우 명시적인 처리가 필수입니다. 예외를 잡거나 전파하지 않으면 프로그램이 컴파일되지 않습니다.
Q3. Can throw and throws be used together?
Q3. throw와 throws를 함께 사용할 수 있나요?
Yes.
A common pattern is to throw an exception using throw inside a method and declare the same exception using throws so that it propagates to the caller.
예. 일반적인 패턴은 메서드 내부에서 throw로 예외를 발생시키고, 같은 예외를 throws로 선언하여 호출자에게 전파하는 것입니다.
Q4. How do I declare multiple exceptions using throws?
Q4. throws를 사용해 여러 예외를 선언하려면 어떻게 하나요?
List them after the throws keyword, separated by commas.
Example: public void sample() throws IOException, SQLException
throws 키워드 뒤에 콤마로 구분하여 나열합니다. 예시: public void sample() throws IOException, SQLException
Q5. Should I use throws with unchecked exceptions?
Q5. 체크되지 않은 예외에 throws를 사용해야 할까요?
Unchecked exceptions (those extending RuntimeException) do not require throws declarations.
However, throws may be used when you want to explicitly inform callers that a method can throw a specific unchecked exception, improving readability and API clarity.
체크되지 않은 예외(RuntimeException을 상속하는 예외)는 throws 선언이 필요하지 않습니다. 하지만 메서드가 특정 체크되지 않은 예외를 발생시킬 수 있음을 명시적으로 알리고 싶을 때는 throws를 사용해 가독성과 API 명확성을 높일 수 있습니다.
Q6. Is it okay to declare Exception or Throwable in a throws clause?
Q6. throws 절에 Exception이나 Throwable을 선언해도 괜찮을까요?
Technically yes, but it is not recommended.
Declaring very broad exception types makes it unclear what kinds of errors may occur and makes proper handling at the caller more difficult.
Use concrete exception classes whenever possible.
기술적으로는 가능하지만 권장되지 않습니다. 너무 포괄적인 예외 타입을 선언하면 어떤 오류가 발생할 수 있는지 불명확해지고, 호출자에서 적절히 처리하기 어려워집니다. 가능한 한 구체적인 예외 클래스를 사용하십시오.
Q7. Do I always need to catch exceptions declared in throws?
Q7. throws에 선언된 예외를 항상 잡아야 하나요?
A7.
체크된 예외의 경우, 호출자는 예외를 잡거나 throws를 사용해 더 위로 전파해야 합니다.
이를 수행하지 않으면 컴파일 오류가 발생합니다.
언체크 예외는 이 중 어느 것도 요구하지 않습니다.
Q8. throws를 쓰는 것을 잊으면 어떻게 되나요?
A8.
메서드가 체크된 예외를 발생시키지만 throws로 선언하지 않으면 컴파일 시 오류가 발생합니다.
언체크 예외의 경우, throws 없이도 메서드가 정상적으로 컴파일되지만 여전히 적절한 오류 처리를 구현해야 합니다.
이 FAQ 섹션을 활용하여 Java 예외 처리에 대한 이해를 심화하세요.


