Skip to content

hotfix: trim & 학기별 과목 정리#83

Merged
KimGyeongLock merged 2 commits intomainfrom
30-feature-ranking
Jan 25, 2026
Merged

hotfix: trim & 학기별 과목 정리#83
KimGyeongLock merged 2 commits intomainfrom
30-feature-ranking

Conversation

@KimGyeongLock
Copy link
Owner

.

@gemini-code-assist
Copy link

Summary of Changes

Hello @KimGyeongLock, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 과목 랭킹 서비스의 정확성과 사용자 친화성을 향상시키기 위한 중요한 개선 사항을 포함합니다. 특히, 과목명에 존재하는 미묘한 차이(예: 공백)로 인해 동일한 과목이 분리되어 집계되는 문제를 해결하고, 전공 로드맵 데이터의 정확성을 높여 전반적인 데이터 일관성을 강화했습니다.

Highlights

  • 과목명 정규화 및 병합 로직 추가: 공백을 무시하고 동일한 과목명을 가진 과목들을 합산하여 랭킹을 계산하는 새로운 로직(toTop10Merged)이 CourseRankingService에 추가되었습니다. 이는 '웹서비스개발'과 '웹 서비스 개발'처럼 공백 유무만 다른 과목들을 하나의 항목으로 처리하여 정확한 랭킹을 제공합니다.
  • 표시명 선택 로직 개선: 병합된 과목들의 표시명을 결정할 때, 더 길고 공백을 포함하여 가독성이 좋은 이름을 우선적으로 선택하도록 chooseDisplay 유틸리티 메서드가 추가되었습니다.
  • 전공 로드맵 데이터 수정: major_roadmap.json 파일에서 일부 과목의 학기 정보가 수정되었고, 과목명에서 불필요한 부가 정보(예: '(전산전공)')가 제거되거나 간결하게 변경되었습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이번 PR은 과목 랭킹을 집계할 때 공백 유무에 따라 다른 과목으로 집계되던 문제를 해결하고, major_roadmap.json의 학기별 과목 정보를 최신화하는 중요한 수정을 포함하고 있습니다.
toTop10Merged 메서드를 도입하여 과목명을 정규화하고 수강 횟수를 합산하는 로직을 추가한 점이 인상적입니다. 이를 통해 데이터의 정확성을 크게 향상시켰습니다.

리뷰에서는 주로 코드의 가독성과 재사용성을 높이기 위한 몇 가지 제안을 드렸습니다.

  • Agg 내부 클래스를 Java record로 전환하여 코드를 간소화
  • ComparatorMap.merge를 사용하여 로직을 더 선언적으로 표현
  • 여러 곳에서 중복되는 norm 메서드를 공통 유틸리티로 분리

추가로, PR 설명이 비어있습니다. 스타일 가이드(134-137 라인)에 따라 변경 내용, 이유, 관련 이슈 등을 작성해주시면 다른 팀원들이 변경 사항을 이해하는 데 큰 도움이 될 것입니다.

전반적으로 기능 개선을 위한 좋은 커밋이라고 생각합니다. 수고하셨습니다!

Comment on lines +176 to +179
private static String norm(String s) {
if (s == null) return "";
return s.trim().replaceAll("\\s+", "");
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

norm() 유틸리티 메서드가 MajorRoadmapIndex 클래스에도 동일하게 존재합니다. 코드 중복을 피하고 재사용성을 높이기 위해, 이 메서드를 공통 유틸리티 클래스로 추출하는 것을 고려해 보세요.
스타일 가이드 25번 라인에 따라 com.gradu.common 패키지 아래에 StringUtil 같은 클래스를 만들어 관리하면 좋을 것 같습니다.

예시:

// in com.gradu.common.util.StringUtil.java
public final class StringUtil {
    private StringUtil() {}

    public static String normalize(String s) {
        if (s == null) return "";
        return s.trim().replaceAll("\\s+", "");
    }
}
References
  1. 공통 유틸리티는 com.gradu/common/ 패키지에 위치시켜야 합니다. norm() 메서드는 여러 곳에서 사용되므로 공통 유틸리티로 분리하는 것이 좋습니다. (link)

Comment on lines +108 to +122
for (var r : rows) {
String raw = r.getName();
String key = norm(raw);
if (key.isBlank()) continue;

Agg prev = map.get(key);
long nextCount = (prev == null ? 0L : prev.takenCount) + r.getTakenCount();

// ✅ 대표 표기명: 사람이 읽기 편한 쪽(공백 포함, 더 긴 것) 우선
String nextDisplay = (prev == null)
? safe(raw)
: chooseDisplay(prev.displayName, safe(raw));

map.put(key, new Agg(nextCount, nextDisplay));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

for 루프 내의 집계 로직을 Map.merge() 메서드를 사용하여 더 간결하게 개선할 수 있습니다. merge를 사용하면 키 존재 여부를 확인하고 값을 계산하여 업데이트하는 과정을 하나의 메서드 호출로 처리할 수 있어 코드 가독성이 향상됩니다. (이 제안은 Aggrecord라고 가정합니다.)

        for (var r : rows) {
            String raw = r.getName();
            String key = norm(raw);
            if (key.isBlank()) continue;

            var newAgg = new Agg(r.getTakenCount(), safe(raw));
            map.merge(key, newAgg, (oldAgg, agg) -> new Agg(
                    oldAgg.takenCount() + agg.takenCount(),
                    chooseDisplay(oldAgg.displayName(), agg.displayName())
            ));
        }

Comment on lines +125 to +129
.sorted((a, b) -> {
int c = Long.compare(b.takenCount, a.takenCount);
if (c != 0) return c;
return a.displayName.compareTo(a.displayName);
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Comparator 체이닝을 사용하면 정렬 로직을 더 간결하고 읽기 쉽게 표현할 수 있습니다. Comparator.comparingLong()thenComparing()을 활용하여 다중 조건 정렬을 구현하는 것을 권장합니다. (이 제안을 적용하려면 Agg 클래스를 record로 변경하거나 getter를 추가해야 합니다.)

                .sorted(Comparator.comparingLong(Agg::takenCount).reversed()
                        .thenComparing(Agg::displayName))

Comment on lines +193 to +201
private static final class Agg {
final long takenCount;
final String displayName;

private Agg(long takenCount, String displayName) {
this.takenCount = takenCount;
this.displayName = displayName;
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Agg 클래스는 불변 데이터 컨테이너(immutable data carrier)의 역할을 합니다. Java record를 사용하면 보일러플레이트 코드(생성자, getter, equals, hashCode, toString) 없이 클래스를 더 간결하게 정의할 수 있습니다.
프로젝트 스타일 가이드 62번 라인("가독성 향상에 도움이 되면 record ... 사용")에서도 record 사용을 권장하고 있습니다.

    private record Agg(long takenCount, String displayName) {}
References
  1. 가독성 향상에 도움이 된다면 Java 21의 record와 같은 최신 기능을 사용하는 것을 권장합니다. Agg 클래스는 record로 변환하기에 좋은 후보입니다. (link)

@sonarqubecloud
Copy link

@KimGyeongLock KimGyeongLock merged commit 4e98640 into main Jan 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant