[AWS, JPA, MySQL] Table doesn't exist
환경- Spring Boot 3.3.1- OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어)- DB : MySQL 8.X 문제 상황ubuntu:~/spring-ml-practice/build/libs$ sudo java -jar spring-ml-practice-0.0.1-SNAPSHOT.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _ | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / ..
2024.06.30
[Spring Boot, Linux] Error resolving template
환경- 스프링 부트 3.2.5-OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어) 문제 상황로컬 환경에서 타임리프를 사용한 스프링 부트 프로젝트를 실행할 때는 아무 이상 없이 html 템플릿 파일을 잘 찾아서 아무 문제를 느끼지 못했지만, 실제로 AWS를 통해서 배포할 때 문제가 발생했다.바로 Error resolving template 오류였다.이 오류를 해결하기 위해서 GPT와 몇 시간 동안 대화를 하고, 구글링에도 많은 시간을 쏟았다.결국 원인을 찾았지만, 그 원인은 조금 허무했다. 원인Thymeleaf에서 "Error resolving template" 오류가 발생하는 경우, 이는 일반적으로 템플릿을 찾거나 로드할 수 없음을 의미한다.하..
2024.06.30
[AWS EC2] 프리티어 인스턴스 사용시 Gradle build 시 무한 로딩 오류
환경-OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어)-인스턴스 유형 : t2.micro(1 GiB 메모리), (프리티어)-스토리지(ELB) : 1 x 30 GiB(gp3) 문제 상황./gradlew clean build위 명령어를 통해서 스프링부트 프로젝트를 빌드를 하는데 아무리 기다려도 완료가 되지 않았다. 원인스프링 부트 프로젝트를 빌드하는 과정에서는 많은 메모리를 필요로 하기 때문에, 메모리가 부족하면 빌드가 매우 느려지거나 아예 완료되지 않을 수 있다.t2가 메모리를 1GiB 만 제공하기 때문에 스프링 부트 프로젝트를 빌드하는데 실패한 것이었다. 해결 방법1. 인스턴스 유형을 업그레이드 하여 더 많은 메모리를 사용예를들어, 예를 들어..
2024.06.30

환경

- Spring Boot 3.3.1

- OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어)

- DB : MySQL 8.X

 

문제 상황

ubuntu:~/spring-ml-practice/build/libs$ sudo java -jar spring-ml-practice-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _ | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.1)

2024-06-29T21:08:19.056Z  INFO 5768 --- [spring-ml-practice] [           main] C.s.SpringMlPracticeApplication          : Starting SpringMlPracticeApplication v0.0.1-SNAPSHOT using Java 17.0.11 with PID 5768 (/home/ubuntu/spring-ml-practice/build/libs/spring-ml-practice-0.0.1-SNAPSHOT.jar started by root in /home/ubuntu/spring-ml-practice/build/libs)
2024-06-29T21:08:19.071Z  INFO 5768 --- [spring-ml-practice] [           main] C.s.SpringMlPracticeApplication          : No active profile set, falling back to 1 default profile: "default"
2024-06-29T21:08:21.205Z  INFO 5768 --- [spring-ml-practice] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2024-06-29T21:08:21.413Z  INFO 5768 --- [spring-ml-practice] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 179 ms. Found 6 JPA repository interfaces.
2024-06-29T21:08:23.227Z  INFO 5768 --- [spring-ml-practice] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 80 (http)
2024-06-29T21:08:23.264Z  INFO 5768 --- [spring-ml-practice] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-06-29T21:08:23.266Z  INFO 5768 --- [spring-ml-practice] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.25]
2024-06-29T21:08:23.629Z  INFO 5768 --- [spring-ml-practice] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-06-29T21:08:23.634Z  INFO 5768 --- [spring-ml-practice] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4422 ms
2024-06-29T21:08:24.834Z  INFO 5768 --- [spring-ml-practice] [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2024-06-29T21:08:25.044Z  INFO 5768 --- [spring-ml-practice] [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.5.2.Final
2024-06-29T21:08:25.145Z  INFO 5768 --- [spring-ml-practice] [           main] o.h.c.internal.RegionFactoryInitiator    : HHH000026: Second-level cache disabled
2024-06-29T21:08:26.039Z  INFO 5768 --- [spring-ml-practice] [           main] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
2024-06-29T21:08:26.126Z  INFO 5768 --- [spring-ml-practice] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-06-29T21:08:27.060Z  INFO 5768 --- [spring-ml-practice] [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@56299b0e
2024-06-29T21:08:27.063Z  INFO 5768 --- [spring-ml-practice] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-06-29T21:08:27.289Z  WARN 5768 --- [spring-ml-practice] [           main] org.hibernate.orm.deprecation            : HHH90000025: MySQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
2024-06-29T21:08:29.423Z  INFO 5768 --- [spring-ml-practice] [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2024-06-29T21:08:29.433Z  INFO 5768 --- [spring-ml-practice] [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2024-06-29T21:08:30.333Z  INFO 5768 --- [spring-ml-practice] [           main] o.s.d.j.r.query.QueryEnhancerFactory     : Hibernate is in classpath; If applicable, HQL parser will be used.
2024-06-29T21:08:31.922Z  WARN 5768 --- [spring-ml-practice] [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2024-06-29T21:08:33.046Z  INFO 5768 --- [spring-ml-practice] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 80 (http) with context path '/'
2024-06-29T21:08:33.110Z  INFO 5768 --- [spring-ml-practice] [           main] C.s.SpringMlPracticeApplication          : Started SpringMlPracticeApplication in 15.326 seconds (process running for 16.976)
2024-06-29T21:08:33.120Z  INFO 5768 --- [spring-ml-practice] [           main] C.s.config.DatabaseConnectionCheck       : Database connected successfully.
2024-06-29T21:08:44.795Z  INFO 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-06-29T21:08:44.796Z  INFO 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-06-29T21:08:44.800Z  INFO 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
Hibernate: 
    select
        m1_0.member_email,
        m1_0.activity_level,
        m1_0.height,
        m1_0.name,
        m1_0.password,
        m1_0.sex,
        m1_0.weight 
    from
        members m1_0 
    where
        m1_0.member_email=?
2024-06-29T21:08:45.363Z  WARN 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1146, SQLState: 42S02
2024-06-29T21:08:45.363Z ERROR 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Table 'test.members' doesn't exist

 

주요한 부분은 아래와 같다.

2024-06-29T21:08:44.800Z  INFO 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
Hibernate: 
    select
        m1_0.member_email,
        m1_0.activity_level,
        m1_0.height,
        m1_0.name,
        m1_0.password,
        m1_0.sex,
        m1_0.weight 
    from
        members m1_0 
    where
        m1_0.member_email=?
2024-06-29T21:08:45.363Z  WARN 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1146, SQLState: 42S02
2024-06-29T21:08:45.363Z ERROR 5768 --- [spring-ml-practice] [p-nio-80-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Table 'test.members' doesn't exist

 

test.member 테이블을 찾을 수 없다는 상황이다.

 

로컬 개발 환경에서는 h2 DB를 사용하였고, 실제 배포할 때는 MySQL을 사용했다.

h2에서는 아무 문제가 없었는데, 리눅스 환경과 MySQL을 사용하고나니 이런 상황이 발생하여 매우 당황했다.

 

members 테이블의 생성 쿼리는 아래와 같다.

CREATE TABLE Members (
    member_email VARCHAR(255) PRIMARY KEY,
    password VARCHAR(255) NOT NULL,
    name VARCHAR(255) NOT NULL,
    sex INT NOT NULL,
    activity_level INT NOT NULL,
    weight INT NOT NULL,
    height INT NOT NULL
);

 

JPA 엔티티 클래스 코드는 아래와 같다.

@Entity
@Table(name = "Members")
@Getter @Setter
public class Member {
    @Id
    private String memberEmail;
    private String password;
    private String name;
    private int sex;
    private int activityLevel;
    private int weight;
    private int height;
}

맨 처음에 이 문제를 맞닥뜨렸을 때는 도대체 뭐가 문제인지 파악하기 힘들었다.

 

원인

주요 원인은 내 배포 환경인 우분투에서는 MySQL이 대소문자를 확실히 구분한다는 것이다.

mysql> SHOW VARIABLES LIKE 'lower_case_table_names';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_table_names | 0     |
+------------------------+-------+
1 row in set (0.01 sec)

MySQL의 lower_case_table_names 설정이 0이므로, 대소문자를 구분하게 되어 있다.

엔티티 클래스의 테이블 이름 매핑은 Members 로 되어있는데, 실제 DB에 저장되어있는 테이블 명은 members이기 때문이다.

하지만, 엔티티 클래스의 테이블 이름 매핑은 members 로 소문자로 바꿔 봤지만 해결되지 않았다. 

 

해결 방법

현재 테이블 이름은 Members이고, MySQL에서는 테이블 이름을 대소문자를 구분하여 처리하고 있다.

MySQL의 lower_case_table_names 설정이 0이므로, 대소문자를 구분하게 되어 있다.

따라서 엔티티 클래스에서 테이블 이름을 소문자로 변경하는 것이 필요하다.

이 뿐만이 아니라 DB에 DDL 쿼리를 날릴 때, 테이블 명 또한 소문자로 변경이 필요하다.

-- 테이블 명 소문자로 변경
CREATE TABLE members (
    member_email VARCHAR(255) PRIMARY KEY,
    password VARCHAR(255) NOT NULL,
    name VARCHAR(255) NOT NULL,
    sex INT NOT NULL,
    activity_level INT NOT NULL,
    weight INT NOT NULL,
    height INT NOT NULL
);

 

@Entity
@Table(name = "members") //매핑 테이블명 소문자로 변경
@Getter @Setter
public class Member {
    @Id
    private String memberEmail;
    private String password;
    private String name;
    private int sex;
    private int activityLevel;
    private int weight;
    private int height;
}

 

테이블 명과 컬럼명 모두 소문자로 변경하고나서 정상적으로 테이블을 찾았다.

 

정확한 원인은 조금 더 파악해야할 것 같다.

환경

- 스프링 부트 3.2.5

-OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어)

 

문제 상황

로컬 환경에서 타임리프를 사용한 스프링 부트 프로젝트를 실행할 때는 아무 이상 없이 html 템플릿 파일을 잘 찾아서 아무 문제를 느끼지 못했지만, 실제로 AWS를 통해서 배포할 때 문제가 발생했다.

바로 Error resolving template 오류였다.

이 오류를 해결하기 위해서 GPT와 몇 시간 동안 대화를 하고, 구글링에도 많은 시간을 쏟았다.

결국 원인을 찾았지만, 그 원인은 조금 허무했다.

 

원인

Thymeleaf에서 "Error resolving template" 오류가 발생하는 경우, 이는 일반적으로 템플릿을 찾거나 로드할 수 없음을 의미한다.

하지만 원인은 타임리프에 있는 것이 아니라, 컨트롤러에 있었다.

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "/index";
    }
}

 

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "index";
    }
}

 

첫 번째 컨트롤러와 두 번째 컨트롤러의 차이가 보이는가?

뷰를 리턴할 때, 맨 앞에 슬래시(/) 유무이다.

 

왜 그런 것인지는 모르지만, 리눅스 환경에서 뷰 템플릿 파일을 리턴할 때 맨 앞에 슬래시를 사용하면 안된다.

 

해결 방법

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "home/index"; // 뷰 템플릿의 경로를 반환하되, 맨 앞에 슬래시를 사용하지 말 것
    }
}

컨트롤러에서 반환 값으로 뷰 템플릿 경로를 리턴할 때, 맨 앞에 슬래시를 제거한다!

 

 

참고 : https://dev-jwblog.tistory.com/40

환경

-OS : Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1008-aws x86_64) (프리티어)

-인스턴스 유형 : t2.micro(1 GiB 메모리), (프리티어)

-스토리지(ELB) : 1 x 30 GiB(gp3)

 

문제 상황

./gradlew clean build

위 명령어를 통해서 스프링부트 프로젝트를 빌드를 하는데 아무리 기다려도 완료가 되지 않았다.

 

원인

스프링 부트 프로젝트를 빌드하는 과정에서는 많은 메모리를 필요로 하기 때문에, 메모리가 부족하면 빌드가 매우 느려지거나 아예 완료되지 않을 수 있다.

t2가 메모리를 1GiB 만 제공하기 때문에 스프링 부트 프로젝트를 빌드하는데 실패한 것이었다.

 

해결 방법

1. 인스턴스 유형을 업그레이드 하여 더 많은 메모리를 사용

예를들어, 예를 들어, t2.medium 인스턴스는 4 GiB의 메모리를 제공하기 때문에 이로 인스턴스를 교체하는 방법도 있다.

하지만 나는 돈이 없는 학생이기 때문이 이 방법을 선택하지 않았다.

 

2. 스왑 메모리 사용

스왑 메모리

스왑 메모리는 시스템의 물리적 메모리(RAM)가 부족할 때 하드 디스크의 일부를 가상 메모리로 사용하는 것이다. 이렇게 하면 RAM이 부족할 때 시스템이 멈추는 대신 디스크를 사용하여 추가적인 메모리를 확보할 수 있다.

 

나의 서버 배포 환경을 보면, 램은 1GiB 이고, 저장 장치 볼륨 크기는 30GiB이다.

램의 용량이 저장 장치 볼륨 크기보다 상대적으로 작은 것을 확인할 수 있다.

그래서 저장 장치의 볼륨을 빌리는 것이다.

관련 개념은 아래의 글을 참고하기를 바란다.

2023.07.02 - [컴퓨터 구조 & 운영체제/운영체제] - [운영체제] 페이징을 통한 가상 메모리 관리

 

[운영체제] 페이징을 통한 가상 메모리 관리

이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다. 연속 메모리 할당의 문제점은 아래와 같다. 외부 단편화

rebugs.tistory.com

 

 

1. 스왑 파일 생성

sudo dd if=/dev/zero of=/swapfile bs=128M count=16
  • dd: 데이터를 복사하는 명령어이다.
  • if=/dev/zero: 입력 파일로서, 크기가 0인 무한대의 빈 바이트 스트림을 제공하는 특수 파일이다.
  • of=/swapfile: 출력 파일로서, 이 경우 스왑 파일의 경로를 지정한다.
  • bs=128M: 블록 크기를 128MB로 설정한다.
  • count=16: 128MB 블록을 16번 써서 2GB(128MB * 16)의 스왑 파일을 생성한다.

 

2. 스왑 파일에 대한 권한 설정

sudo chmod 600 /swapfile
  • chmod 600 /swapfile: 스왑 파일의 권한을 소유자만 읽고 쓸 수 있도록 설정한다.
  • 600: 소유자에게만 읽기와 쓰기 권한을 부여하는 권한 설정 값이다.

 

3. 스왑 영역으로 설정

sudo mkswap /swapfile
  • mkswap /swapfile: 스왑 파일을 스왑 영역으로 초기화하여 사용할 수 있도록 준비한다.

 

4. 스왑 사용 시작

sudo swapon /swapfile
  • swapon /swapfile: 지정된 스왑 파일을 활성화하여 스왑 메모리로 사용하기 시작한다.

 

5. 스왑 상태 확인

sudo swapon -s

이렇게 출력이 된다면 정상적으로 스왑이 적용된 것이다.

 

6. 재부팅 후에도 스왑이 유지되도록 설정

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  • echo '/swapfile none swap sw 0 0': 스왑 파일을 /etc/fstab 파일에 추가하기 위한 문자열을 생성한다.
  • | sudo tee -a /etc/fstab: 생성된 문자열을 /etc/fstab 파일의 끝에 추가한다.
  • /etc/fstab: 시스템이 부팅될 때 자동으로 마운트할 파일 시스템 목록을 지정하는 파일이다.

 

이렇게 스왑 메모리를 사용하면 부족한 메모리를 하드 디스크로 대체할 수 있다.

 

참고 

https://ksh-coding.tistory.com/40

 

EC2 gradle build 시 무한 로딩 오류(메모리 문제)

EC2에서 git clone으로 서버 파일을 clone하고 ./gradlew test 를 했는데 :compileQuerydsl 에서 무한 로딩이 걸리고 넘어가지 않았다. 구글링을 진행해보니 무한 로딩이 걸리는 오류는 메모리 부족 문제일 수

ksh-coding.tistory.com

 

https://jjong2.tistory.com/70

 

ec2 스프링 빌드 시 멈춤 현상 해결법

스프링 빌드를 하는데 빌드 시간이 1초씩 늘어나는게 아니라 10초 이상씩 늘고, 빌드도 안되길래 여러번 껐다 켰다 반복해서 빌드를 해봤는데 소용없었다 free tier로 ec2를 이용하면 ram이 1기가라

jjong2.tistory.com