본문 바로가기
etc

[KOSTA 프로젝트] 02. JPA와 ArrayIndexOutOfBoundsException

by Zㅣ존수빈zz 2023. 12. 1.

프로젝트 첫 번째 사이클로 Employee CRUD를 맡아 금방 끝내고 다음 사이클로 넘어가려 했는데

이 에러가 발목을 이틀이나 잡았다.

근본적인 이유를 모르니 Chat CPT에게 질문하는 것도 한계가 있었고,

결국 다른 기능을 먼저 개발하다 보니 어느새인가 에러가 해결되어 있었다.

 

그러니까 나의 경우는 ArrayIndexOutOfBoundsException이 발생한 이유가 Employee Entity에 있는

Enum클래스 멤버변수 때문이었다. 정확하게는 내부에 아무 내용도 없는 Enum 클래스이다.

이 변수와 JPA가 만나 ArrayIndexOutOfBoundsException을 발생 시킨 것이기 때문에

다른 기능을 개발하며 Enum클래스에 내용을 넣으니 알아서 해결된 것이었다.


초기 설정

 

1. Employee 엔티티를 생성했다.

2. JpaRepository를 상속받은 EmpRepository 인터페이스를 생성했다.

3. EmpService를 생성하여 findAll()을 사용한 모든 Employee 조회 메서드 getAllEmp()를 만들었다.

4. Controller에 index페이지로 연결되도록 GetMapping을 하고 EmpService의 getAllEmp()를 사용해 Model로 넘겼다.

5. 초기 데어터값이 있으면 좋겠다고 생각해 CommandLineRunner를 상속한 InitData 클래스를 생성했다.

6. InitData 클래스에 반복문을 사용하여 자동으로 5개의 초기 Employee값을 저장하는 메서드를 작성했다.

7. 애플리케이션을 구동하자 정상적으로 작동했으며 DB에서 직접 확인할 수 있었다.


에러 발생

 

여기서  getAllEmp() 메서드를 사용하는 페이지로 넘어가자  ArrayIndexOutOfBoundsException가 발생했다.

 

정해진 배열의 크기보다 크거나 음수 index에 대한 요청이 있으면 발생하는 에러인데,

저 'Index 0 out of bounds for length 0' 문구를 보니 배열이 0인 Array를 출력하거나 건드려서 발생한 것 같았다.

그래서 직접 findAll()한 List<Employee>의 size를 출력해 봤더니 0이긴 했다..

아니 근데 나는 DB에서 조회할 수 있는데!!!! 왜 읽어오질 못하는 건데!!!!

 

그래서 그 다음엔 JpaRepository가 문제라고 생각했다.

어떤 설정을 빼먹었는지, 사실 플러그인이나 디팬던시가 더 필요한데 몰랐던 건지,

다 찾아봐도 내가 뭘 잘못했는지 알 수 없었다.

 

정말 이틀간 이것만 찾았는데도 알 수가 없어서 일단 구현을 계속했다.

그 다음엔 사원을 등록하는 페이지를 만들 생각이라 비워두었던 Position이라는 Enum 클래스를 완성했고

그제서야 에러가 안뜨고 제대로 작동되기 시작했다.

문제는 비워두었던 Enum 클래스였다...하..

Chat GPT도 직접적으로 Enum클래스와 JPA에 관련하여 물어보니 대답을 해주더라

 

요약해보면 기본적으로 JPA에서 Enum을 매핑할 때,
EnumType.ORDINAL이라는 기본 매핑 전략을 사용한다고 한다.
그래서 0부서 숫자로 DB에 저장되는데 DB에 저장된 값과 기대한 값이 다를 경우에ArrayIndexOutOfBoundsException이 발생할 수 있다는 것이다.

그러니까 다시 말하면 Position 클래스가 비어 있기 때문에 Enum에 0도 매핑을 할 수가 없었다는 것이고, ArrayIndexOutOfBoundsException은 findAll()이 생성하는 List때문이 아니라 비어있는 Enum 클래스에 매핑을 하다 배열의 인덱스를 잘못 참조하여 발생한 에러라는 것이다.

 

그래서 일단 근본적인 해결법은 Enum클래스에 값을 넣는 것이었으며

만일 값이 있다고 해도 EnumType.ORDINAL일 경우 Enum 순서가 바뀔 때 오류가 발생할 수 있으므로

어느 방법을 선택하든, EnumType.STRING을 사용하면 오류의 가능성을 예방할 수 있다고 한다.

 

결론은

Enum 클래스를 비워두지 말고,

Enum 클래스 변수를 사용할 때에는 꼭 @Enumerated(EnumType.STRING) 애노테이션 붙이기!

 

 

 

 

 

 

댓글