더 나은 개발자로 성장하는 방법, 에러 메시지를 읽으세요.
에러의 원인을 직접 분석하고 해결할 수 있는 개발자로 성장하려면 에러 메시지를 읽는것부터 시작하세요.
자바는 에러가 발생하면 메소드 콜 스택 트레이스와 함께 Exception이 던진 메시지를 출력해 줍니다. 이런 장치를 활용해서 자바 기반의 여러 라이브러리나 프레임워크도 꽤나 유용한 정보를 제공하고 있죠.
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-08-14 22:06:13.208 ERROR 10285 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accountRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.Optional me.g1moon.springbootsecurity2.account.AccountRepository.findByUserName(java.lang.String)! No property userName found for type Account! Did you mean 'username'?
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1827) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1265) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
... (중략) ...
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:97) ~[spring-data-commons-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:89) ~[spring-data-jpa-2.3.3.RELEASE.jar:2.3.3.RELEASE]
... 49 common frames omitted
Process finished with exit code 1
스프링 부트 개념과 활용 강좌 수강생 중 한분께서 위와 같은 에러가 발생했는데 이유를 모르겠다고 질문을 보내왔습니다.

초보적인 개발자는 이런 기다란 에러 메시지를 만나면 당황하고 에러 메시지를 읽지도 않고 '아 이거 왜 안돼지?'라고 상상속으로 빠져들며 에러 원인을 추측하기 시작합니다.
단서는 에러 메시지에 있습니다.
우선 저런 메시지를 읽을 때는 덩어리 중에서 일부를 거르고 진짜 필요한 부분만 찾아보면 됩니다. 일단 메소드 콜 스택 즉 어디서 어떤 메소드를 호출하고 또 거기서는 어떤 메소드를 호출했는지 쭉~~ 나와있습니다. at 으로 시작하고 있죠. 가량 A.a() 메소드에서 B.b()를 호출하다 에러가 났다면 보통 이런식으로 쌓여있습니다.
at B.b()
at A.a()
스택에서 제일 위에있는 메소드에서 에러를 던진거죠. 그 아래있는 메소드들은 최상단에 있는 메소드를 실행하기까지 거쳐온 메소드들 목록이구요. 그리고 그 최상단 스택 바로 위에 어떤 Exception이 발생했으며 그당시 발생한 에러메시지가 있습니다.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accountRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.Optional me.g1moon.springbootsecurity2.account.AccountRepository.findByUserName(java.lang.String)! No property userName found for type Account! Did you mean 'username'?
지금 보고 있는 에러 로그에서는 BeanCreationException
이 발생했고 즉 빈을 만들다가 에러가 발생했고, 빈을 만들다 에러가 발생한 이유는 IllegalArgumentException
이 발생했기 때문인데, 이 에러는 다시 public abstract Optional findByUserName(String)
이라는 메소드에 대한 쿼리를 만들다가 실패했기 때문이라 적혀있습니다. 마지막에 보면 Account
에 userName
이라는 프로퍼티는 없는데 혹시 username
을 사용하려던건 아니냐고 까지 적혀있네요.
즉 findByUsername
으로 메소드 이름만 교체하면 해당 메소드 이름으로 쿼리가 잘 생성되고 문제는 해결되겠죠. 하지만, 제가 그렇게 답을 알려드린다 한들 에러 메시지를 읽지 않는 나쁜 습관을 고치지 않는다면 장기적으로 무슨 소용이 있을까요?
에러 메시지는 읽으라고 있는 겁니다. 제발 읽으세요.