프로젝트를 완성해 EC2에 서버를 배포했다. 깃허브를 연동해 EC2 리눅스에 프로젝트를 내려 받고 성공적으로 JAR 파일을 빌드하는데 성공했다. (여기까지도 2-3시간 걸린듯 하다. gradle이 빌드시에 롬복을 인식하지 못하는 상황이 발생해서 build.gradle에 아래와 같이 조치를 취한 후 아래와 같은 명령어로 빌드를 수행했다.)
/** 에러가 발생하는 build.gradle */
...
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
...
/** 빌드 시에 롬복을 발견하지 못하는 에러를 해결한 build.gradle */
...
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// 아래의 dependencies를 추가
implementation 'com.google.code.findbugs:jsr305:3.0.2'
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
...
Build 명령어
./gradlew build -x test
("테스트는 제외하고 빌드하라." 왜인지 위의 의존관계를 추가해도 테스트는 오류가 나더라..)
빌드를 성공적으로 수행한 후 프로젝트를 EC2에서 띄웠다. 스프링부트가 실행됐다. 배포 성공...
EC2가 제공하는 도메인을 타고 크롬으로 배포된 프로젝트를 열어봤다. 어, 웬걸..? 특정 페이지들이 열리지 않는다. 아래의 에러 메세지와 함께..
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Jan 18 17 : 40 : 56 KST 2021
There was an unexpected error (type=Internal Server Error, status=500).
뭐지? 로컬에서는 잘만 돌아가는 프로젝트인데..?
원인
몇 시간을 붙잡고 있었다. 로컬을 다시 띄워보고, 다시 배포된 서버를 최신화해보고를 반복해도 해결이 되지 않았다. EC2와 리눅스에 익숙하지 않아 로그를 어떻게 보는지도 몰랐기 때문에 멘땅에 해딩하는 시간이 상당히 길었다. 그러다 우연히 리눅스 상에서 로그를 볼 수 있는 방법을 알게 되었는데, 로그에는 아니나 다를까 프로젝트를 하면서 늘 나를 괴롭히던 TemplateInputException이 적혀 있었다.
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [/login/login], template might not exist or might not be accessible by any of the configured Template Resolvers
진짜 끝까지 나를 괴롭히는구나.. 하는 생각으로 문제가 발생하는 html 페이지와 관련된 controller들을 살펴봤다. 그런데 이게 웬걸. 내 눈엔 아무래도 문제가 없는거 같은데..?
야인이 된 심정으로 웹 검색을 하기 시작했다. 검색어는 '배포 타임리프' 혹은 '배포 TemplateInputException' 정도였다. 그리고 마침내 몇시간의 좌절을 해결할 수 있는 실마리를 아래의 블로그에서 발견할 수 있었다.
https://dev-jwblog.tistory.com/40
블로그의 내용은 다음과 같았다. controller에서 return값에 "/xxx"와 같은 형태를 적을 경우, 리눅스는 이를 인식하지 못해 에러가 발생하고 화면에 접근하지 못할 수 있다.
해결
설마 하는 마음에 프로젝트의 controller를 조사하기 시작했다. 아니나 다를까, 화면 출력에 문제가 있었던 controller에는 어김없이 위와 같은 형태의 코드가 적혀 있었다. 즉, 예를 들면 login 화면이 출력이 되지 않았는데 login 화면을 라우팅해주는 LoginController는 이렇게 되어 있었던 것이다.
@GetMapping("login")
public String loginPage() {
return "/login/login";
}
저 부분이 문제일 수 있겠다는 사실을 인식하기까지 이미 서너시간이 지났기 때문에, 또 이 에러 이전에도 또 다른 에러로 두어시간을 소모했기 때문에 오후 3시부터 시작했던 배포 작업은 어느덧 밤 10시를 가리키고 있었다. 제발, 제발 되었으면 좋겠다 하는 마음에 관련된 코드들을 아래와 같이 수정했다.
@GetMapping("login")
public String loginPage() {
return "login/login";
// 원래는 return "/login/login";
}
안되면 나는 이제 안할거야, 하는 마음에 다시 프로젝트를 최신화하고 배포를 진행했다. 두근거리는 마음으로 프로젝트를 실행했다.
와, 잘 된다.
후기
스트레스를 너무 많이 받아서 곱창을 시켜먹었다. 그래도 에러를 해결해 기분이 좋았다.
끝
'메모 & 삽질기록보관소' 카테고리의 다른 글
[jqeury] ajax에서의 parse error | 스프링과 자바스크립트의 부조화 (0) | 2022.03.13 |
---|---|
[메모] 배포 관련 리눅스 명령어 (0) | 2022.01.19 |
JPA와 서브쿼리 (JPA 서브쿼리의 한계) (2) | 2022.01.12 |
[JPA] 연관관계 주인과 CASCADE 옵션 (0) | 2021.12.24 |
MOOC를 통한 프로그래밍 공부 커리큘럼 가이드 (0) | 2021.09.28 |