코딩/sparta TIL

TIL 11 : 계산기 과제 V2, Markdown 문법, Enum

americanoallday 2025. 3. 4. 15:34

Timeline

09:00 ~ 10:00 : 데일리 스크럼, 코드카타(SQL&알고리즘 4문제 진행)

10:00 ~ 13:00 : 자바 종합 문법 1~3주차 복습

13:00 ~ 14:20 : 점심 시간, 고용노동부 방문(외출)

14:20 ~ 15:00 : 클래스 특강 

15:00 ~ 15:30 : 자바 종합 문법 3주차 복습

15:30 ~ 18:00 : 계산기 과제 레벨2, README문서 작성

18:00 ~ 19:00 : 저녁 시간

19:00 ~ 21:00 : Enum,

 

저번 주 금토월(대체공휴일) 모두 놀았다...

 

데일리 스크럼, 코드카타 문제 풀고

자바 다 까먹은 것 같아서 다시 1~3주차 복습 진행

고용노동부 방문했다가 돌아와서

계산기 과제 클래스(레벨 2) 활용 진행

 

(고용노동부 내일 방문인데, 오늘 다녀와서 허탕침 ㅠㅠ)

 

오늘은 README 깃허브 문서 서식 꾸민다고 2시간 날린 듯

 

Markdown 문법

# 제목 (가장 큰 제목) > ###### 제목 (가장 작은 제목)

** 굵게 **

* 기울임 *

~~ 취소선 ~~

*** 굵게 + 기울임 ***

 

링크 추가 : [GitHub](https://github.com)

이미지 추가 : ![이미지 설명](https://via.placeholder.com/150)

 

인라인 코드

이 문장 안에서 `System.out.println("Hello World");` 사용 가능.

 

코드 블록

```java

 

체크리스트

- [x] 완료된 항목  
- [ ] 미완료된 항목

 

테이블 표

| 이름  | 나이 | 직업  |
|------|----|------|
| 홍길동 | 30 | 개발자 |
| 김영희 | 25 | 디자이너 |

 

인용구(Quote)

> 이것은 인용구입니다.
>> 중첩된 인용구입니다.

 

구분선

---

 

Enum(열거형)이란?

 “여러 개의 관련된 상수(constant)값을 하나의 그룹으로 묶을 때” 사용하는 자료형

 

✔ 일반 상수(final static) 사용 vs. enum 사용 비교

 

✅ (1) 상수를 final static으로 관리하는 경우

public class OrderStatus {
    public static final int ORDERED = 1;
    public static final int SHIPPED = 2;
    public static final int DELIVERED = 3;
}

 

✅ (2) enum을 사용한 경우 (더 안전하고 명확한 방법!)

public enum OrderStatus {
    ORDERED,    // 주문됨
    SHIPPED,    // 배송됨
    DELIVERED   // 배송 완료
}

 

📌 enum 사용 예제

public class Main {
    public static void main(String[] args) {
        OrderStatus status = OrderStatus.SHIPPED;

        // ✅ enum 값을 출력
        System.out.println(status); // 출력: SHIPPED

        // ✅ switch 문에서 사용 가능
        switch (status) {
            case ORDERED:
                System.out.println("주문이 완료되었습니다.");
                break;
            case SHIPPED:
                System.out.println("상품이 배송 중입니다.");
                break;
            case DELIVERED:
                System.out.println("상품이 배송 완료되었습니다.");
                break;
        }
    }
}

 

enum에 추가 기능(필드, 생성자, 메서드) 추가하기

enum도 클래스처럼 필드와 메서드를 가질 수 있음.

각 enum 값마다 특정한 속성을 가질 수도 있음.

public enum OrderStatus {
    ORDERED("주문 완료"),
    SHIPPED("배송 중"),
    DELIVERED("배송 완료");

    private final String description; // ✅ 설명 필드 추가

    // ✅ 생성자
    OrderStatus(String description) {
        this.description = description;
    }

    // ✅ 설명을 반환하는 메서드
    public String getDescription() {
        return description;
    }
}

public class Main {
    public static void main(String[] args) {
        OrderStatus status = OrderStatus.SHIPPED;
        
        // ✅ enum 값과 설명 출력
        System.out.println(status); // 출력: SHIPPED
        System.out.println(status.getDescription()); // 출력: 배송 중
    }
}

📌 ORDERED, SHIPPED, DELIVERED는 static final이 자동으로 붙은 것처럼 동작

📌 즉, new OrderStatus()로 새로운 값을 만들 수 없음 → enum의 값은 변경 불가능(immutable)

 

ORDERED = new OrderStatus("주문 완료"); // ❌ 불가능

ORDERED.description = "다른 값"; // ❌ 불가능

 

🚀 즉, enum의 값들은 한 번 정의되면 변하지 않는 final static 상수처럼 동작

위의 코드 실제 동작 방식

public final class OrderStatus extends Enum<OrderStatus> {
    public static final OrderStatus ORDERED = new OrderStatus("주문 완료");
    public static final OrderStatus SHIPPED = new OrderStatus("배송 중");
    public static final OrderStatus DELIVERED = new OrderStatus("배송 완료");

    private final String description;

    private OrderStatus(String description) { // ✅ 생성자는 한 번만 실행됨
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

ORDERED, SHIPPED, DELIVERED는 new OrderStatus("설명")처럼 미리 생성된 객체.

그래서 OrderStatus.SHIPPED;를 하면 새로 생성하는 게 아니라 “미리 만들어진 객체”를 가져오는 것 ✅

public class Main {
    public static void main(String[] args) {
        OrderStatus status = OrderStatus.SHIPPED;  // ✅ 여기서 생성자 호출 ❌ (이미 생성된 객체 가져오기)
        System.out.println("현재 상태: " + status.getDescription());
    }
}

✔ 실행 과정:

1. OrderStatus가 처음 로드될 때, ORDERED, SHIPPED, DELIVERED 객체가 한 번만 생성됨

2. OrderStatus.SHIPPED;을 하면 이미 만들어진 SHIPPED 객체를 가져옴

3. status.getDescription();을 호출하면 "배송 중"이 출력됨

enum의 주요 기능

메서드 설명
values() 모든 enum 값을 배열로 반환
valueOf(String name) name과 일치하는 enum 값을 반환
ordinal() enum의 순서(0부터 시작) 반환
public class Main {
    public static void main(String[] args) {
        // ✅ 모든 enum 값 출력
        for (OrderStatus status : OrderStatus.values()) {
            System.out.println(status + " (" + status.ordinal() + ")");
        }

        // ✅ 문자열을 enum 값으로 변환
        OrderStatus status = OrderStatus.valueOf("SHIPPED");
        System.out.println("변환된 값: " + status);
    }
}
ORDERED (0)
SHIPPED (1)
DELIVERED (2)
변환된 값: SHIPPED

 

enum vs. class 차이

비교 항목 enum class
용도 관련된 상수 그룹화 여러 개의 객체 생성
인스턴스 생성 자동으로 인스턴스 생성 new 키워드 사용
상속 다른 클래스를 상속할 수 없음 가능
인터페이스 구현 가능 가능

 

예제: 캐릭터 직업 (JobType)

public enum JobType {
    WARRIOR,    // 전사
    MAGE,       // 마법사
    ARCHER      // 궁수
}
public class Character {
    private String name;
    private JobType jobType;

    public Character(String name, JobType jobType) {
        this.name = name;
        this.jobType = jobType;
    }

    public void printCharacterInfo() {
        System.out.println("캐릭터: " + name + ", 직업: " + jobType);
    }
}

public class Main {
    public static void main(String[] args) {
        Character hero = new Character("아르테미스", JobType.ARCHER);
        hero.printCharacterInfo();  // 출력: 캐릭터: 아르테미스, 직업: ARCHER
    }
}

enum을 사용하면 jobType 필드에 WARRIOR, MAGE, ARCHER만 들어갈 수 있음.

즉, jobType에 new JobType("고블린") 같은 잘못된 값을 넣을 가능성이 사라짐.

더보기

나중에 직업이 추가되면 JobType(enum)을 변경해도 될까?

기존 캐릭터(ARCHER, MAGE, WARRIOR)에는 영향 없음!

하지만, 기존 직업을 삭제하거나 이름을 변경하면 문제가 발생할 수 있음! 🚨

📌 새로운 값을 추가하는 것은 괜찮지만, 기존 값을 삭제하거나 이름을 변경하면 위험함! 🚨

따라서 기존 값은 유지하면서 새로운 값을 추가하는 방식이 안전함!

public enum JobType {
    WARRIOR,    
    MAGE,       
    ARCHER,
    PALADIN,  // 추가됨
    ASSASSIN  // 추가됨
}

 

🚨 enum 이름을 변경해야 할 경우 (안전한 변경 방법)

public enum JobType {
    WARRIOR,    
    MAGE,       
    ARCHER,  // 기존 값 유지 (나중에 deprecated 처리 가능)
    RANGER,  // 새로운 이름 추가
    PALADIN,   
    ASSASSIN   
}

이렇게 하면 기존 데이터(ARCHER)가 깨지지 않고, 새로운 이름(RANGER)을 사용할 수 있음!

나중에 ARCHER를 제거할 때도, 먼저 “더 이상 사용하지 말 것”이라고 경고한 후 제거 가능!

 

enum을 더 안전하게 변경하는 방법 (String 값을 저장하기)

데이터를 숫자로 저장하면 값이 바뀌어도 안전하게 유지할 수 있음!

예제: JobType에 숫자 ID 추가

public enum JobType {
    WARRIOR(1),    
    MAGE(2),       
    ARCHER(3),     
    PALADIN(4),   
    ASSASSIN(5);

    private final int id;

    JobType(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

📌 이제 데이터베이스에 저장할 때 ARCHER 대신 3을 저장할 수 있음

이렇게 하면 ARCHER를 RANGER로 바꿔도 id=3으로 매핑되기 때문에 기존 데이터가 깨지지 않음

 

예제: 무기 시스템 (Weapon 클래스)

public class Weapon {
    private String name;
    private int damage;

    public Weapon(String name, int damage) {
        this.name = name;
        this.damage = damage;
    }

    public void attack() {
        System.out.println(name + " 공격! 데미지: " + damage);
    }
}
public class Main {
    public static void main(String[] args) {
        Weapon sword = new Weapon("전사의 검", 50);
        Weapon bow = new Weapon("궁수의 활", 30);

        sword.attack();  // 출력: 전사의 검 공격! 데미지: 50
        bow.attack();    // 출력: 궁수의 활 공격! 데미지: 30
    }
}

class는 new Weapon()을 통해 여러 개의 인스턴스를 만들 수 있음!

즉, “직업”처럼 고정된 개념이 아니라, “각각 다른 무기”를 생성해야 하므로 class가 적합!

 

enum과 class를 함께 사용하기

📌 enum을 활용해 특정 클래스의 속성을 제한할 수도 있음

예제: 무기 타입을 enum으로 제한

public enum WeaponType {
    SWORD, BOW, STAFF
}

public class Weapon {
    private String name;
    private int damage;
    private WeaponType type; // ✅ 무기 타입을 enum으로 제한

    public Weapon(String name, int damage, WeaponType type) {
        this.name = name;
        this.damage = damage;
        this.type = type;
    }

    public void attack() {
        System.out.println(name + " (" + type + ") 공격! 데미지: " + damage);
    }
}

public class Main {
    public static void main(String[] args) {
        Weapon sword = new Weapon("전사의 검", 50, WeaponType.SWORD);
        Weapon bow = new Weapon("궁수의 활", 30, WeaponType.BOW);

        sword.attack();  // 출력: 전사의 검 (SWORD) 공격! 데미지: 50
        bow.attack();    // 출력: 궁수의 활 (BOW) 공격! 데미지: 30
    }
}