Today's Codekata
class Solution {
public int solution(int[] absolutes, boolean[] signs) {
int answer = 0;
for (int i = 0; i < absolutes.length; i++) {
if (signs[i]) {
answer += absolutes[i];
} else {
answer -= absolutes[i];
}
}
return answer;
}
}
class Solution {
public String solution(String phone_number) {
String answer = "";
for (int i = 0; i < phone_number.length() - 4; i++) {
answer += "*";
}
for (int i = phone_number.length() - 4; i < phone_number.length(); i++) {
answer += phone_number.charAt(i);
}
return answer;
}
}
반복문을 쓸 때 항상 i = 0으로 시작하던 습관이 있었는데, 오늘은 특정 범위만 반복하기 위해 i = phone_number.length() - 4로 시작해보면서 사고가 열렸다. 특히 배열의 일부만 처리할 때 어떻게 할 수 있을지 고민해보는 것이 좋을 것 같다. 그리고 charAt()을 통해서 문자열에서도 배열처럼 문자를 하나씩 꺼낼 수 있다는 걸 체감했다.
SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME, '%Y-%m-%d') AS '날짜'
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;
SELECT DR_NAME, DR_ID, MCDP_CD, DATE_FORMAT(HIRE_YMD, '%Y-%m-%d') AS HIRE_YMD
FROM DOCTOR
WHERE MCDP_CD LIKE 'CS' OR MCDP_CD LIKE 'GS'
ORDER BY HIRE_YMD DESC, DR_NAME ASC;
DATE_FORMAT(날짜컬럼, '포맷형식') 함수는 날짜와 시간을 원하는 형식의 문자열로 변환할 때 사용한다. 포맷형식에서 대소문자에 따라 전혀 다른 출력 결과가 나오게 된다.
키오스크 프로젝트
public static void printDiscount() {
System.out.println("\n할인 정보를 입력해주세요.");
System.out.println("1. " + VETERAN.type + " : " + VETERAN.displayRate);
System.out.println("2. " + SOLDIER.type + " : " + SOLDIER.displayRate);
System.out.println("3. " + STUDENT.type + " : " + STUDENT.displayRate);
System.out.println("4. " + REGULAR.type + " : " + REGULAR.displayRate);
}
public static BigDecimal applyDiscount(BigDecimal totalPrice, int selectedDiscount) {
if (selectedDiscount == 1) {
return totalPrice.subtract(totalPrice.multiply(VETERAN.getRate()));
}
if (selectedDiscount == 2) {
return totalPrice.subtract(totalPrice.multiply(SOLDIER.getRate()));
}
if (selectedDiscount == 3) {
return totalPrice.subtract(totalPrice.multiply(STUDENT.getRate()));
}
return totalPrice;
}
위 코드로도 현재 동작하는데는 전혀 문제가 없지만 키오스크 할인 메뉴에 '신규 회원 할인'이라거나 '특별 할인!' 이런 것들을 추가하고 싶어도 현재 구조에선 너무 재사용성이 떨어진다고 생각돼서 Enum의 메서드들에 대해 살펴보고 리팩토링할 방향을 찾아봤다.
Enum 메서드
| 메서드 | 설명 | 리턴 타입 |
| name() | 열거 객체의 문자열을 리턴 | String |
| ordinal() | 열거 객체의 순번(0부터 시작)을 리턴 | int |
| compareTo() | 열거 객체를 비교해서 순번 차이를 리턴 | int |
| valueOf(String name) | 문자열을 입력받아서 일치하는 열거 객체를 리턴 | enum |
| values() | 모든 열거 객체들을 배열로 리턴 | enum[] |
// name() : Discount.VETERAN 이라는 열거 상수 이름을 문자열로 얻음
Discount d1 = Discount.VETERAN;
String name = d1.name();
System.out.println(name); // VETERAN 출력
// ordinal() : 열거 객체의 순번(0부터 시작)을 리턴
Discount d2 = Discount.STUDENT;
int position = d2.ordinal(); // enum 선언 순서에서의 인덱스 값
System.out.println(position); // 2 (VETERAN, SOLDIER, STUDENT ← 3번째로 선언했다.)
// compareTo() : 두 열거 객체의 순번 차이를 계산
Discount a = Discount.SOLDIER; // ordinal 1
Discount b = Discount.REGULAR; // ordinal 3
System.out.println(a.compareTo(b)); // -2
System.out.println(b.compareTo(a)); // 2
// valueOf() : 문자열 "STUDENT"를 기반으로 Discount 열거 객체를 가져옴
Discount d3 = Discount.valueOf("STUDENT");
System.out.println(d3.getType()); // 학생
System.out.println(d3.getDisplayRate()); // 3%
// values() : 모든 열거 객체들을 배열로 리턴
Discount[] allDiscounts = Discount.values();
System.out.println(Arrays.toString(allDiscounts)); // [VETERAN, SOLDIER, STUDENT, REGULAR] 출력
내 Enum 클래스에 상수들을 활용해서 위처럼 예시를 만들어봤다. 이 메서드들 중에 나는 values()를 활용해서 상수들을 배열로 만들어서 그 배열을 순회하면서 원하는 값을 호출하는 방식으로 만들어줘야할 것 같다.
public static void printDiscount() {
System.out.println("\n할인 정보를 입력해주세요.");
int index = 1;
for (Discount discount : Discount.values()) {
System.out.println(index++ + ". " + discount.type + " : " + discount.displayRate);
}
}
public static BigDecimal applyDiscount(BigDecimal totalPrice, int selectedDiscount) {
if (selectedDiscount > 0 && selectedDiscount <= Discount.values().length) {
return totalPrice.subtract(totalPrice.multiply(Discount.values()[selectedDiscount - 1].getRate()));
} else {
throw new IllegalArgumentException("잘못된 번호를 입력하셨습니다.");
}
}
- 외부 -
int selectedDiscount = sc.nextInt();
totalPrice = Discount.applyDiscount(totalPrice, selectedDiscount);
처음에는 할인 종류마다 따로 코드를 써줘야 할 것 같아서 뭔가 복잡하게 느껴졌는데, enum을 활용하니까 생각보다 훨씬 쉽게 관리할 수 있었다. 할인 항목을 추가할 때도 기존 코드를 손댈 필요 없이 열거형 안에만 정의해주면 되고, 특히 values() 메서드를 쓰니까 배열처럼 다룰 수 있어서 조금이나마 익숙한 방식으로 코딩할 수 있었다. 오입력 처리도 enum 안에서 하도록 수정하니 외부 코드가 아주 깔끔해보인다. 이렇게 하나하나 정리하면서 배우는 게 재밌고, 다음엔 조금 더 복잡한 구조도 한번 직접 구현해보고 싶다는 생각이 들었다.
프로젝트를 마치며
처음엔 단순한 콘솔 키오스크를 구현한다는 목표였지만, 진행하면서 자바의 클래스 구조나 enum, Stream, BigDecimal 등 다양한 기능들을 직접 써보며 배운 점이 많았다. 사용자 입력 처리부터 예외 방지, 할인 적용 로직까지 하나하나 만들어가다 보니 단순히 동작하는 코드를 넘어서, 구조와 재사용성을 어떻게 고려해야 하는지 꾸준히 고민하게 되었다. 그 과정에서 작성했던 코드들을 여러 차례 수정해가며 '유지, 보수' 라는 것이 어떤 작업인지 조금이나마 이해하게 되었다. 특히 클래스를 기능별로 나누고, 반복되는 코드 구조를 메서드로 분리하면서 역할과 책임을 명확히 하려 했던 시도가 기억에 남는다. 코드를 리팩토링하면서 흐름이 점점 더 깔끔해지는 걸 볼 때마다, 개발이라는 작업 자체가 점점 더 재미있게 느껴졌다. 물론 가독성만 생각하고 분리했던 메서드를 다시 수정하는 일도 있었지만, 그런 시행착오 덕분에 더 나은 방향을 찾을 수 있었다. 이번 프로젝트는 단순한 학습을 넘어서, 내가 무엇을 만들려고 하는지, 어떤 기준으로 기능을 담을지 스스로 질문해보는 계기가 되었다. 그리고 코드를 쓰는 것뿐만 아니라, 누가 봐도 어떤 목적으로 만든 프로젝트인지 알 수 있도록 정리하고 문서화하는 과정 역시 개발의 일부라는 걸 느끼게 되었다. 다음엔 내가 쓴 코드를 다시 봤을 때, 나 스스로도 확실히 성장했다고 느낄 수 있으면 좋겠다.