gony-dev 님의 블로그

[Trouble Shooting] Restricted Identifier 본문

TroubleShooting

[Trouble Shooting] Restricted Identifier

minarinamu 2024. 12. 4. 14:27

학과 프로젝트를 마치고 보수 작업을 이어나가기 위해 클래스별로 하나씩 살펴보던 와중,
엔티티 클래스에서 sonarlint가 한 가지 이슈를 발견했다.

 

실행 과정에는 Exception이 발행할 만큼의 문제는 아니지만, 충돌 가능성이 충분히 일어날 만해서 글을 끄적여 본다.
이는 내가 만들었던 엔티티 클래스이다. 여러분도 찾아 보시길 바란다.

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "MEETING")
public class Meeting extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "meeting_id")
    private Long id;

    @NotNull
    @Size(min = 1, max = 50)
    @Column(nullable = false, length = 50)
    private String title;

    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Column(name = "date_column", length = 10, nullable = false)
    private LocalDate date;

    @Size(max = 3)
    @Column(name = "day_column", length = 5)
    private String day;

    @NotNull
    @Size(max = 1000)
    @Column(length = 1000)
    private String extraContent;

    //@NotNull
    @Size(max = 5000)
    @Column(length = 5000)
    private String summary;

    //@NotNull
    @Size(max = 500)
    @Column(length = 500)
    private String recommendKeyword;

    //@NotNull
    @OneToOne(mappedBy = "meeting")
    @JoinColumn(name = "record_id")
    private Recorder record;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    @OneToMany(mappedBy = "meeting")
    private List<MeetingMembers> meetingMembers = new ArrayList<>();

    public Meeting(String title, LocalDate date, String extraContent, Recorder record, Team team) {
        this.title = title;
        this.date = date;
        this.extraContent = extraContent;
        this.recorder = recorder;
        this.team = team;
    }

    @Builder
    public static Meeting withFile(String title, LocalDate date, String extraContent, Recorder record, Team team) {
        return new Meeting(title, date, extraContent, record, team);
    }

    @Builder
    public static Meeting withoutFile(String title, LocalDate date, String extraContent, Team team) {
        return Meeting.builder()
                .title(title)
                .date(date)
                .extraContent(extraContent)
                .team(team)
                .build();
    }

 

찾았다면 당신은 천재!

문제는 record라는 변수였다. 소나린트에서 발행한 내용은 다음과 같다.

 

요약하자면, "기술적으로는 가능할지 몰라도 제한된 식별자를 사용하는 것은 하지 말아야 한다. 이는 코드에 혼란을 야기할 수 있기에 모든 Java 버전에 적용된다. 추가적으로 var이나 yield 같은 식별자도 마찬가지로 사용하지 않을 것을 당부한다."라는 내용이다.

 

"당연한 거 아니야?"

맞다. 이는 당연한 말이다. 하지만 무심코 지나칠 수 있는 작은 문제이기에 왜 사용하면 안되는 지에 알아보자!


변수 이름으로 사용하면 안되는 식별자들

  • Java에서는 특정 키워드와의 충돌을 방지하기 위해 제한된 식별자를 포함하여 예약어를 변수 이름으로 사용해서는 안된다.

1. Java 예약어

예약어는 이미 Java 언어에서 특정 용도로 사용되고 있는 단어로, 변수 이름으로 사용할 수 없다.

  • 데이터 타입 : int, double, float, long, char, boolean, void
  • 제어문 : if, else, when, switch, case, default, for, while, do, break, continue
  • 접근 제한자 : public, private, protected
  • 클래스 관련 : class, interface, enum
  • 기타 키워드 : package, import, new, try, catch, throw, static, final, super, this

2. 제한된 식별자

  • record, var, yield

3. 외부 예약어

해당 엔티티에는 date와 day라는 변수도 있는데, 이는 외부 라이브러리인 mysql의 예약어로 자칫하면 오류가 날 수 있다.

이 외에도 데이터베이스 도구의 예약어들을 사용하지 말자!

  • 그럼에도 불구하고 정 사용하고 싶다면, 백틱('')을 사용하거나 좀 더 구체적인 이름을 사용하자!
SELECT `date` FROM my_table WHERE `date` = '2024-12-04';
SELECT my_date FROM my_table

사용하면 안 되는 이유?

그렇다면 이것들을 왜 사용하면 안될까?

  1. 키워드 충돌 가능성
    • record의 경우, 이를 그대로 사용한다면 컴파일러가 record를 키워드로 해석하기 때문에 충돌이 일어날 수 있다.
    • 실제로 boilerplate code를 줄이기 위해 record라는 클래스를 dto에서 많이 사용하고 있다. 만일 변수명을 record로 사용한다면 후에 충분히 오해의 소지가 있을 것이다.
  2. 가독성 저하
    • 프로젝트는 혼자서 하지 않는다. 따라서 다른 개발자가 제한된 식별자로 사용한 변수를 보았을 때 혼란을 야기할 수 있다.
    • record 키워드가 프로젝트에서 널리 사용된다면 변수과 구분하는데 충분히 어려움을 겪을 수 있다.

해결 방안

그리하여 나는 이 변수명을 다음과 같이 수정하였다.

이는 충돌이 나지 않는 변수로 원만하게 흘러갔다:)

@Builder
public static Meeting withFile(String title, LocalDate date, String extraContent, Recorder recorder, Team team) {
    return new Meeting(title, date, extraContent, recorder, team);
}

'TroubleShooting' 카테고리의 다른 글

[RDS] Failed to determine a suitable driver class  (0) 2024.12.23
[Spring] Page Interface의 직렬화  (2) 2024.11.14