본격적으로 Kotlin/Spring을 배우게 되는 날이 왔다. 주특기 챕터라고 적을 정도로 사실 제일 핵심이 되는 부분일 거고 내가 안해본 영역이라 여기서부터는 진도를 놓치지 않는 것이 중요해서 정보를 더욱 더 적극 사용할 것 같다.
우선 분반도 진행하게 됐는데 사실 DI, API, MVC 같은 것도 여태 개념을 제대로 모른 채로 썼다 봐야하고 얼추 아는 정도의 지식으로 챌린지 반을 지원하는게 맞나 싶었지만 지금 튜터님도 계실 때 빠르게 채찍질해서 궤도에 올라볼까 싶은 생각이 들어서 챌린지로 지원하게 됐다.
(매니저님이 모르겠으면 스탠다드 도강하라고 추천도 해주셔서 그렇게 할 것 같다.)
새로운 팀도 배정이 됐는데 개발을 해보셨거나 즐기신 분들도 계셔서 이번엔 미니튜터 느낌보다는 그냥 말 많은 팀원이 될 것 같다. 이게 수다를 줄여야 하는데 MBTI I인거 치곤 꽤 많이 나대고 있지 않나? 싶은 생각이 든다.
팀 프로젝트는 여전히 없지만 스크럼, 회고에서 자기가 듣는 강의의 내용을 정리해서 전달하면 또 좋은 공유가 되지 않을까 싶고 나도 한번 제안 드려볼 생각이다.
특히 두루두루 연락이 닿는 사람들 끼리는 강의에서 들은 내용 있으면 도강이 가능하지만 핵심도 쉽게쉽게 정리하고자 한다.
숫자 야구 피드백은 알고리즘적 부분보다는 테스트 코드에서 대부분 튀어나왔다. 테스트 코드를 딱 강의에서 본 만큼만 작성했고 추가로 공부 안했으니 당연히 까일만 했고 관련 키워드나 레퍼런스도 던져주셨으니 약간 수정을 가하는 시간을 가졌다.
- Kotest BDD 기반에서 gwt는 명시를 잘 해줘야하고 관련없는 테스트 시나리오는 분리하자
- 풍부한 테스트 데이터를 위해서 JUnit의 parameterizedTest, Kotest의 forAll 키워드처럼 범위 기반으로 테스트하자
- AutoParams 같은 라이브러리도 참고해보자
- 성공/실패에 대한 테스트를 응답 메시지로 처리하지 말고 Exception 기반으로 Enum handling 해라
- 코드 리딩을 할 때 함수도 접근제어 기준으로 분류해서 봐야하는 내용 우선으로 배치해두면 리딩하기 좋은 구조가 된다.
로직이었다면 공부했거나 처리했을 내용들인데 처음 제대로 써보는 테스트 코드라고 성의없이 적은 부분들을 많이 피드백해주셔서 로직 부분이랑 크게 다른 개념 없이 접근해도 되겠다는 생각이 들었다.
우선 기초적인 개념 부분을 듣고 Spring에서 자주 쓰이는 Web(Controller), Service, Repository Layer 계층과 나누는 이유, 거기에 쓰는 DTO와 Entity의 개념을 간단하게 들었다.
DTO와 Entity는 앱에서 짜던 모델들의 모양 구분새가 왜 나왔는지 느낌이 왔고 Kotlin 에서는 data class를 자주 쓰게 되긴 하겠구나도 느껴졌다.
간만에 모르는 개념 부분이 나온 거라 GPT한테도 많이 물어보며 진행했고 아직 써보진 않아서 작성까진 헷갈릴 수도 있지만 생각보다 구조 자체는 직관적이고 익숙하다고 느껴지기도 했다. 다만 수많은 Annotation 들은 제대로 외워야지 써먹을 수 있을 것 같다.
"명예의 전당"이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.
이 프로그램에서는 매일 "명예의 전당"의 최하위 점수를 발표합니다. 예를 들어, k
= 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.
명예의 전당 목록의 점수의 개수 k
, 1일부터 마지막 날까지 출연한 가수들의 점수인 score
가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.
fun solution(k: Int, score: IntArray): IntArray {
val scoreList = ArrayList<Int>()
val lastScoreList = ArrayList<Int>()
score.forEach {
scoreList.add(it)
scoreList.sortDescending()
if (scoreList.count() > k) { scoreList.removeLast() }
lastScoreList.add(scoreList.last())
}
return lastScoreList.toIntArray()
}
처음에는 Collection을 안쓰고 lastScore 만 기록해서 작은 값을 기록하면 되는게 아닌가? 싶었는데 그렇게 호락호락한 함정문제일리는 없었고 일단 정석대로 Collection으로 저장부터 하고 시작했다.
평소대로 mutableList를 쓰려다가 GPT 출처로는 add, remove의 속도가 가장 빠르고 탐색 또한 log 시간복잡도를 지닌다는 ArrayList로 작성했는데 딱히 큰 문제는 없었다.
다 적고 고민하는 점은 매 순회마다 sort를 하지 않고 작성할 방법이 없는가? 였다. 지난 번에 알아본 TreeSet 같은 정렬된 Collection은 중복을 허용 안해서 쓸 수 없었고 다른 방법으로 찾은 건 PriorityQueue<Int>()
였는데 이 또한 로그 시간복잡도를 기록하는 건 똑같아서 ArrayList랑 크게 차이는 없을 것 같아 그대로 제출했다.
실제로 다들 다양하게 구현하긴 하셨지만 PriorityQueue 비율이 제일 높아보였다. 이걸 보면 아무래도 ArrayList 보단 효율적이었다고 판단이 되는데 한번 바꾸고 제출해볼걸 싶었다.