개발자 ν˜Έμ†ŒμΈ

[Class -11] 상속 / μ˜ˆμ™Έμ²˜λ¦¬ / μž…μΆœλ ₯(OI)

리제🫧 2026. 6. 1. 16:31

β—† μƒμ†μ˜ 기본적인 νŠΉμ„±κ³Ό νŠΉμ§•

상속은 κΈ°μ‘΄ 클래슀(λΆ€λͺ¨)의 λ³€μˆ˜μ™€ λ©”μ„œλ“œλ₯Ό μƒˆλ‘œμš΄ 클래슀(μžμ‹)κ°€ λ¬Όλ €λ°›μ•„ κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κ±°λ‚˜ κΈ°λŠ₯을 ν™•μž₯ν•˜λŠ” λ§€μ»€λ‹ˆμ¦˜μž„.

  • ν‚€μ›Œλ“œ: extends (ν™•μž₯ν•˜λ‹€) 기호λ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•¨.
  • 적용 λ²”μœ„: λΆ€λͺ¨μ˜ 멀버 쀑 private μ§€μ‹œμžκ°€ 뢙은 λ³€μˆ˜λ‚˜ λ©”μ„œλ“œλŠ” 상속은 λ˜μ§€λ§Œ μžμ‹μ΄ 직접 μ ‘κ·Όν•  수 μ—†μŒ. λ˜ν•œ μƒμ„±μžλŠ” 상속 λŒ€μƒμ—μ„œ μ™„μ „νžˆ μ œμ™Έλ¨.
  • 이점: 이미 κ²€μ¦λœ μ½”λ“œλ₯Ό μž¬μ‚¬μš©ν•˜λ―€λ‘œ 쀑볡 μ½”λ“œκ°€ 획기적으둜 쀄어듀고, μœ μ§€λ³΄μˆ˜κ°€ μ‰¬μ›Œμ§€λ©° ν”„λ‘œκ·Έλž¨μ˜ ν™•μž₯성이 κ·ΉλŒ€ν™”λ¨.

β—† λͺ¨λ“  클래슀의 쑰상: Object 클래슀 후손

μžλ°”μ—μ„œ κ°œλ°œμžκ°€ λ§Œλ“œλŠ” λͺ¨λ“  ν΄λž˜μŠ€λŠ” λ³„λ„λ‘œ extendsλ₯Ό 적지 μ•Šμ•„λ„ 무쑰건 java.lang.Object 클래슀λ₯Ό μžλ™μœΌλ‘œ 상속받도둝 μ„€κ³„λ˜μ–΄ 있음.

  • μ΅œμƒμœ„ 쑰상: λͺ¨λ“  ν΄λž˜μŠ€λŠ” μ΅œν•˜μœ„ 후손이며, Objectκ°€ μ œκ³΅ν•˜λŠ” κΈ°λ³Έ λ©”μ„œλ“œλ“€μ„ λ¬Όλ €λ°›μ•„ μ‚¬μš©ν•  수 있음.
  • μ£Όμš” λ¬Όλ €λ°›λŠ” λ©”μ„œλ“œ:
    • toString(): 객체의 ν…μŠ€νŠΈ ν‘œν˜„(μ£Όμ†Œκ°’ λ˜λŠ” 데이터)을 λ°˜ν™˜ν•¨.
    • equals(Object obj): 두 객체가 λ©”λͺ¨λ¦¬μƒμ—μ„œ λ™μΌν•œμ§€ 비ꡐ함.

β—† 단일 상속 vs 닀쀑 상속

  • 단일 상속 (μžλ°”μ˜ ν‘œμ€€ κ·œμΉ™): μžλ°”λŠ” 클래슀 κ°„μ˜ 닀쀑 상속을 μ ˆλŒ€ ν—ˆμš©ν•˜μ§€ μ•ŠμŒ. 즉, class Child extends Father, Mother와 같이 두 개 μ΄μƒμ˜ λΆ€λͺ¨λ₯Ό λ™μ‹œμ— μ§€μ •ν•  수 μ—†μŒ.
  • 이유 (닀이아λͺ¬λ“œ 문제 λ°©μ§€): λ§Œμ•½ 두 λΆ€λͺ¨ ν΄λž˜μŠ€μ— 이름이 λ˜‘κ°™μ€ λ©”μ„œλ“œκ°€ μ‘΄μž¬ν•  경우, μžμ‹ 객체가 μ–΄λ–€ λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•΄μ•Ό ν• μ§€ 컴퓨터 μ‹œμŠ€ν…œμ΄ νŒλ‹¨ν•  수 μ—†λŠ” λͺ¨ν˜Έμ„±μ΄ λ°œμƒν•˜κΈ° λ•Œλ¬Έμž„.
  • ν•΄κ²°μ±…: 닀쀑 μƒμ†μ˜ 효과λ₯Ό λ‚΄κΈ° μœ„ν•΄ μžλ°”λŠ” μΈν„°νŽ˜μ΄μŠ€(Interface)λΌλŠ” 특수 ꡬ쑰λ₯Ό μ œκ³΅ν•¨.

β—† μƒμ„±μž 호좜 관계 νŒŒμ•…

μžμ‹ 객체λ₯Ό 생성할 λ•Œ, λ©”λͺ¨λ¦¬(Heap) λ‚΄λΆ€μ—μ„œλŠ” μžμ‹ 혼자 νƒœμ–΄λ‚˜μ§€ μ•ŠμŒ. λ°˜λ“œμ‹œ λΆ€λͺ¨ 객체가 λ¨Όμ € μƒμ„±λœ ν›„ μžμ‹ 객체가 κ·Έ 겉을 감싸며 κ²°ν•©ν•˜λŠ” μ•„ν‚€ν…μ²˜λ₯Ό 가짐.

  • μ‹€ν–‰ μˆœμ„œ: μžμ‹ μƒμ„±μžκ°€ 호좜되면, λ‚΄λΆ€μ μœΌλ‘œ λΆ€λͺ¨ μƒμ„±μžκ°€ λ¨Όμ € μ™„λ²½ν•˜κ²Œ 싀행을 끝낸 λ’€ μžμ‹ μƒμ„±μžμ˜ λ‚˜λ¨Έμ§€ λ³Έλ¬Έ μ½”λ“œκ°€ 가동됨.

β—† super() 와 super 의 차이점

이름은 λΉ„μŠ·ν•˜μ§€λ§Œ λ©”λͺ¨λ¦¬λ₯Ό μ œμ–΄ν•˜λŠ” μš©λ„κ°€ μ™„μ „νžˆ 닀름.

β‘  super() : λΆ€λͺ¨μ˜ μƒμ„±μž 호좜 λͺ…λ Ή

  • μžμ‹ μƒμ„±μž λ‚΄λΆ€μ—μ„œ λΆ€λͺ¨μ˜ μƒμ„±μžλ₯Ό κ°•μ œλ‘œ κ°€λ™μ‹œν‚€λŠ” λ©”μ„œλ“œ ν˜•νƒœμ˜ λͺ…λ Ήμ–΄μž„.
  • κ·œμΉ™: μžμ‹ μƒμ„±μž λ³Έλ¬Έμ—μ„œ λ°˜λ“œμ‹œ 첫 μ€„μ—λ§Œ μœ„μΉ˜ν•΄μ•Ό 함. μƒλž΅ν•˜λ©΄ μ»΄νŒŒμΌλŸ¬κ°€ λΆ€λͺ¨μ˜ κΈ°λ³Έ μƒμ„±μžλ₯Ό λΆ€λ₯΄λŠ” super();λ₯Ό μžλ™μœΌλ‘œ 맨 첫 쀄에 μ‚½μž…ν•¨.

β‘‘ super : λΆ€λͺ¨ 객체의 λ©”λͺ¨λ¦¬ μ£Όμ†Œλ‘(μ°Έμ‘° λ³€μˆ˜)

  • μžμ‹ 클래슀 λ‚΄λΆ€μ—μ„œ λ‚΄ λ³€μˆ˜μ™€ λΆ€λͺ¨μ˜ λ³€μˆ˜ 이름이 μ€‘λ³΅λ˜μ–΄ μΆ©λŒν•  λ•Œ, λΆ€λͺ¨μ˜ μžμ›μ„ 콕 μ§‘μ–΄μ„œ κ°€λ¦¬ν‚€λŠ” ν‚€μ›Œλ“œμž„.
  • thisκ°€ ν˜„μž¬ λ‚˜ μžμ‹ μ˜ λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό λœ»ν•œλ‹€λ©΄, superλŠ” λ‚΄ λΆ€λͺ¨ 방의 μ£Όμ†Œλ₯Ό μ˜λ―Έν•¨.

β—† 상속이 도움이 λ˜λŠ” μƒν™©μ˜ μ˜ˆμ‹œ

  • 상황: νšŒμ‚¬μ—μ„œ '정직원' 관리 ν”„λ‘œκ·Έλž¨κ³Ό 'μ•Œλ°”μƒ' 관리 ν”„λ‘œκ·Έλž¨μ„ λ”°λ‘œ ꡬ좕해야 ν•˜λŠ” 경우.
  • 상속 미적용 μ‹œ: 두 클래슀 λͺ¨λ‘μ— 이름, λ‚˜μ΄, μ‚¬μ›λ²ˆν˜Έ, μž…μ‚¬μΌ λ“± λ˜‘κ°™μ€ λ³€μˆ˜μ™€ 좜λ ₯ λ©”μ„œλ“œλ₯Ό μ€‘λ³΅ν•΄μ„œ 타이핑해야 함.
  • 상속 적용 μ‹œ: 곡톡 λΆ„λͺ¨μΈ '사원(Employee)' 클래슀λ₯Ό μœ„ μƒμœ„μ— μ •μ˜ν•˜κ³ , '정직원(Regular)'κ³Ό 'μ•Œλ°”μƒ(PartTime)'은 μƒμœ„ 클래슀λ₯Ό extends ν•œ λ’€ 각각 λ³΄λ„ˆμŠ€ κ³„μ‚°λ²•μ΄λ‚˜ μ‹œκΈ‰ 계산법 λ“± μžμ‹ λ§Œμ˜ 고유 μ°¨λ³„μ λ§Œ μ•„λž˜μ— μΆ”κ°€ κ΅¬ν˜„ν•˜λ©΄ 됨.

β—† λ‹¨μˆœ 인λ§₯ 관리 ν”„λ‘œκ·Έλž¨ 예제 (관리 λŒ€μƒμ΄ λ‘˜μΈ ꡬ쑰)

관리 λŒ€μƒμ΄ "동창(UnivFriend)"κ³Ό "직μž₯ λ™λ£Œ(CompanyFriend)" λ‘˜μΈ 경우의 μ•„ν‚€ν…μ²˜ 섀계 μ½”λ“œμž„. 곡톡 λ°μ΄ν„°λŠ” μƒμœ„ 클래슀(Friend)둜 λ¬Άκ³  상속을 톡해 κ΅¬ν˜„ν•¨.

1. 곡톡 μƒμœ„ 클래슀 μ •μ˜


 
// πŸ’‘ 곡톡 λΆ€λͺ¨ 클래슀
class Friend {
    protected String name; // μžμ‹ ν΄λž˜μŠ€μ—μ„œ 직접 μ ‘κ·Όν•  수 μžˆλ„λ‘ protected 배치
    protected String phone;

    public Friend(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public void showInfo() {
        System.out.println("이름: " + name);
        System.out.println("μ „ν™”: " + phone);
    }
}

2. 두 개의 μžμ‹ 클래슀 λŒ€μƒ μ •μ˜ 및 상속 κ΅¬ν˜„ μ½”λ“œ

 
// πŸ’‘ 관리 λŒ€μƒ 1: λŒ€ν•™κ΅ 동창 클래슀
class UnivFriend extends Friend {
    private String major; // λ™μ°½λ§Œμ˜ 고유 νŠΉμ„± (전곡)

    public UnivFriend(String name, String phone, String major) {
        super(name, phone); // πŸ’‘ super()λ₯Ό 톡해 λΆ€λͺ¨ μƒμ„±μžμ— 이름과 μ „ν™”λ²ˆν˜Έ 재료 전달
        this.major = major;
    }

    @Override
    public void showInfo() {
        super.showInfo(); // πŸ’‘ super ν‚€μ›Œλ“œλ‘œ λΆ€λͺ¨μ˜ 좜λ ₯ κΈ°λŠ₯ λ¨Όμ € 가동
        System.out.println("전곡: " + major);
    }
}

// πŸ’‘ 관리 λŒ€μƒ 2: 직μž₯ λ™λ£Œ 클래슀
class CompanyFriend extends Friend {
    private String department; // 직μž₯ λ™λ£Œλ§Œμ˜ 고유 νŠΉμ„± (λΆ€μ„œ)

    public CompanyFriend(String name, String phone, String department) {
        super(name, phone); // λΆ€λͺ¨ μƒμ„±μž 호좜
        this.department = department;
    }

    @Override
    public void showInfo() {
        super.showInfo(); // λΆ€λͺ¨μ˜ 곡톡 정보 좜λ ₯ ν™œμš©
        System.out.println("λΆ€μ„œ: " + department);
    }
}

3. 메인 μ‹€ν–‰ 및 μ œμ–΄ μ½”λ“œ


 
public class Main {
    public static void main(String[] args) {
        // 동창 객체와 직μž₯ λ™λ£Œ 객체 각각 생성 (Heap λ©”λͺ¨λ¦¬μ— λΆ€λͺ¨ 곡간과 ν•¨κ»˜ 배치됨)
        UnivFriend uFriend = new UnivFriend("홍길동", "010-1111-2222", "컴퓨터곡학");
        CompanyFriend cFriend = new CompanyFriend("μ΄μˆœμ‹ ", "010-3333-4444", "κ°œλ°œνŒ€");

        System.out.println("--- 동창 정보 좜λ ₯ ---");
        uFriend.showInfo();

        System.out.println("\n--- 직μž₯ λ™λ£Œ 정보 좜λ ₯ ---");
        cFriend.showInfo();
    }
}

 

β—† 1. static μžμ›λ„ 상속이 λ˜λŠ”κ°€?

κ²°λ‘ λΆ€ν„° λ§ν•˜λ©΄, static λ³€μˆ˜μ™€ static λ©”μ„œλ“œλ„ μžμ‹ ν΄λž˜μŠ€μ—κ²Œ 상속됨.

  • 원리: λΆ€λͺ¨ ν΄λž˜μŠ€μ— static으둜 μ„ μ–Έλœ μžμ›μ€ μžμ‹ 클래슀 이름을 ν†΅ν•΄μ„œλ„ κ·ΈλŒ€λ‘œ μ ‘κ·Όν•˜κ³  μ‚¬μš©ν•  수 있음.
  • μ½”λ“œ μ˜ˆμ‹œ:
  • Java
     
    class Parent {
        static int sharedVal = 100;
        static void staticMethod() {
            System.out.println("λΆ€λͺ¨μ˜ μŠ€νƒœν‹± λ©”μ„œλ“œ");
        }
    }
    
    class Child extends Parent {
        // 아무것도 적지 μ•Šμ•„λ„ λΆ€λͺ¨μ˜ static μžμ›μ„ λ¬Όλ €λ°›μŒ
    }
    
    public class Main {
        public static void main(String[] args) {
            // πŸ’‘ μžμ‹ 클래슀 이름을 톡해 λΆ€λͺ¨μ˜ static μžμ›μ— μ ‘κ·Ό κ°€λŠ₯
            System.out.println(Child.sharedVal); // 좜λ ₯: 100
            Child.staticMethod();                // 좜λ ₯: λΆ€λͺ¨μ˜ μŠ€νƒœν‹± λ©”μ„œλ“œ
        }
    }
    

β—† 2. λ©”λͺ¨λ¦¬ μ•„ν‚€ν…μ²˜λ‘œ λ³΄λŠ” μƒμ†μ˜ μ§„μ‹€: "곡유"

상속이라고 ν•˜λ©΄ λΆ€λͺ¨μ˜ 곡간을 μžμ‹μ΄ λ³΅μ‚¬ν•΄μ„œ μ†Œμœ ν•˜λŠ” κ²ƒμ²˜λŸΌ λŠκ»΄μ§€μ§€λ§Œ, static은 μ™„μ „νžˆ λ‹€λ₯΄κ²Œ μž‘λ™ν•¨.

  • μΈμŠ€ν„΄μŠ€ λ³€μˆ˜ 상속: μžμ‹ 객체λ₯Ό new둜 생성할 λ•Œλ§ˆλ‹€ νž™(Heap) μ˜μ—­μ— λΆ€λͺ¨μ˜ λ³€μˆ˜ 곡간과 μžμ‹μ˜ λ³€μˆ˜ 곡간이 각각 μƒˆλ‘­κ²Œ 파짐.
  • static 자수 상속: static λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€(객체)에 μ†ν•˜μ§€ μ•Šκ³  였직 Static(Method) μ˜μ—­μ— 단 ν•œ 개만 생성됨. μžμ‹ ν΄λž˜μŠ€κ°€ 이λ₯Ό μƒμ†λ°›λŠ”λ‹€λŠ” 것은, μƒˆλ‘œμš΄ μƒμžκ°€ μƒκΈ°λŠ” 것이 μ•„λ‹ˆλΌ Static μ˜μ—­μ— μ‘΄μž¬ν•˜λŠ” ν•˜λ‚˜μ˜ λ˜‘κ°™μ€ μƒμžλ₯Ό λΆ€λͺ¨μ™€ μžμ‹μ΄ '곡유'ν•˜λŠ” κ΅¬μ‘°μž„.
  • μ½”λ“œ 증λͺ… μ˜ˆμ‹œ:
  • Java
     
    Child.sharedVal = 500; // μžμ‹ μͺ½μ—μ„œ static λ³€μˆ˜ 값을 λ°”κΏˆ
    System.out.println(Parent.sharedVal); // πŸ’‘ 좜λ ₯: 500 (λΆ€λͺ¨ μͺ½ 값도 λ°”λ€œ, κ²°κ΅­ 같은 μƒμžμ΄κΈ° λ•Œλ¬Έ)
    

β—† 3. ⚠️ static λ©”μ„œλ“œλŠ” μ˜€λ²„λΌμ΄λ”©(Overriding)이 λΆˆκ°€λŠ₯ν•˜λ‹€

μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλŠ” λΆ€λͺ¨μ˜ 것을 μžμ‹μ΄ μž¬μ •μ˜(Overriding)ν•˜μ—¬ λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•  수 있음. ν•˜μ§€λ§Œ static λ©”μ„œλ“œλŠ” μ˜€λ²„λΌμ΄λ”© κ·œμΉ™μ΄ μ μš©λ˜μ§€ μ•ŠμŒ.

μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨μ˜ static λ©”μ„œλ“œμ™€ μ™„μ „νžˆ λ˜‘κ°™μ€ 이름과 ν˜•νƒœλ‘œ λ©”μ„œλ“œλ₯Ό λ‹€μ‹œ μ •μ˜ν•˜λ©΄, μ˜€λ²„λΌμ΄λ”©λœ 것이 μ•„λ‹ˆλΌ 'λ©”μ„œλ“œ μˆ¨κΉ€(Method Hiding)' ν˜„μƒμ΄ λ°œμƒν•¨.

❌ 잘λͺ»λœ μ˜€λ²„λΌμ΄λ”© 이해와 'λ©”μ„œλ“œ μˆ¨κΉ€' μ˜ˆμ‹œ

Java
 
class SuperClass {
    static void print() {
        System.out.println("λΆ€λͺ¨ μŠ€νƒœν‹±");
    }
}

class SubClass extends SuperClass {
    // @Override ❌ μ—λŸ¬ λ°œμƒ: μŠ€νƒœν‹± λ©”μ„œλ“œμ—λŠ” μ˜€λ²„λΌμ΄λ”© 마크λ₯Ό 뢙일 수 μ—†μŒ
    static void print() {
        System.out.println("μžμ‹ μŠ€νƒœν‹±"); // λΆ€λͺ¨ λ©”μ„œλ“œλ₯Ό 가렀버림(Hiding)
    }
}

public class Main {
    public static void main(String[] args) {
        SuperClass sub = new SubClass(); // λ‹€ν˜•μ„± ꡬ쑰둜 객체 생성
        sub.print(); // πŸ’‘ 좜λ ₯ κ²°κ³Ό: "λΆ€λͺ¨ μŠ€νƒœν‹±"
    }
}
  • 이유 (컴파일 νƒ€μž„ 바인딩): 일반 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλŠ” ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 도쀑(Runtime)에 μ§„μ§œ νž™μ— μžˆλŠ” 객체가 무엇인지 ν™•μΈν•˜κ³  λ©”μ„œλ“œλ₯Ό 찾아감. 반면, static λ©”μ„œλ“œλŠ” μ‹€ν–‰λ˜κΈ°λ„ 전인 컴파일 μ‹œμ μ— μ°Έμ‘° λ³€μˆ˜μ˜ 'νƒ€μž…'만 보고 μ‹€ν–‰ν•  λ©”μ„œλ“œλ₯Ό 미리 κ²°μ •ν•΄ 버림. μœ„ μ½”λ“œμ—μ„œ sub λ³€μˆ˜μ˜ νƒ€μž…μ΄ SuperClass이기 λ•Œλ¬Έμ— μ‹€μ œ μ•Œλ§Ήμ΄κ°€ SubClass일지라도 λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•΄ λ²„λ¦¬λŠ” κ²ƒμž„.

β—† μ΅œμ’… μš”μ•½

  • λΆ€λͺ¨μ˜ static λ³€μˆ˜μ™€ λ©”μ„œλ“œλŠ” μžμ‹μ—κ²Œ μƒμ†λ˜μ–΄ μžμ‹ μ΄λ¦„μœΌλ‘œ μ‚¬μš© κ°€λŠ₯함.
  • 물리적으둜 λ³΅μ‚¬λ˜λŠ” 것이 μ•„λ‹ˆλΌ Static μ˜μ—­μ˜ 단 ν•˜λ‚˜μ˜ μžμ›μ„ λΆ€λͺ¨μ™€ μžμ‹μ΄ κ³΅μœ ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μž„.
  • static λ©”μ„œλ“œλŠ” μ‹€ν–‰ μ‹œμ μ΄ μ•„λ‹Œ 컴파일 μ‹œμ μ— κ²°ν•©ν•˜λ―€λ‘œ μ˜€λ²„λΌμ΄λ”©(λ‹€ν˜•μ„±)이 λΆˆκ°€λŠ₯ν•˜λ©°, λ˜‘κ°™μ΄ λ§Œλ“€ 경우 λ‹¨μˆœνžˆ λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό κ°€λ¦¬λŠ” 'λ©”μ„œλ“œ μˆ¨κΉ€(Hiding)'이 일어남.

 

β—† ν”„λ‘œκ·Έλž¨ 였λ₯˜ (Error)의 μ’…λ₯˜

컴퓨터 ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” κ³Όμ •μ—μ„œ λ°œμƒν•˜λŠ” 였λ₯˜λŠ” λ°œμƒ μ‹œμ κ³Ό 성격에 따라 3κ°€μ§€λ‘œ λΆ„λ₯˜λ¨.

  • 컴파일 였λ₯˜ (Compile-time Error): μ†ŒμŠ€ μ½”λ“œμ˜ 문법이 ν‹€λ € μžλ°” 컴파일러(javac)κ°€ μ‹€ν–‰ 파일(.class)을 λ§Œλ“€μ§€ λͺ»ν•˜κ³  λΉ¨κ°„ 쀄을 λ„μš°λŠ” 였λ₯˜μž„. κ°€μž₯ μ•ˆμ „ν•˜κ³  λ°œκ²¬ν•˜κΈ° 쉬움.
  • 논리적 였λ₯˜ (Logical Error): μ»΄νŒŒμΌλ„ 잘 되고 ν”„λ‘œκ·Έλž¨λ„ λ©ˆμΆ”μ§€ μ•Šκ³  μ‹€ν–‰λ˜μ§€λ§Œ, 개발자의 계산 μ‹€μˆ˜ λ“±μœΌλ‘œ 인해 μ›ν•˜λŠ” κ²°κ³Όκ°€ λ‚˜μ˜€μ§€ μ•ŠλŠ” 였λ₯˜μž„ (예: λ§μ…ˆ 연산에 λΊ„μ…ˆ 기호λ₯Ό λ„£μŒ).
  • λŸ°νƒ€μž„ 였λ₯˜ (Runtime Error): μ»΄νŒŒμΌμ€ μ™„λ²½νžˆ λλ‚¬μœΌλ‚˜, ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” 도쀑(Runtime) μ˜ˆμΈ‘ν•˜μ§€ λͺ»ν•œ 상황을 λ§Œλ‚˜ κ°•μ œλ‘œ κ³ μž₯ λ‚˜λŠ” 였λ₯˜μž„. μ˜ˆμ™Έ μ²˜λ¦¬λŠ” λ°”λ‘œ 이 λŸ°νƒ€μž„ 였λ₯˜λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•¨.

β—† 였λ₯˜ μ’…λ£Œμ™€ ν•΄κ²° 방법

  • 였λ₯˜ μ’…λ£Œ (Abnormal Termination): λŸ°νƒ€μž„ 였λ₯˜κ°€ λ°œμƒν•˜λ©΄ μžλ°” 가상 λ¨Έμ‹ (JVM)은 μ¦‰μ‹œ ꡬ동을 μ€‘λ‹¨ν•˜κ³  μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό μŸμ•„λ‚΄λ©° ν”„λ‘œκ·Έλž¨μ„ κ°•μ œ μ’…λ£Œμ‹œν‚΄. μ›Ή μ„œλ²„λ‚˜ 금육 ν”„λ‘œκ·Έλž¨μ˜ 경우 μ‹œμŠ€ν…œ 전체가 λ§ˆλΉ„λ˜λŠ” 치λͺ…적인 κ²°κ³Όλ₯Ό μ΄ˆλž˜ν•¨.
  • ν•΄κ²° 방법 (μ˜ˆμ™Έ 처리 - Exception Handling): ν”„λ‘œκ·Έλž¨μ΄ κΈ‰μž‘μŠ€λŸ½κ²Œ μ£½λŠ” 것을 막고, 였λ₯˜κ°€ λ°œμƒν–ˆμ„ λ•Œ 우회 λ„λ‘œλ₯Ό κ°œμ„€ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ„ λκΉŒμ§€ 정상 μ‹€ν–‰μ‹œν‚€λ„λ‘ μ œμ–΄ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μž„. μžλ°”μ—μ„œλŠ” try - catch - finally 블둝을 μ•„ν‚€ν…μ²˜λ‘œ μ‚¬μš©ν•¨.
     
    try {
        // πŸ’‘ μ˜ˆμ™Έκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλŠ” μœ„ν—˜ν•œ μ½”λ“œ 배치
        int result = 10 / 0; 
    } catch (ArithmeticException e) {
        // πŸ’‘ μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μ‹€ν–‰ν•  수슡용 우회 μ½”λ“œ 배치
        System.out.println("0으둜 λ‚˜λˆŒ 수 μ—†μŠ΅λ‹ˆλ‹€. κΈ°λ³Έκ°’μœΌλ‘œ λŒ€μ²΄ν•©λ‹ˆλ‹€.");
    } finally {
        // πŸ’‘ μ˜ˆμ™Έ λ°œμƒ 여뢀와 상관없이 무쑰건 λ§ˆμ§€λ§‰μ— μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜λŠ” 정리 μ½”λ“œ (μžμ› ν•΄μ œ λ“±)
    }
    

β—† μ˜ˆμ™Έ 클래슀의 계측 ꡬ쑰

μžλ°”λŠ” ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑 λ°œμƒν•  수 μžˆλŠ” λͺ¨λ“  였λ₯˜ 상황을 '객체'둜 λ§Œλ“€μ–΄μ„œ 관리함. λ”°λΌμ„œ 였λ₯˜λ„ λΆ€λͺ¨-μžμ‹ 상속 ꡬ쑰λ₯Ό 가짐.

  • Throwable : μžλ°”μ—μ„œ 였λ₯˜λ‘œ 던져질 수 μžˆλŠ” λͺ¨λ“  클래슀의 μ΅œμƒμœ„ μ‘°μƒμž„.
  • Error 후손: μ‹œμŠ€ν…œ λ©”λͺ¨λ¦¬ λΆ€μ‘±(OutOfMemoryError)μ΄λ‚˜ ν•˜λ“œμ›¨μ–΄ κ³ μž₯ λ“± ν”„λ‘œκ·Έλž¨ μ½”λ“œλ‘œ μˆ˜μŠ΅ν•  수 μ—†λŠ” μ‹¬κ°ν•œ ꡬ쑰적 였λ₯˜μž„. κ°œλ°œμžκ°€ μ½”λ“œλ‘œ μž‘μ„ 수 μ—†μŒ.
  • Exception 후손: κ°œλ°œμžκ°€ λ°œμƒμ„ μ˜ˆμΈ‘ν•˜κ³  μ½”λ“œλ₯Ό 톡해 정상 μƒνƒœλ‘œ μˆ˜μŠ΅ν•  수 μžˆλŠ” κ°€λ²Όμš΄ 였λ₯˜μž„. μ˜ˆμ™Έ 처리의 직접적인 λŒ€μƒμž„.
    • Checked Exception: RuntimeException을 상속받지 μ•Šμ€ μ˜ˆμ™Έλ“€. μ»΄νŒŒμΌλŸ¬κ°€ μ˜ˆμ™Έ 처리λ₯Ό 무쑰건 λͺ…μ‹œν•˜λΌκ³  κ°•μ œν•¨. μ•ˆ 적으면 컴파일(λΉ¨κ°„ 쀄) μžμ²΄κ°€ μ•ˆ 됨 (예: IOException, SQLException).
    • Unchecked Exception: RuntimeExceptionκ³Ό κ·Έ μžμ‹λ“€. μ»΄νŒŒμΌλŸ¬κ°€ κ°•μ œν•˜μ§€ μ•Šμ•„ 개발자의 주의λ ₯에 μ˜μ‘΄ν•¨.

β—† RuntimeException (Unchecked Exception)

μ˜ˆμ™Έ 계측 ꡬ쑰 쀑 κ°€μž₯ λ…νŠΉν•˜κ³  λΉˆλ²ˆν•˜κ²Œ λ§Œλ‚˜λŠ” μ˜μ—­μž„.

  • νŠΉμ§•: 주둜 개발자의 논리적 였λ₯˜λ‚˜ μ½”λ”© μ‹€μˆ˜(주의 λΆ€μ‘±)둜 인해 λ°œμƒν•˜λŠ” μ˜ˆμ™Έλ“€μ„ λͺ¨μ•„놓은 ν΄λž˜μŠ€μž„.
  • λ§€μ»€λ‹ˆμ¦˜: μ»΄νŒŒμΌλŸ¬κ°€ 수슡 μ½”λ“œλ₯Ό μ μ—ˆλŠ”μ§€ κ°μ‹œν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—(try-catchλ₯Ό μ•ˆ 써도 μ»΄νŒŒμΌμ€ 톡과됨) ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ μ „κΉŒμ§€ 였λ₯˜λ₯Ό μΈμ§€ν•˜κΈ° 어렀움. μ² μ €ν•œ μ½”λ“œ 검증과 μ˜ˆμ™Έ μ²˜λ¦¬κ°€ λ™λ°˜λ˜μ–΄μ•Ό 함.
  • λŒ€ν‘œμ μΈ μžμ‹ ν΄λž˜μŠ€λ“€:
    • NullPointerException : 객체 μ£Όμ†Œλ‘μ΄ λΉ„μ–΄μžˆλŠ” μƒνƒœ(null)인데 κ·Έ μ•ˆμ˜ λ³€μˆ˜λ‚˜ λ©”μ„œλ“œλ₯Ό μ°Έμ‘°ν•˜λ €κ³  μ ‘κ·Όν•  λ•Œ λ°œμƒν•¨.
    • ArrayIndexOutOfBoundsException : λ°°μ—΄μ˜ 크기가 5인데 6번 인덱슀 칸을 열어달라고 μš”μ²­ν•  λ•Œ λ°œμƒν•¨.
    • ArithmeticException : μ •μˆ˜λ₯Ό 0으둜 λ‚˜λˆ„λŠ” λ“± μˆ˜ν•™μ μœΌλ‘œ λΆˆκ°€λŠ₯ν•œ 연산을 λͺ…λ Ήν•  λ•Œ λ°œμƒν•¨.

β—† Java API Document ν™•μΈν•˜λŠ” μ˜ˆμ‹œ

λ‚΄κ°€ μ“°λ €λŠ” μžλ°” ν‘œμ€€ λ©”μ„œλ“œκ°€ μ–΄λ–€ μ˜ˆμ™Έλ₯Ό λ˜μ§€λŠ”μ§€ μ•Œκ³  싢을 λ•Œ 곡식 API λ¬Έμ„œλ₯Ό ν™•μΈν•˜λŠ” λ°©λ²•μž„. (주둜 였라클 곡식 μ‚¬μ΄νŠΈμ˜ μžλ°” API λ¬Έμ„œλ₯Ό 기쀀함)

  • 상황: λ¬Έμžμ—΄μ„ μ •μˆ˜λ‘œ λ°”κΏ”μ£ΌλŠ” Integer.parseInt(String s) λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ €λŠ” 경우.
  • 확인 μˆœμ„œ:
      1. λ¬Έμ„œ 검색창에 Integer 클래슀λ₯Ό μ°Ύκ³ , λ©”μ„œλ“œ 리슀트 쀑 parseInt(String s) λͺ…μ„Έμ„œλ₯Ό 찾음.
      1. λ©”μ„œλ“œ μ„ μ–ΈλΆ€ ν•˜λ‹¨μ˜ "Throws" ν•­λͺ©μ„ μ •λ°€ 확인해야 함.
      1. λ¬Έμ„œλ₯Ό 보면 Throws: NumberFormatException 이라고 λͺ…μ‹œλ˜μ–΄ 있음. κ·Έ μ˜†μ˜ μ„€λͺ…을 읽어보면 *"λ¬Έμžμ—΄μ΄ μ •μˆ˜λ‘œ λ³€ν™˜λ  수 μžˆλŠ” ν˜•νƒœκ°€ 아닐 λ•Œ λ°œμƒν•œλ‹€"*κ³  μ ν˜€ 있음.
      1. κ²°κ³Ό λ§€ν•‘: κ°œλ°œμžλŠ” 이 λͺ…μ„Έλ₯Ό 보고 μ•„λž˜μ™€ 같이 λ°©μ–΄ μ½”λ“œλ₯Ό μ•„ν‚€ν…μ²˜μ— 미리 μ‹¬μ–΄λ‘˜ 수 있음.

     
    String input = "123abc"; // μˆ«μžκ°€ μ•„λ‹Œ λ¬Έμžκ°€ μ„žμž„
    
    try {
        int num = Integer.parseInt(input); // πŸ’‘ Throws λͺ…세에 μ νžŒλŒ€λ‘œ NumberFormatException λ°œμƒν•¨
    } catch (NumberFormatException e) {
        System.out.println("숫자 포맷이 잘λͺ»λ˜μ–΄ κΈ°λ³Έκ°’ 0으둜 μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.");
    }

μžλ°”(Java)μ—μ„œ μ˜ˆμ™Έλ₯Ό μˆ˜μŠ΅ν•˜λŠ” 핡심 도ꡬ인 try - catch 문에 λŒ€ν•œ ꡬ동 원리와 λ§€μ»€λ‹ˆμ¦˜ μ€‘μ‹¬μ˜ μ •λ¦¬μž„.

β—† try - catch 문의 μ •μ˜μ™€ κΈ°λŠ₯

  • μ •μ˜: ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑 λ°œμƒν•  수 μžˆλŠ” λŸ°νƒ€μž„ μ˜ˆμ™Έ(였λ₯˜)λ₯Ό κ°€λ‘œμ±„μ„œ, ν”„λ‘œκ·Έλž¨μ΄ λΉ„μ •μƒμ μœΌλ‘œ μ£½μ§€ μ•Šλ„λ‘ 방어막을 μΉ˜λŠ” μ œμ–΄λ¬Έμž„.
  • κΈ°λŠ₯: μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ ν”„λ‘œκ·Έλž¨μ˜ κ°•μ œ μ’…λ£Œλ₯Ό 막고, κ°œλ°œμžκ°€ 미리 μ€€λΉ„ν•œ 우회 λ„λ‘œ(λŒ€λΉ„μ±…)λ₯Ό 따라 정상적인 μ‹€ν–‰ 흐름을 μœ μ§€μ‹œν‚΅λ‹ˆλ‹€.

β—† try - catch κΈ°λ³Έ ꡬ쑰 및 λ§€μ»€λ‹ˆμ¦˜

  • try 블둝: μ˜ˆμ™Έ(였λ₯˜)κ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλŠ” μœ„ν—˜ν•œ μ½”λ“œλ₯Ό λͺ¨μ•„λ‘λŠ” κ³΅κ°„μž„.
  • catch 블둝: try 블둝 μ•ˆμ—μ„œ μ§„μ§œλ‘œ μ˜ˆμ™Έκ°€ ν„°μ‘Œμ„ λ•Œλ§Œ κ°€λ™λ˜λŠ” 비상 수슡 κ³΅κ°„μž„. κ΄„ν˜Έ () μ•ˆμ— μˆ˜μŠ΅ν•˜κ³ μž ν•˜λŠ” μ˜ˆμ™Έ 객체의 νƒ€μž…μ„ λͺ…μ‹œν•΄μ•Ό 함.

β—† μ˜ˆμ™Έ λ°œμƒ μ‹œλ‚˜λ¦¬μ˜€λ³„ ꡬ동 흐름

μ‹œλ‚˜λ¦¬μ˜€ β‘ : try 블둝 λ‚΄μ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•œ 경우 (비상 상황)

    1. try 블둝을 μœ„μ—μ„œλΆ€ν„° ν•œ 쀄씩 μ‹€ν–‰ν•˜λ‹€κ°€ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λŠ” μˆœκ°„, κ·Έ μ¦‰μ‹œ 싀행을 쀑단함 (밑에 남은 μ½”λ“œλŠ” λ¬΄μ‹œλ¨).
    1. λ°œμƒν•œ μ˜ˆμ™Έ 객체와 μΌμΉ˜ν•˜λŠ” νƒ€μž…μ„ κ°€μ§„ catch 블둝이 μžˆλŠ”μ§€ μœ„μ—μ„œλΆ€ν„° μ°¨λ‘€λ‘œ 검사함.
    1. μΌμΉ˜ν•˜λŠ” catch 블둝을 찾으면 κ·Έ λ‚΄λΆ€ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜μ—¬ 상황을 μˆ˜μŠ΅ν•¨.
    1. try-catch 전체 문을 λΉ μ Έλ‚˜κ°€ κ·Έ λ‹€μŒ μ€„μ˜ μ½”λ“œλ₯Ό μ •μƒμ μœΌλ‘œ μ΄μ–΄μ„œ 싀행함.

μ‹œλ‚˜λ¦¬μ˜€ β‘‘: try 블둝 λ‚΄μ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•Šμ€ 경우 (평화 상황)

    1. try 블둝 μ•ˆμ˜ λͺ¨λ“  μ½”λ“œκ°€ μ •μƒμ μœΌλ‘œ λκΉŒμ§€ 싀행됨.
    1. catch 블둝은 μ‹€ν–‰λ˜μ§€ μ•Šκ³  ν†΅μ§Έλ‘œ 패슀됨.
    1. try-catch 전체 λ¬Έ μ•„λž˜μ˜ μ½”λ“œλ₯Ό μ΄μ–΄μ„œ 싀행함.
    2.  

β—† 싀무 μ½”λ“œ μ˜ˆμ‹œ

❌ μ˜ˆμ™Έ 처리λ₯Ό ν•˜μ§€ μ•Šμ•„ ν”„λ‘œκ·Έλž¨μ΄ 도쀑에 μ£½λŠ” 경우


 
public class Main {
    public static void main(String[] args) {
        System.out.println("ν”„λ‘œκ·Έλž¨ μ‹œμž‘");
        
        int sVal = 10 / 0; // πŸ’₯ λŸ°νƒ€μž„ μ—λŸ¬ λ°œμƒ (ArithmeticException)
        
        // μ—λŸ¬ λ°œμƒμœΌλ‘œ 인해 μ•„λž˜ μ½”λ“œλŠ” μ‹€ν–‰λ˜μ§€ λͺ»ν•˜κ³  κ°•μ œ μ’…λ£Œλ¨
        System.out.println("μ—°μ‚° κ²°κ³Ό: " + sVal); 
        System.out.println("ν”„λ‘œκ·Έλž¨ 정상 μ’…λ£Œ");
    }
}

β­• try - catch 둜 μ˜ˆμ™Έλ₯Ό μˆ˜μŠ΅ν•˜μ—¬ μ•ˆμ „ν•˜κ²Œ μ‹€ν–‰ν•˜λŠ” 경우

Java
 
public class Main {
    public static void main(String[] args) {
        System.out.println("ν”„λ‘œκ·Έλž¨ μ‹œμž‘");

        try {
            System.out.println("πŸ’‘ [try] 연산을 μ‹œλ„ν•©λ‹ˆλ‹€.");
            int sVal = 10 / 0; // πŸ’₯ μ—¬κΈ°μ„œ μ˜ˆμ™Έ λ°œμƒ! μ¦‰μ‹œ catch λΈ”λ‘μœΌλ‘œ μˆœκ°„μ΄λ™ν•¨
            
            System.out.println("[try] 이 μ½”λ“œλŠ” μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€."); 
        } catch (ArithmeticException e) {
            // 🚨 수슡 가동
            System.out.println("⚠️ [catch] μ—λŸ¬ λ°œμƒ: 0으둜 λ‚˜λˆŒ 수 μ—†μ–΄ κ²°κ³Όλ₯Ό 0으둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.");
        }

        // πŸ’‘ 수슡이 μ™„λ£Œλ˜μ—ˆμœΌλ―€λ‘œ μ•„λž˜ μ½”λ“œκ°€ 정상 싀행됨
        System.out.println("ν”„λ‘œκ·Έλž¨ 정상 μ’…λ£Œ");
    }
}

β—† 닀쀑 catch 블둝 ν™œμš© κ·œμΉ™ (상속 계측 κ³ λ €)

ν•˜λ‚˜μ˜ try 블둝 μ•ˆμ—μ„œ μ—¬λŸ¬ μ’…λ₯˜μ˜ μ˜ˆμ™Έκ°€ λ°œμƒν•  수 μžˆλ‹€λ©΄, catch 블둝을 μ•„λž˜λ‘œ μ—¬λŸ¬ 개 덧뢙여 닀쀑 방어벽을 μ„ΈμšΈ 수 있음.

μ΄λ•Œ λΆ€λͺ¨-μžμ‹ 상속 계측에 따라 μžμ‹ μ˜ˆμ™Έ 클래슀λ₯Ό 무쑰건 μƒμœ„μ—, λΆ€λͺ¨ μ˜ˆμ™Έ 클래슀λ₯Ό ν•˜μœ„μ— λ°°μΉ˜ν•΄μ•Ό 함.

 
try {
    int[] arr = new int[3];
    arr[5] = 100; // πŸ’₯ ArrayIndexOutOfBoundsException λ°œμƒ κ°€λŠ₯μ„±
    
    int num = Integer.parseInt("abc"); // πŸ’₯ NumberFormatException λ°œμƒ κ°€λŠ₯μ„±
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("λ°°μ—΄ 인덱슀 λ²”μœ„λ₯Ό λ²—μ–΄λ‚¬μŠ΅λ‹ˆλ‹€.");
} catch (NumberFormatException e) {
    System.out.println("숫자둜 λ°”κΏ€ 수 μ—†λŠ” λ¬Έμžμ—΄μž…λ‹ˆλ‹€.");
} catch (Exception e) {
    // πŸ’‘ λͺ¨λ“  μ˜ˆμ™Έμ˜ 쑰상인 Exception은 맨 λ§ˆμ§€λ§‰μ— λ°°μΉ˜ν•˜μ—¬
    // μœ„μ—μ„œ κ±ΈλŸ¬μ§€μ§€ μ•Šμ€ μ˜ˆμƒμΉ˜ λͺ»ν•œ λͺ¨λ“  μ˜ˆμ™Έλ₯Ό μ΅œμ’… μˆ˜μŠ΅ν•˜λŠ” μ•ˆμ „μž₯치둜 씀
    System.out.println("μ•Œ 수 μ—†λŠ” μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.");
}

 

 

μžλ°”(Java)μ—μ„œ λͺ¨λ“  μ˜ˆμ™Έμ™€ 였λ₯˜μ˜ μ‹œμ‘°μ΄μž μ΅œμƒμœ„ κ°€λ¦¬ν‚€λŠ” 섀계도가 λ°”λ‘œ Throwable ν΄λž˜μŠ€μž„.

μžλ°” ν”„λ‘œκ·Έλž¨μ—μ„œ throw ν‚€μ›Œλ“œλ₯Ό 톡해 던져질 수 μžˆλŠ”(Throwable) λͺ¨λ“  κ°μ²΄λŠ” λ°˜λ“œμ‹œ 이 클래슀λ₯Ό 상속받아야 λ©”λͺ¨λ¦¬ μ•„ν‚€ν…μ²˜ μƒμ—μ„œ μ˜ˆμ™Έ μ‹œμŠ€ν…œμœΌλ‘œ 인식됨.

β—† 1. Throwable 클래슀의 계측적 μœ„μΉ˜

μžλ°”μ˜ λͺ¨λ“  객체의 쑰상인 Object λ°”λ‘œ μ•„λž˜μ— μœ„μΉ˜ν•˜λ©°, μžμ‹μœΌλ‘œ Error와 Exception 두 개의 κ±°λŒ€ν•œ κΈ°λ‘₯을 거느리고 있음.

  • java.lang.Object (μ΅œμƒμœ„ 객체)
    • └── java.lang.Throwable (λͺ¨λ“  μ˜ˆμ™Έ/였λ₯˜μ˜ μ‹œμ‘°)
      • β”œβ”€β”€ java.lang.Error (λŒ€ν˜• 사고: μ½”λ“œλ‘œ 수슡 λΆˆκ°€)
      • └── java.lang.Exception (일반 μ˜ˆμ™Έ: μ½”λ“œλ‘œ 수슡 κ°€λŠ₯)

β—† 2. 두 μ’…λ₯˜μ˜ 후손(μžμ‹) ꡬ별 핡심

Throwable을 상속받은 μžμ‹λ“€μ€ 성격이 μ™„μ „νžˆ κ·Ήλ‹¨μ μœΌλ‘œ λ‚˜λ‰¨.

  • Error 계열: JVM λ‚΄λΆ€ λ©”λͺ¨λ¦¬ 고갈(OutOfMemoryError), μŠ€νƒ 곡간 μ˜€λ²„ν”Œλ‘œμš°(StackOverflowError) λ“± μ‹œμŠ€ν…œ λ‹¨μœ„μ˜ 치λͺ…적인 κ²°ν•¨μž„. κ°œλ°œμžκ°€ μ½”λ“œ μˆ˜μ€€μ—μ„œ try-catch둜 κ°€λ‘œμ±„μ„œ μˆ˜μŠ΅ν•  수 μ—†μœΌλ―€λ‘œ 무쑰건 ν”„λ‘œκ·Έλž¨μ΄ 죽음.
  • Exception 계열: 개발자의 μ‹€μˆ˜λ‚˜ μ‚¬μš©μžμ˜ 잘λͺ»λœ μ‘°μž‘μœΌλ‘œ 인해 μΌμ–΄λ‚˜λŠ” κ°€λ²Όμš΄ 였λ₯˜ μƒν™©μž„. 예츑이 κ°€λŠ₯ν•˜λ―€λ‘œ try-catch둜 μž‘μ•„λ‚΄μ–΄ 우회 λ„λ‘œλ₯Ό κ°œμ„€(수슡)ν•  수 있음.

β—† 3. Throwable 클래슀의 핡심 λ‚΄μž₯ λ©”μ„œλ“œ κΈ°λŠ₯

Throwable ν΄λž˜μŠ€λŠ” μžμ‹λ“€μ—κ²Œ μ˜ˆμ™Έκ°€ λ°œμƒν•œ 상세 원인과 경둜λ₯Ό 좔적할 수 μžˆλŠ” κ°•λ ₯ν•œ 핡심 λ©”μ„œλ“œλ“€μ„ 물렀쀌. κ°œλ°œμžκ°€ μ˜ˆμ™Έ 처리λ₯Ό ν•  λ•Œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” κΈ°λŠ₯λ“€μž„.

β‘  getMessage() : μ—λŸ¬ λ©”μ‹œμ§€ λ°˜ν™˜

  • μ˜ˆμ™Έ 객체 내뢀에 μ €μž₯된 λ°œμƒ 원인에 λŒ€ν•œ 핡심 μš”μ•½ ν•œ 쀄 μ½”λ©˜νŠΈ(λ¬Έμžμ—΄)λ₯Ό 리턴함.
  • μ½”λ“œ μ˜ˆμ‹œ: System.out.println(e.getMessage()); ➑️ 좜λ ₯: "/ by zero" (0으둜 λ‚˜λˆ„μ—ˆμ„ λ•Œ)

β‘‘ toString() : μ˜ˆμ™Έ 이름과 λ©”μ‹œμ§€ 톡합 λ°˜ν™˜

  • λ°œμƒν•œ μ˜ˆμ™Έ 클래슀의 ν’€ λ„€μž„(νŒ¨ν‚€μ§€ 경둜 포함)κ³Ό μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό κ²°ν•©ν•˜μ—¬ λ¬Έμžμ—΄λ‘œ λ‚΄λ†“μŒ.
  • μ½”λ“œ μ˜ˆμ‹œ: System.out.println(e.toString()); ➑️ 좜λ ₯: "java.lang.ArithmeticException: / by zero"

β‘’ printStackTrace() : 좔적 경둜 상세 좜λ ₯ (κ°€μž₯ μ€‘μš”)

  • μ˜ˆμ™Έκ°€ 졜초둜 λ°œμƒν•œ μ†ŒμŠ€ μ½”λ“œμ˜ μœ„μΉ˜(클래슀λͺ…, λ©”μ„œλ“œλͺ…, 쀄 번호)λΆ€ν„° μ‹œμž‘ν•΄μ„œ, μ–΄λ–€ 경둜λ₯Ό 거쳐 λ³€μˆ˜κ°€ 타고 λ‚΄λ €μ™”λŠ”μ§€ μŠ€νƒ(Stack) μ˜μ—­μ˜ λ©”λͺ¨λ¦¬ 이동 행적을 화면에 λΉ¨κ°„ κΈ€μ”¨λ‘œ μ „λΆ€ μŸμ•„λƒ„.
  • μ˜ˆμ™Έ 처리λ₯Ό ν•˜λ”λΌλ„ 이 λ©”μ„œλ“œλ₯Ό 내뢀에 심어두어야 κ°œλ°œμžκ°€ λ‚˜μ€‘μ— 둜그λ₯Ό 보고 버그λ₯Ό μž‘μ„ 수 있음.

β—† 4. μ‹€μ œ μž‘λ™ 및 λ©”μ„œλ“œ ν™œμš© μ˜ˆμ‹œ

Java
 
public class ThrowableExample {
    public static void main(String[] args) {
        try {
            int[] arr = new int[2];
            System.out.println(arr[5]); // πŸ’₯ ArrayIndexOutOfBoundsException λ°œμƒ
            
        } catch (Throwable t) { 
            // πŸ’‘ λ‹€ν˜•μ„± μ•„ν‚€ν…μ²˜: Exception의 쑰상인 Throwable νƒ€μž…μœΌλ‘œλ„ λͺ¨λ“  μ˜ˆμ™Έλ₯Ό λ‹€ λ°›μ•„λ‚Ό 수 있음
            
            System.out.println("1. getMessage κ²°κ³Ό: " + t.getMessage());
            System.out.println("-------------------------------------");
            
            System.out.println("2. toString κ²°κ³Ό: " + t.toString());
            System.out.println("-------------------------------------");
            
            System.out.println("3. printStackTrace κ²°κ³Ό:");
            t.printStackTrace(); // μ½˜μ†”μ— 상세 좔적 이λ ₯ 좜λ ₯
        }
    }
}
  • 좜λ ₯ κ²°κ³Ό 데이터 λ§€ν•‘:
    • getMessage : "Index 5 out of bounds for length 2"
    • toString : "java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 2"
    • printStackTrace : μ†ŒμŠ€μ½”λ“œ λͺ‡ 번째 μ€„μ—μ„œ λ°°μ—΄ λ°© 번호 μ—λŸ¬κ°€ ν„°μ‘ŒλŠ”μ§€ 좔적 경둜λ₯Ό 둜그둜 좜λ ₯함.

 printStackTrace

β—† 1. printStackTrace()의 핡심 κΈ°λŠ₯

  • μŠ€νƒ λ©”λͺ¨λ¦¬ 좔적: μ˜ˆμ™Έκ°€ ν„°μ§€κΈ° μ§μ „κΉŒμ§€ 가상 λ¨Έμ‹ (JVM)의 Stack μ˜μ—­μ— μ–΄λ–€ λ©”μ„œλ“œλ“€μ΄ μˆœμ„œλŒ€λ‘œ μŒ“μ—¬μ„œ μ‹€ν–‰λ˜κ³  μžˆμ—ˆλŠ”μ§€ κ·Έ 계보λ₯Ό μ „λΆ€ μ°Ύμ•„λ‚΄μ–΄ 파일λͺ…, λ©”μ„œλ“œλͺ…, μ†ŒμŠ€ μ½”λ“œ 쀄 번호(Line Number)κΉŒμ§€ λͺ…μ‹œν•¨.
  • 비정상 μ’…λ£Œ μ—†λŠ” 확인: try-catch문으둜 μ˜ˆμ™Έλ₯Ό κ°€λ‘œμ±˜κΈ° λ•Œλ¬Έμ— ν”„λ‘œκ·Έλž¨μ€ 정상 ꡬ동 μƒνƒœλ₯Ό μœ μ§€ν•˜μ§€λ§Œ, 이 λ©”μ„œλ“œ 덕뢄에 내뢀에 μ–΄λ–€ μ‹¬κ°ν•œ 버그가 μžˆμ—ˆλŠ”μ§€ κ°œλ°œμžκ°€ μœ‘μ•ˆμœΌλ‘œ 좔적할 수 있음.

β—† 2. μ½˜μ†” 좜λ ₯ κ²°κ³Ό 해체 (둜그 μ½λŠ” 방법)

μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ printStackTrace()κ°€ μŸμ•„λ‚΄λŠ” λΉ¨κ°„ κΈ€μ”¨μ˜ λ‘œκ·ΈλŠ” κ°€μž₯ μ•„λž˜μͺ½ 쀄뢀터 μœ„μͺ½ 쀄 μˆœμ„œλŒ€λ‘œ 읽어 μ˜¬λΌκ°€μ•Ό 함.

  • 맨 μ•„λž«μ€„: ν”„λ‘œκ·Έλž¨μ˜ μ‹œμž‘μ (main λ©”μ„œλ“œ)μž„.
  • 쀑간 쀄듀: mainμ—μ„œ μ–΄λ–€ λ©”μ„œλ“œλ₯Ό 타고 λ“€μ–΄κ°”λŠ”μ§€ 이동 경둜λ₯Ό λ‚˜νƒ€λƒ„.
  • 맨 μœ—μ€„: μ΅œμ’…μ μœΌλ‘œ μ˜ˆμ™Έκ°€ λ°œμƒν•œ μ§„μ§œ 원인(μ˜ˆμ™Έ 클래슀 이름 및 λ©”μ‹œμ§€)κ³Ό 사건이 ν„°μ§„ μ΅œμ’… μ†ŒμŠ€ μ½”λ“œ μœ„μΉ˜μž„.

β—† 3. 싀무 μ½”λ“œ 및 좜λ ₯ λ§€ν•‘ μ˜ˆμ‹œ

μΌλΆ€λŸ¬ λ©”μ„œλ“œλ₯Ό 3λ‹¨κ³„λ‘œ κ±°μ³μ„œ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨ λ’€ printStackTrace()κ°€ μŠ€νƒ λ©”λͺ¨λ¦¬λ₯Ό μ–΄λ–»κ²Œ μ—­μΆ”μ ν•˜λŠ”μ§€ λ³΄μ—¬μ£ΌλŠ” κ΅¬μ‘°μž„.

Java
 
public class Test {
    public static void main(String[] args) {
        try {
            methodA(); // πŸ’‘ 1. mainμ—μ„œ methodA 호좜
        } catch (ArithmeticException e) {
            System.out.println("--- printStackTrace 좜λ ₯ μ‹œμž‘ ---");
            e.printStackTrace(); // 🚨 μ˜ˆμ™Έ 좔적 가동
            System.out.println("--- printStackTrace 좜λ ₯ 끝 ---");
        }
        System.out.println("ν”„λ‘œκ·Έλž¨μ€ μ£½μ§€ μ•Šκ³  λκΉŒμ§€ 싀행됨");
    }

    public static void methodA() {
        methodB(); // πŸ’‘ 2. methodAμ—μ„œ methodB 호좜
    }

    public static void methodB() {
        int crash = 10 / 0; // πŸ’₯ 3. μ—¬κΈ°μ„œ μ΅œμ’… ArithmeticException λ°œμƒ!
    }
}

πŸ“Š μ‹€μ œ μ½˜μ†” 좜λ ₯ κ²°κ³Ό 데이터:

Plaintext
 
--- printStackTrace 좜λ ₯ μ‹œμž‘ ---
java.lang.ArithmeticException: / by zero
	at Test.methodB(Test.java:19)
	at Test.methodA(Test.java:15)
	at Test.main(Test.java:5)
--- printStackTrace 좜λ ₯ 끝 ---
ν”„λ‘œκ·Έλž¨μ€ μ£½μ§€ μ•Šκ³  λκΉŒμ§€ 싀행됨
  • 좔적 경둜 해독:
      1. at Test.main(Test.java:5) ➑️ 5번째 μ€„μ—μ„œ methodA()λ₯Ό λΆˆλ €μŒ.
      1. at Test.methodA(Test.java:15) ➑️ 15번째 μ€„μ—μ„œ methodB()λ₯Ό λΆˆλ €μŒ.
      1. at Test.methodB(Test.java:19) ➑️ 19번째 μ€„μ—μ„œ 0으둜 λ‚˜λˆ„λŠ” λŒ€ν˜• 사고가 터짐.
      1. java.lang.ArithmeticException: / by zero ➑️ 사고 원인은 μˆ˜ν•™μ  μ—°μ‚° 였λ₯˜μž„.

β—† 4. 싀무 운영 ν™˜κ²½μ—μ„œμ˜ 주의 사항 (λ³΄μ•ˆ 및 μ„±λŠ₯)

  • λ³΄μ•ˆ 취약점 λ°œμƒ: printStackTrace()λŠ” μ†ŒμŠ€ μ½”λ“œμ˜ νŒ¨ν‚€μ§€ ꡬ쑰, 클래슀λͺ…, λ©”μ„œλ“œλͺ…을 가감 없이 λ…ΈμΆœν•¨. λ§Œμ•½ μ‹€μ œ μ„œλΉ„μŠ€ 쀑인 μ›Ήμ‚¬μ΄νŠΈ μ‹œμŠ€ν…œ 화면에 이 정보가 κ·ΈλŒ€λ‘œ λ…ΈμΆœλ˜λ©΄ ν•΄μ»€μ—κ²Œ μ•„ν‚€ν…μ²˜ 섀계도λ₯Ό λ„˜κ²¨μ£ΌλŠ” 꼴이 λ˜μ–΄ λ³΄μ•ˆμƒ 맀우 μœ„ν—˜ν•¨.
  • μ„±λŠ₯ μ €ν•˜: 이 λ©”μ„œλ“œλŠ” νž™κ³Ό μŠ€νƒμ˜ λ©”λͺ¨λ¦¬ 좔적을 μœ„ν•΄ μ‹œμŠ€ν…œ μžμ›μ„ 생각보닀 많이 μ†Œλͺ¨ν•¨. λŒ€κ·œλͺ¨ μ‚¬μš©μžκ°€ λͺ°λ¦¬λŠ” μ„œλ²„μ—μ„œ λ‚¨λ°œν•˜λ©΄ μ„±λŠ₯을 κ°‰μ•„λ¨ΉμŒ.
  • ν•΄κ²°μ±…: ν˜„μ—… μ‹€λ¬΄μ—μ„œλŠ” 개발 μ€‘μ—λ§Œ μ½˜μ†”λ‘œ ν™•μΈν•˜κ³ , μ‹€μ œ 배포할 λ•ŒλŠ” μ½˜μ†” 좜λ ₯을 κΈˆμ§€ν•˜λ©°, Logbackμ΄λ‚˜ log4j 같은 μ „λ¬Έ λ‘œκΉ… 라이브러리λ₯Ό κ²°ν•©ν•˜μ—¬ μ•ˆμ „ν•œ 파일 μ‹œμŠ€ν…œ ν˜•νƒœλ‘œ μ—λŸ¬ 둜그λ₯Ό 기둝 관리함.

μžλ°”(Java)μ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό μžμ‹ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ν•˜λŠ” μ˜€λ²„λΌμ΄λ”©(Overriding)을 μ§„ν–‰ν•  λ•Œ, λ©”μ„œλ“œκ°€ λ˜μ§€λŠ” μ˜ˆμ™Έ(Exception)μ—λŠ” 상속 관계에 λ”°λ₯Έ μ—„κ²©ν•œ μ•„ν‚€ν…μ²˜ κ·œμΉ™μ΄ μ‘΄μž¬ν•¨.

μžλ°” μ»΄νŒŒμΌλŸ¬λŠ” λ‹€ν˜•μ„± κ΅¬ν˜„ μ‹œ μ•ˆμ •μ„±μ„ 보μž₯ν•˜κΈ° μœ„ν•΄ 이 κ·œμΉ™μ„ κ°•μ œν•¨. 핡심 κ·œμΉ™κ³Ό λ©”μ»€λ‹ˆμ¦˜μ„ 팩트 μœ„μ£Όλ‘œ 해체함.

β—†  μ˜ˆμ™Έ μ˜€λ²„λΌμ΄λ”©μ˜ λŒ€μ›μΉ™: "ν™•μž₯ λΆˆκ°€, μΆ•μ†Œ κ°€λŠ₯"

μžμ‹ ν΄λž˜μŠ€μ—μ„œ λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©ν•  λ•Œ, λΆ€λͺ¨ λ©”μ„œλ“œκ°€ λ˜μ§€λ˜ μ˜ˆμ™Έλ³΄λ‹€ 더 ν¬κ±°λ‚˜(μƒμœ„ 클래슀) 더 λ§Žμ€ μ’…λ₯˜μ˜ Checked μ˜ˆμ™Έλ₯Ό 던질 수 μ—†μŒ. 즉, μ˜ˆμ™Έμ˜ λ²”μœ„λ₯Ό μ’νžˆκ±°λ‚˜ μ•„μ˜ˆ λ˜μ§€μ§€ μ•ŠλŠ” λ°©ν–₯(μΆ•μ†Œ)으둜만 μ˜€λ²„λΌμ΄λ”©μ΄ ν—ˆμš©λ¨.

⚠️ μ€€μˆ˜ν•΄μ•Ό ν•˜λŠ” 3λŒ€ μ˜ˆμ™Έ κ·œμΉ™

  1. 더 μƒμœ„μ˜ μ˜ˆμ™Έ μ„ μ–Έ λΆˆκ°€: λΆ€λͺ¨ λ©”μ„œλ“œκ°€ IOException을 λ˜μ§„λ‹€λ©΄, μžμ‹ λ©”μ„œλ“œλŠ” κ·Έ 쑰상인 Exceptionμ΄λ‚˜ Throwable을 던질 수 μ—†μŒ.
  2. μƒˆλ‘œμš΄ Checked μ˜ˆμ™Έ μΆ”κ°€ λΆˆκ°€: λΆ€λͺ¨κ°€ μ„ μ–Έν•˜μ§€ μ•Šμ€ μ™„μ „νžˆ μƒˆλ‘œμš΄ Checked μ˜ˆμ™Έ(예: SQLException)λ₯Ό λ§ˆμŒλŒ€λ‘œ μΆ”κ°€ν•  수 μ—†μŒ.
  3. μžμ‹ μ˜ˆμ™Έ 선언은 κ°€λŠ₯ (μΆ•μ†Œ): λΆ€λͺ¨ λ©”μ„œλ“œκ°€ Exception을 λ˜μ§„λ‹€λ©΄, μžμ‹ λ©”μ„œλ“œλŠ” κ·Έ μžμ‹ 클래슀인 IOExceptionμ΄λ‚˜ NullPointerException으둜 μ’ν˜€μ„œ λ˜μ§€λŠ” 것이 κ°€λŠ₯함. λ˜ν•œ μ˜ˆμ™Έλ₯Ό μ•„μ˜ˆ λ˜μ§€μ§€ μ•Šλ„λ‘ μˆ˜μ •ν•˜λŠ” 것도 ν—ˆμš©λ¨.

β—† μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” 잘λͺ»λœ μ˜€λ²„λΌμ΄λ”© μ˜ˆμ‹œ


 
import java.io.IOException;
import java.sql.SQLException;

class Parent {
    // πŸ’‘ λΆ€λͺ¨ λ©”μ„œλ“œλŠ” IOException(Checked Exception)을 λ˜μ§€λ„λ‘ 섀계됨
    public void process() throws IOException {
        System.out.println("λΆ€λͺ¨ 처리");
    }
}

class Child extends Parent {
    // ❌ 컴파일 μ—λŸ¬ λ°œμƒ: λΆ€λͺ¨λ³΄λ‹€ 더 κ΄‘λ²”μœ„ν•œ μƒμœ„ μ˜ˆμ™Έ(Exception)λ₯Ό 던질 수 μ—†μŒ
    @Override
    public void process() throws Exception { 
        System.out.println("μžμ‹ 처리");
    }
}

class Child2 extends Parent {
    // ❌ 컴파일 μ—λŸ¬ λ°œμƒ: λΆ€λͺ¨ 섀계도에 μ—†λ˜ μƒˆλ‘œμš΄ Checked μ˜ˆμ™Έ(SQLException)λ₯Ό μΆ”κ°€ν•  수 μ—†μŒ
    @Override
    public void process() throws SQLException { 
        System.out.println("μžμ‹ 처리 2");
    }
}

β—† μ •μƒμ μœΌλ‘œ μž‘λ™ν•˜λŠ” μ˜¬λ°”λ₯Έ μ˜€λ²„λΌμ΄λ”© μ˜ˆμ‹œ

 
import java.io.FileNotFoundException;
import java.io.IOException;

class Parent {
    public void process() throws IOException {
        System.out.println("λΆ€λͺ¨ 처리");
    }
}

class ChildGood1 extends Parent {
    // β­• κ°€λŠ₯: λΆ€λͺ¨κ°€ μ„ μ–Έν•œ IOException의 ν•˜μœ„(μžμ‹) μ˜ˆμ™ΈμΈ FileNotFoundException으둜 λ²”μœ„λ₯Ό 쒁힘
    @Override
    public void process() throws FileNotFoundException {
        System.out.println("μžμ‹ 처리 1");
    }
}

class ChildGood2 extends Parent {
    // β­• κ°€λŠ₯: μžμ‹ λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œ μ˜ˆμ™Έλ₯Ό μ™„λ²½νžˆ μˆ˜μŠ΅ν•˜μ—¬ μ™ΈλΆ€λ‘œ μ•„μ˜ˆ μ•ˆ λ˜μ§€λ„λ‘ μΆ•μ†Œν•¨
    @Override
    public void process() {
        System.out.println("μžμ‹ 처리 2");
    }
}

β—†μ΄λŸ¬ν•œ μ œμ•½ κ·œμΉ™μ΄ μ‘΄μž¬ν•˜λŠ” 이유: λ‹€ν˜•μ„± 보μž₯

μžλ°” μ»΄νŒŒμΌλŸ¬κ°€ μ™œ μžμ‹μ˜ μ˜ˆμ™Έ ν™•μž₯을 λ§‰λŠ”μ§€ λ‹€ν˜•μ„± 호좜 ꡬ쑰 κ΄€μ μ—μ„œ 해체해야 함.

Java
 
public class Main {
    public static void main(String[] args) {
        // πŸ’‘ λ‹€ν˜•μ„±: λΆ€λͺ¨ νƒ€μž… 리λͺ¨μ»¨(Parent)으둜 μžμ‹ 객체(Child)λ₯Ό 쑰쒅함
        Parent obj = new Child(); 
        
        try {
            obj.process(); // πŸ’‘ μ»΄νŒŒμΌλŸ¬λŠ” 리λͺ¨μ»¨ νƒ€μž…μΈ 'Parent.process()'의 λͺ…μ„Έλ§Œ 보고 μ½”λ“œλ₯Ό 검사함
        } catch (IOException e) {
            // κ°œλ°œμžλŠ” λΆ€λͺ¨ λͺ…세에 적힌 IOException만 μž‘λ„λ‘ λŒ€λΉ„μ±…(catch)을 μ„Έμ›Œλ‘ 
            System.out.println("λΆ€λͺ¨κ°€ μ„ μ–Έν•œ μ˜ˆμ™Έ 수슡 μ™„λ£Œ");
        }
    }
}
  • λ©”μ»€λ‹ˆμ¦˜ λΉ„ν‹€κΈ°: λ§Œμ•½ μžμ‹ 클래슀인 Childκ°€ μ˜€λ²„λΌμ΄λ”©μ„ ν•˜λ©΄μ„œ λΆ€λͺ¨ λͺ°λž˜ SQLExceptionμ΄λΌλŠ” μ™„μ „νžˆ μƒˆλ‘œμš΄ μ˜ˆμ™Έλ₯Ό λ˜μ§€λ„λ‘ ν—ˆμš©ν•΄ 버렸닀면 μ–΄λ–»κ²Œ 될까?
  • μ‹€μ œ ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ μ‹œ obj.process() ꡬ동 도쀑 SQLException이 ν„°μ Έ ν˜λŸ¬λ‚˜μ˜€κ²Œ 됨. ν•˜μ§€λ§Œ μƒμœ„ main λ©”μ„œλ“œμ—λŠ” 였직 IOException만 μž‘λŠ” 방어막(catch)만 쳐져 있기 λ•Œλ¬Έμ—, 이 μ˜ˆμ™Έλ₯Ό κ°€λ‘œμ±„μ§€ λͺ»ν•˜κ³  ν”„λ‘œκ·Έλž¨μ΄ κ·Έ μžλ¦¬μ—μ„œ κ°•μ œ 였λ₯˜ μ’…λ£Œλ˜λŠ” 치λͺ…적인 ꡬ멍이 생김.
  • μžλ°” μ»΄νŒŒμΌλŸ¬λŠ” μ΄λŸ¬ν•œ λ‹€ν˜•μ„± ꡬ동 μ‹œμ˜ λŸ°νƒ€μž„ λΆ•κ΄΄λ₯Ό μ›μ²œ μ°¨λ‹¨ν•˜κΈ° μœ„ν•΄, μ˜€λ²„λΌμ΄λ”© μ‹œ λΆ€λͺ¨κ°€ μ„ μ–Έν•œ μ˜ˆμ™Έμ˜ μšΈνƒ€λ¦¬λ₯Ό μžμ‹μ΄ μ ˆλŒ€ λ„˜μ–΄κ°€μ§€ λͺ»ν•˜λ„둝 κ·œμ œν•˜λŠ” κ²ƒμž„.

β—† μ˜ˆμ™Έ κ·œμΉ™μ˜ μœ μΌν•œ μ˜ˆμ™Έ: RuntimeException

  • Unchecked Exception(RuntimeException 계열)은 이 μ˜€λ²„λΌμ΄λ”© μ œμ•½ κ·œμΉ™μ—μ„œ μ™„μ „νžˆ μžμœ λ‘œμ›€.
  • μžμ‹ ν΄λž˜μŠ€μ—μ„œ μ˜€λ²„λΌμ΄λ”©ν•  λ•Œ λΆ€λͺ¨ λ©”μ„œλ“œκ°€ μ„ μ–Έν•˜μ§€ μ•Šμ€ NullPointerExceptionμ΄λ‚˜ ArrayIndexOutOfBoundsException 같은 μ˜ˆμ™ΈλŠ” μ œν•œ 없이 μ–Όλ§ˆλ“ μ§€ λ˜μ§€λ„λ‘ μΆ”κ°€ν•  수 있음.
  • 이유: Unchecked μ˜ˆμ™ΈλŠ” μ• μ΄ˆμ— μ»΄νŒŒμΌλŸ¬κ°€ try-catch 선언을 κ°•μ œ κ°μ‹œν•˜μ§€ μ•ŠλŠ” μ˜μ—­μ΄κΈ° λ•Œλ¬Έμ— κ·œμΉ™ λ§€ν•‘ μžμ²΄μ—μ„œ μ œμ™Έν•˜κΈ° λ•Œλ¬Έμž„.

데이터 이동 핡심 λ©”μ»€λ‹ˆμ¦˜μΈ μž…μΆœλ ₯(I/O - Input/Output)κ³Ό 슀트림(Stream) μ•„ν‚€ν…μ²˜λ₯Ό 팩트 기반으둜 ν•΄μ²΄ν•˜μ—¬ 정리함.

β—†  μž…μΆœλ ₯(I/O)의 μ •μ˜μ™€ κΈ°λŠ₯

  • μ •μ˜: 컴퓨터 λ‚΄λΆ€ ν”„λ‘œκ·Έλž¨κ³Ό μ™ΈλΆ€ μž₯치(파일, ν‚€λ³΄λ“œ, λͺ¨λ‹ˆν„°, λ„€νŠΈμ›Œν¬, λ©”λͺ¨λ¦¬ λ“±) 간에 데이터λ₯Ό μ£Όκ³ λ°›λŠ” 일련의 ν–‰μœ„λ₯Ό μ˜λ―Έν•¨.
  • κΈ°λŠ₯: * Input (μž…λ ₯): μ™ΈλΆ€ μž₯μΉ˜μ— μ‘΄μž¬ν•˜λŠ” 데이터λ₯Ό ν”„λ‘œκ·Έλž¨ λ©”λͺ¨λ¦¬ μ•ˆμœΌλ‘œ 읽어 λ“€μ΄λŠ” κΈ°λŠ₯ (Read μ—°μ‚°)
    • Output (좜λ ₯): ν”„λ‘œκ·Έλž¨μ΄ λ©”λͺ¨λ¦¬μƒμ—μ„œ μ—°μ‚°ν•œ 데이터 결과물을 μ™ΈλΆ€ μž₯치둜 내보내어 μ €μž₯ν•˜κ±°λ‚˜ ν‘œμ‹œν•˜λŠ” κΈ°λŠ₯ (Write μ—°μ‚°)

β—† 슀트림(Stream)의 μ •μ˜ 및 핡심 κ°œλ…

μžλ°”μ˜ I/OλŠ” 슀트림(Stream)μ΄λΌλŠ” λͺ¨λΈμ„ 톡해 물리적인 μž₯치 μ’…λ₯˜μ™€ 상관없이 λ™μΌν•œ λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μ œμ–΄ν•¨.

  • 슀트림의 μ •μ˜: 데이터가 μ΄λ™ν•˜λŠ” '단방ν–₯ ν†΅λ‘œ' λ˜λŠ” '흐λ₯΄λŠ” 물쀄기'λ₯Ό λœ»ν•¨.
  • 단방ν–₯μ„±μ˜ 원칙: ν•˜λ‚˜μ˜ ν†΅λ‘œ(슀트림)λ‘œλŠ” ν•œ κ°€μ§€ λ°©ν–₯으둜만 데이터가 흐λ₯Ό 수 있음. 즉, μž…λ ₯κ³Ό 좜λ ₯을 λ™μ‹œμ— μ²˜λ¦¬ν•  수 μ—†μœΌλ―€λ‘œ μž…λ ₯용 ν†΅λ‘œμ™€ 좜λ ₯용 ν†΅λ‘œλ₯Ό 각각 λ³„λ„λ‘œ κ°œμ„€ν•΄μ•Ό 함.
  • FIFO (First-In-First-Out): ν†΅λ‘œμ— λ¨Όμ € λ“€μ–΄κ°„ 데이터가 λ°˜λŒ€μͺ½ 끝으둜 λ¨Όμ € λ‚˜μ˜€λŠ” μ„ μž…μ„ μΆœ ꡬ쑰λ₯Ό 따름.

β—† 슀트림(Stream)의 3λŒ€ λΆ„λ₯˜ κΈ°μ€€

μžλ°”λŠ” 효율적인 μžμ› μ œμ–΄λ₯Ό μœ„ν•΄ μŠ€νŠΈλ¦Όμ„ μ„Έ κ°€μ§€ κΈ°μ€€(λ°©ν–₯, 데이터 ν˜•νƒœ, κΈ°λŠ₯)에 따라 λͺ…ν™•ν•˜κ²Œ λΆ„λ₯˜ν•¨.

κΈ°μ€€ β‘ : 데이터 νλ¦„μ˜ λ°©ν–₯에 λ”°λ₯Έ λΆ„λ₯˜ (단방ν–₯ 원칙)

  • μž…λ ₯ 슀트림 (Input Stream): λŒ€μƒ λͺ©μ μ§€λ‘œλΆ€ν„° ν”„λ‘œκ·Έλž¨μœΌλ‘œ 데이터λ₯Ό λ°€μ–΄ λ„£μ–΄μ£ΌλŠ” 읽기 μ „μš© ν†΅λ‘œ.
  • 좜λ ₯ 슀트림 (Output Stream): ν”„λ‘œκ·Έλž¨ λ‚΄λΆ€ 데이터λ₯Ό λŒ€μƒ μž₯치둜 λ°€μ–΄λ‚΄ μ£ΌλŠ” μ“°κΈ° μ „μš© ν†΅λ‘œ.

κΈ°μ€€ β‘‘: λ‹€λ£¨λŠ” λ°μ΄ν„°μ˜ μ΅œμ†Œ 단주(ν˜•νƒœ)에 λ”°λ₯Έ λΆ„λ₯˜

데이터 μ•Œλ§Ήμ΄λ₯Ό μ–΄λ–€ 크기둜 μͺΌκ°œμ„œ μ „μ†‘ν•˜λŠλƒμ— 따라 물리적 처리 방식이 μ™„μ „νžˆ λ‚˜λ‰¨.

  • λ°”μ΄νŠΈ 슀트림 (Byte Stream): * 데이터λ₯Ό 1λ°”μ΄νŠΈ(byte, 8bit) λ‹¨μœ„λ‘œ 가곡 없이 κ·ΈλŒ€λ‘œ μ£Όκ³ λ°›λŠ” κ°€μž₯ μ›μ‹œμ μ΄κ³  κ°•λ ₯ν•œ ν†΅λ‘œμž„.
    • κ·Έλ¦Ό 파일(.jpg), μŒμ•…(.mp3), λ™μ˜μƒ, μ‹€ν–‰ 파일(.exe) λ“± λͺ¨λ“  ν˜•νƒœμ˜ λ°”μ΄λ„ˆλ¦¬ 데이터λ₯Ό 깨짐 없이 μ™„λ²½ν•˜κ²Œ 전솑할 수 있음.
    • 클래슀 이름 접미사: μž…λ ₯은 ~InputStream, 좜λ ₯은 ~OutputStream ν˜•μ‹μ„ 취함. (예: FileInputStream)
  • 문자 슀트림 (Character Stream):
    • 데이터λ₯Ό 2λ°”μ΄νŠΈ(2byte, 16bit) λ‹¨μœ„λ‘œ μͺΌκ°œμ–΄ μ „μ†‘ν•˜λ©°, 전솑 κ³Όμ •μ—μ„œ μžλ°” λ‚΄μž₯ 인코딩(UTF-16 λ“±) κ·œκ²©μ— 맞좰 문자(Text)둜 μžλ™ λ²ˆμ—­ν•΄ μ£ΌλŠ” ν†΅λ‘œμž„.
    • 였직 ν…μŠ€νŠΈ 파일(.txt, .csv, μ†ŒμŠ€ μ½”λ“œ) μ „μš©μ΄λ©°, μ˜μ–΄ μ™Έμ˜ μ „ 세계 문자(ν•œκΈ€, ν•œμž λ“± 2λ°”μ΄νŠΈ 이상 문자)κ°€ κΉ¨μ§€μ§€ μ•Šλ„λ‘ 보μž₯함.
    • 클래슀 이름 접미사: μž…λ ₯은 ~Reader, 좜λ ₯은 ~Writer ν˜•μ‹μ„ 취함. (예: FileReader)

κΈ°μ€€ β‘’: 슀트림의 μ—­ν•  및 κ²°ν•© μ•„ν‚€ν…μ²˜μ— λ”°λ₯Έ λΆ„λ₯˜

  • 기반 슀트림 (1μ°¨ 슀트림): νŒŒμΌμ΄λ‚˜ λ©”λͺ¨λ¦¬ 같은 데이터 μ†ŒμŠ€μ— 직접 λΉ¨λŒ€λ₯Ό 꽂아 ν†΅λ‘œλ₯Ό κ°œμ„€ν•˜λŠ” μŠ€νŠΈλ¦Όμž„. ν˜Όμžμ„œ 데이터λ₯Ό 직접 퍼 올릴 수 있음. (예: FileInputStream, FileReader)
  • 보쑰 슀트림 (2μ°¨ 슀트림 / ν•„ν„° 슀트림): 데이터 μ†ŒμŠ€μ— 직접 μ—°κ²°ν•  수 μ—†μŒ. λŒ€μ‹  이미 κ°œμ„€λœ 1μ°¨ 기반 슀트림 주변을 κ°μ‹Έμ„œ 버퍼 κΈ°λŠ₯(속도 ν–₯상), 문자 인코딩 λ³€ν™˜, μ„±λŠ₯ μ—…κ·Έλ ˆμ΄λ“œ λ“± λΆ€κ°€ κΈ°λŠ₯만 λ°μ½”λ ˆμ΄μ…˜ν•΄ μ£ΌλŠ” 특수 μŠ€νŠΈλ¦Όμž„. (예: BufferedInputStream, BufferedReader)

 

 

β—† File 클래슀

 

 ν•˜λ“œλ””μŠ€ν¬ 같은 물리적 μ €μž₯ μž₯μΉ˜μ— μ‘΄μž¬ν•˜λŠ” μ‹€μ œ νŒŒμΌμ΄λ‚˜ 디렉터리(폴더)λ₯Ό μžλ°” 객체 μ•„ν‚€ν…μ²˜λ‘œ μΆ”μƒν™”ν•˜μ—¬ μ œμ–΄ν•˜λŠ” λ„κ΅¬μž„.β—† File 클래슀의 객체 ν˜•μ„±(생성) 방식 및 λ©”μ»€λ‹ˆμ¦˜

  • μ ˆλŒ€ 경둜: λ“œλΌμ΄λΈŒμ˜ μ΅œμƒμœ„ λ£¨νŠΈλΆ€ν„° 파일이 μžˆλŠ” μœ„μΉ˜κΉŒμ§€ 전체 경둜λ₯Ό μ „λΆ€ λ‹€ μ μ–΄μ£ΌλŠ” λ°©μ‹μž„.
    • μ˜ˆμ‹œ: C:\java_project\test.txt
  • μƒλŒ€ 경둜: ν˜„μž¬ ν”„λ‘œκ·Έλž¨(ν”„λ‘œμ νŠΈ 폴더)이 μ‹€ν–‰λ˜κ³  μžˆλŠ” μœ„μΉ˜λ₯Ό 기쀀점(./)으둜 작고 파일의 μœ„μΉ˜λ₯Ό μ°Ύμ•„κ°€λŠ” λ°©μ‹μž„. 경둜 μœ μ—°μ„±μ΄ λ†’μ•„ 싀무 μ•„ν‚€ν…μ²˜μ—μ„œ 훨씬 μ„ ν˜Έλ¨.
    • μ˜ˆμ‹œ: src/data/test.txt

β—† File 객체 ν˜•μ„± 및 핡심 λ©”μ„œλ“œ μ œμ–΄ μ˜ˆμ‹œ

Java
 
import java.io.File;
import java.io.IOException;

public class FileExample {
    public static void main(String[] args) {
        
        // πŸ’‘ 1. 디렉터리(폴더) μ œμ–΄μš© File 객체 ν˜•μ„±
        File dir = new File("src/myFolder");
        
        // πŸ’‘ 2. 파일 μ œμ–΄μš© File 객체 ν˜•μ„± (κ²½λ‘œμ™€ 파일λͺ… κ²°ν•©)
        File file = new File(dir, "sample.txt");

        try {
            // β—† 물리적 폴더 생성 λ©”μ»€λ‹ˆμ¦˜
            if (!dir.exists()) { // ν•΄λ‹Ή κ²½λ‘œμ— 폴더가 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄
                dir.mkdir();     // ν•˜λ“œλ””μŠ€ν¬μ— μ§„μ§œ 폴더λ₯Ό νŒŒλƒ„
                System.out.println("πŸ“ 폴더 생성 μ™„λ£Œ");
            }

            // β—† 물리적 파일 생성 λ©”μ»€λ‹ˆμ¦˜
            if (!file.exists()) {  // ν•΄λ‹Ή 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄
                file.createNewFile(); // πŸ’₯ Checked Exception λ°œμƒν•˜λ―€λ‘œ try-catch ν•„μˆ˜ ꡬ쑰, μ§„μ§œ 파일 생성
                System.out.println("πŸ“„ 파일 생성 μ™„λ£Œ");
            }

            // β—† ν˜•μ„±λœ File 객체λ₯Ό ν†΅ν•œ μƒνƒœ 데이터 쑰회 κΈ°λŠ₯
            System.out.println("--------------------------------");
            System.out.println("파일 μ ˆλŒ€κ²½λ‘œ: " + file.getAbsolutePath());
            System.out.println("파일 크기(Byte): " + file.length());
            System.out.println("읽기 κ°€λŠ₯ μ—¬λΆ€: " + file.canRead());
            System.out.println("μ“°κΈ° κ°€λŠ₯ μ—¬λΆ€: " + file.canWrite());
            System.out.println("이것은 νŒŒμΌμΈκ°€?: " + file.isFile());
            System.out.println("이것은 폴더인가?: " + file.isDirectory());
            System.out.println("--------------------------------");

            // β—† 파일 μ‚­μ œ λ©”μ»€λ‹ˆμ¦˜ (ν…ŒμŠ€νŠΈ ν•„μš” μ‹œ 주석 ν•΄μ œ)
            // if (file.exists()) {
            //     file.delete(); // 물리 파일 μ‚­μ œ
            //     System.out.println("πŸ—‘οΈ 파일 μ‚­μ œ μ™„λ£Œ");
            // }

        } catch (IOException e) {
            // printStackTraceλ₯Ό ν™œμš©ν•œ 경둜 역좔적 μ—λŸ¬ 둜그 좜λ ₯
            e.printStackTrace(); 
        }
    }
}

β—† ⚠️ 주의 사항 및 ꡬ동 팩트

  • 객체 생성 vs 물리 파일 생성 뢄리: File file = new File("test.txt"); λ¬Έμž₯을 μ‹€ν–‰ν–ˆλ‹€κ³  ν•΄μ„œ ν•˜λ“œλ””μŠ€ν¬μ— 파일이 μ¦‰μ‹œ λ§Œλ“€μ–΄μ§€λŠ” 것이 μ•„λ‹˜. 단지 λ©”λͺ¨λ¦¬ μŠ€νƒ μ˜μ—­μ— μ£Όμ†Œ μƒμž(μžλ°” 객체)만 νŒŒμ§„ μƒνƒœμž„.
  • 쑴재 μ—¬λΆ€ 확인 ν•„μˆ˜: λ°˜λ“œμ‹œ 객체 ν˜•μ„± 이후 file.exists() λ©”μ„œλ“œλ‘œ 파일이 μ‹€μ œ ν•˜λ“œλ””μŠ€ν¬μ— μžˆλŠ”μ§€ ν™•μΈν•œ λ’€, createNewFile()μ΄λ‚˜ mkdir() λ©”μ„œλ“œλ₯Ό λͺ…μ‹œμ μœΌλ‘œ 가동해야 물리 곡간에 할당됨.
  • μ•„λž˜ μ½”λ“œλŠ” μƒλŒ€ 경둜 ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‹€μ œ 파일 μ‹œμŠ€ν…œμ— 물리적 파일과 폴더λ₯Ό νƒ„μƒμ‹œν‚€κ³  속성을 μ‘°νšŒν•˜λŠ” 전체 μ‹œν€€μŠ€μž„.
  • File 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄μ„œλŠ” λŒ€μƒ 파일이 μœ„μΉ˜ν•œ 물리적 경둜(Path) λ¬Έμžμ—΄μ„ μ§€μ •ν•΄μ•Ό 함. μ΄λ•Œ κ²½λ‘œλŠ” 두 κ°€μ§€ λ°©μ‹μœΌλ‘œ λ§€ν•‘ν•  수 있음.
  • μ‹€μ œ 파일 λ‚΄λΆ€μ˜ 데이터 μ•Œλ§Ήμ΄λ₯Ό 읽고 μ“°λŠ” κΈ°λŠ₯은 μ—†μœΌλ©°, 파일의 경둜, 이름, 크기, μˆ˜μ • λ‚ μ§œ 등을 μ‘°νšŒν•˜κ±°λ‚˜ νŒŒμΌμ„ 생성, μ‚­μ œ, 이름 λ³€κ²½ν•˜λŠ” λ“±μ˜ μ™Έν˜•μ  관리 κΈ°λŠ₯만 μˆ˜ν–‰ν•¨.