앞으로는 전체적인 트러블 슈팅과 코드 리뷰를 받으면서 그 날 겪었던 문제 사항들에 대해서 적고, 지식과 이론과 관련된 부분은 추가적으로 좀 더 깊게 정리해서 날을 잡아서 정리하고자 한다. 해야할게 많기도 하고 블로그 포스팅에 너무 많은 리소스를 쏟게 되면 그 만큼 학습량이 줄어든다는 부분도 있기 때문이다. 단, 당일 회고가 아닌 나의 발전을 확인하는 회고는 주 1회 일요일날 작성하는게 좋을 것 같다.
Lombok
오늘 팀원에게 다음과 같은 오류가 발생했다.
error: constructor Numbers in class Numbers cannot be applied to given types;
Numbers nums = new Numbers(Stream.generate(() -> faker.number().randomDigitNotZero())
해당 내용을 보고 생성자 문제인가 접근을 해보니, @AllArgsConstructor 를 사용하고 있는 모습을 볼 수 있었다. 우선 해당 코드를 상속하고 있는 친구에 대해 기본 생성자가 존재하지 않는 경우 일 수도 있다고 봤으나, 해당 코드에는 기본 생성자의 여부는 크게 상관이 없었다.
해결과정 1
두 번째로는 Annotation Processors 에서 Enable annotation processing이 체크가 되어있는지를 확인했는데 체크가 안 되어있음을 확인 할 수 있었다.
해결과정 2
해당 영역을 체크하고 나서도 동일한 오류가 발생하였다. 혹시 몰라서 Build Tools 를 Intellij 로 변경해봤다.
해당 작업 이후에는 코드가 정상적으로 실행하는 모습을 볼 수 있었다. 하지만 Gradle과 Intellij 의 차이는 증분 빌드에서 나타나는데 뭔가 변경사항이 있는데 제대로 불러오지 못하는 상황을 의미하는 것 같았다. Gradle build와 Intellij IDEA Build 의 차이는 여기 에서 확인이 가능하다.
해결과정 3
따라서 혹시 build.gradle 에 설정이 잘 못 되어있는지 확인해봤다.
dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation 'com.github.javafaker:javafaker:1.0.2'
compileOnly 'org.projectlombok:lombok:1.18.28'
}
코드는 다음과 같은 상황으로 구성이 되어있었다. 여기까지는 크게 큰 문제를 못 느꼈는데 롬복 세팅 관련해서 찾아보니 중요한 것 하나가 빠졌음을 확인 할 수 있었다. annotationProcessor 'org.projectlombok:lombok:1.18.28' 이 빠져있는 상황이었다.
이어서 해당 내용을 추가하고 다시 재 빌드하니 정상적으로 동작함을 확인 할 수 있었다. 팀원들과 흔히 놓칠 수 있는 부분에 대해서 트러블 슈팅으로 답을 찾아가는 과정이 너무 재미있었다!
Enum 최적화
인자가 연산자가 맞는지를 확인하기 위해서 enum 에서 다음과 같은 메서드를 사용하였다.
public static boolean isOperator(String symbol) {
return Arrays.stream(Operator.values())
.anyMatch(operator -> operator.symbol.equals(symbol));
}
public static Operator getOperation(String symbol) {
return Arrays.stream(Operator.values())
.filter(operator -> operator.symbol.equals(symbol))
.findFirst()
.orElseThrow(() -> new WrongOperationException("잘못된 연산자가 들어왔습니다." + symbol));
}
지금은 연산자를 5개 밖에 사용하지 않은 상황이라 많은 리소스가 소모되지 않지만 연산자의 개수가 늘어날수록 O(n) 만큼의 시간복잡도가 매번 수행을 하게 될 것이다. 그리고 이를 해결하기 위해 O(1) 만큼의 시간복잡도로 만드는 방법을 코드 리뷰를 통해 enum의 내부 필드에 대한 최적화 방식에 대해서 알아보는 것이 좋을 것 같다는 코드리뷰를 받게 되었다.
enum 내부에서 Map 을 생성
다음과 같이 수정 불가능한 Map을 생성이 가능하다.
private static final Map<String, Operator> OPERATOR_MAP =
Collections.unmodifiableMap(Arrays.stream(values())
.collect(Collectors.toMap(Operator::getSymbol, Function.identity())));
실제로 enum 자체도 컴파일 이후 한번만 생성이 되기 때문에 내부에서도 map을 static final 을 선언하여, 수정불가능하고 한 번만 생성이 되게끔 하였다. 그리고 map의 key로 각 symbol에 따라서 자기 자신을 호출하도록 map을 구성하였다.
그리고 이제는 들어오는 인자에 따라 확인하는 과정에서 다음과 같이 코드를 수정 할 수 있다.
public static boolean isOperator(String symbol) {
return OPERATOR_MAP.containsKey(symbol);
}
public static Operator getOperation(String symbol) {
if (OPERATOR_MAP.containsKey(symbol))
return OPERATOR_MAP.get(symbol);
throw new WrongOperationException("잘못된 연산자가 들어왔습니다." + symbol);
}
이전 코드에 비해서 상당히 깔끔해지기도 했고, 시간복잡도 또한 Map의 탐색은 O(1) 만큼 소요되기때문에, 성능이 개선됨을 확인 할 수 있다. 이러한 방식은 상당히 임팩트있고 성능적인 부분도 개선 할 수 있어서 컬쳐쇼크 수준이었다.
회고
오늘은 프리팀 팀원분들을 처음 실제로 만나게 되는 날이였다. 아쉽게도 민희님은 학교 시험으로 인해 스케줄을 비울 수 없어 함께하지 못해서 아쉽다. 직접 만나서 여러가지에 대해서 얘기도 나누고, 위처럼 트러블 슈팅도 하는 과정이 정말 너무 좋았다. 서로 모르는 부분에 있어서 바로바로 이러한 지식은 이게 맞지 않는지 이건 이렇게 하는 것이 좋지 않은지에 대한 얘기도 너무 생산성있는 대화여서 너무 좋았다.
여담이지만 다들 인물이 너무 좋으셔서 놀라기도 했다!
직접 만나서 대화를 해서 프리팀 기간동안 거의 붙어있으니 정도 많이 들긴 했는데 new 팀에서 다 떨어져야 한다는 사실이 너무 아쉬운 것 같다ㅠㅠ
'프로그래머스 데브코스' 카테고리의 다른 글
프로그래머스 데브코스 9일차 - Static Inner 클래스를 사용해야 하는 이유, Optional orElse, orElseGet의 차이 (0) | 2023.06.12 |
---|---|
프로그래머스 데브코스 8일차 - Null 제거와, Pattern 객체 캐싱 (1) | 2023.06.11 |
프로그래머스 데브코스 6일차 - 전략패턴 (3) | 2023.06.08 |
프로그래머스 데브코스 5일차 (0) | 2023.06.08 |
프로그래머스 데브코스 4일차 - 인터페이스 (0) | 2023.06.07 |