
기본적인 깃과 깃허브 계정 세팅은 되어 있을 거라 가정한 포스트임을 알려드립니다. 또한 전문적인 배경 지식보다는 실질적으로 어떻게 하는지에 집중한 포스트이므로 등장하는 개념을 깊게 설명하지 않는 점을 알려드립니다.

클론 받고자 하는 깃허브 레포지토리에 방문하여 초록 버튼 누르면 위와 같은 화면이 나올 것이다.
HTTPS 깃허브 리포지토리 링크를 복사해두고 프로젝트를 생성하고자 하는 폴더 위치에서 터미널에 다음과 같이 명령어를 실행하면 된다.
git clone <복사한 깃허브 리포지토리 주소>
명령어 실행 시, 현재 터미널이 열린 폴더 위치 안에 리포지토리 이름을 가진 또다른 폴더가 하나 생성되며 리포지토리의 내용이 모두 복사되어 있을 것이다.
1단계는 완료되었다.
본격적으로 포팅 작업을 순차적으로 설명하기 전에 전반적으로 작업 도중에 발생하는 에러에 대처하는 방식에 대해 설명하고자 한다.
가장 먼저 확인할 것은 에러 메세지이다.
로그에 출력되는 에러 메세지를 확인하여 어떤 의존성이, 어떤 객체가, 어떤 파일을 찾을 수 없어 발생하는 에러인지 확인하여야 한다.
무조건 챗지피티에게 먼저 물어보는 것은 권하지 않는 방식이다.
일반적으로 리포지토리에 푸쉬한 코드는 해당 개발자의 로컬 PC 에서는 돌아가는 코드일 가능성이 높으므로 나의 컴퓨터에 포팅할 때 잘 되지 않는 이유는 기입한 내용이 틀렸거나, 기입한 내용이 형식에 맞지 않거나, 폴더 경로가 맞지 않거나, 의존성 버전이 너무 낮거나 높아 서로 호환되지 않는 경우 등의 상황일 것이다.
따라서 설정과 내용을 하나하나 차근차근 확인하여서 해결할 수 있기를 바란다.
applicationContext.xml 은 Spring Framework 기반의 애플리케이션에서 중요한 역할을 하는 설정 파일이다.
이 파일은 스프링 애플리케이션 컨텍스트를 초기화할 때 필요한 설정을 포함하며, 애플리케이션에서 사용하는 빈(Bean) 과 그들의 의존성, 환경설정 등을 정의한다.
내가 클론 받은 코드의 경우 README.md 파일에 applicationContext.xml 의 템플릿이 포함되어 있어서 다른 건 신경쓰지 않고 Bean 부분만 수정하면 되었다.
해당 코드는 아래와 같다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.example"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
# <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://<DB 가 있는 호스트의 IP Address>:<해당 호스트에서 원하는 DB 에 접근할 수 있는 Port #>/<DB Name>?serverTimezone=UTC&characterEncoding=UTF-8"/>
<property name="username" value="root 혹은 설정한 username 값"/>
<property name="password" value="비밀번호"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mappers/*-mapper.xml"></property>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
여기서 우리가 집중해야 할 부분은 이 부분이다.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:<mysql 또는 mariadb>://<IP Address>:<Port #>/<DB Name>?serverTimezone=UTC&characterEncoding=UTF-8"/>
# mariadb 사용하는 경우 아래와 같이 수정해야 함 (cj 없는 거 꼭 확인!!)
# <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="1006"/>
</bean>
여기서 연결 설정이 잘 안 될 경우, 데이터베이스 설정 오류를 발생시킬 수 있다.
데이터베이스 설정 오류 자체는 보통 500 에러로 나타나곤 하며 직접적으로 404 에러를 유발하지는 않지만, 데이터베이스 연결 문제로 인해 애플리케이션이 제대로 초기화되지 않거나, 요청 처리를 담당하는 로직이 실패하는 등의 상황으로 인해 간접적으로 404 에러를 유발할 수 있다.
따라서 위의 부분에서 오타가 없는지 잘 확인하길 바란다.
gradle 이 빌드 도구인 경우에는 build.gradle 에서 똑같이 해주면 된다.
pom.xml 은 Maven 프로젝트의 핵심 구성 파일로, POM(Project Object Model) 을 정의한다.
Maven은 Java 기반의 빌드 및 의존성 관리 도구이며, pom.xml 파일은 프로젝트의 빌드 설정, 의존성 관리, 플러그인 설정 등을 명시하는 데 사용된다.
따라서 앞서 언급한 에러가 발생하는 상황들 중 의존성 호환성 문제와 관련된 부분은 대체로 이 파일에서 해결할 수 있을 것이다.
나의 경우 annotation 과 관련된 오류가 자꾸만 발생해서 코드를 수정해야 하나 고민했는데, 앞서 한 번 더 언급했듯이 클론을 떠와도 될 정도로 깃허브 리포지토리에 공유한 프로젝트는 코드 상 문제가 없을 확률이 높기 때문에 일단은 설정과 관련해서 해결하기 위한 접근을 하는 것이 좋을 것이라는 판단 하에 나는 다음과 같이 하였다.
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
스프링에서 annotation을 사용하기 위한 라이브러리인 Lombok 의 버전을 30 정도로 높여주었다.
Maven Repository 에서 사람들이 가장 많이 업보트한 버전 위주로 올리면 대체로 해결될 것이다.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
이후 발생하는 로그를 찍어주는 라이브러리가 없다는 에러를 해결하기 위해 위의 의존성도 추가해주었다.
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!-- MariaDB -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.1.0</version>
</dependency>
마지막으로 나는 MariaDB 를 사용할 예정이므로 MySQL 대신 MariaDB 관련 의존성을 추가해주었다.

위 버튼을 눌러 Maven 변경 내용 로드 해주는 것도 잊지 말자!
스프링 프로젝트를 빌드하여 .war 파일로 패키징한다.
mvn clean install
위 명령어를 터미널에서 실행할 수도 있고

또는 위의 화면처럼 Maven 아이콘을 누르고
CoupangSpring Maven Webapp >> 수명주기 (Life Cycle) >> clean 더블 클릭 >> install 더블 클릭
하면 똑같은 작업을 GUI 로 할 수 있다.
위 과정은 Maven 또는 Gradle을 사용하여 프로젝트를 빌드하는 과정이다.
clean 은 이전 빌드의 산출물(예: 클래스 파일, JAR/WAR 파일 등)을 삭제하는 명령어이다.
install 은 프로젝트의 산출물을 로컬 Maven 저장소에 설치한다.
package 라는 명령어도 동일하게 프로젝트 코드를 컴파일하고 테스트한 후, 최종 산출물(JAR, WAR, 또는 ZIP 파일 등)을 생성하지만 target 디렉터리에 저장할 뿐, install 처럼 로컬 Maven repository 에 저장하지는 않는다는 차이점이 존재한다.
Docker Hub에서 기본 tomcat 이미지를 가져오는 방법이 있고, 사용자 정의 Dockerfile을 작성하여 커스터마이징된 Tomcat 이미지를 만드는 방법이 있다.
첫번째 방식은 두번째 방식을 조금 더 직관적으로 터미널에 명령어로 실행하는 것과 유사하므로 두번째 방법을 중점적으로 설명하도록 하겠다.
Dockerfile 은 Docker 이미지를 생성하기 위한 스크립트 파일이다.
이 파일은 텍스트 형식으로 작성되며, 이미지의 기반 운영체제, 애플리케이션, 실행 명령어 등을 단계적으로 정의한다.
Docker 는 이 Dockerfile 을 읽고 명령어를 순차적으로 실행하여 사용자 지정 Docker 이미지를 생성한다.
내가 작성한 도커파일의 위치와 내용은 다음과 같다.

# Dockerfile
FROM tomcat:9.0
COPY target/*.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh", "run"]
FROM tomcat:9.0COPY target/*.war /usr/local/tomcat/webapps/ROOT.warhttp://localhost:8080 으로 접속하면 해당 애플리케이션이 바로 실행된다(별도의 경로 지정 불필요).COPY target/*.war /usr/local/tomcat/webapps/testApplication.war 를 실행한다면 브라우저에서 <기본 경로>/testApplication 으로 접속해야 원하는 페이지가 보여질 것이다.CMD ["catalina.sh", "run"]docker build -t <원하는 이미지명> .
Docker 와 Dockerfile 을 사용하여 생성된 이미지를 기반으로 컨테이너를 실행한다.
이 과정에서 컨테이너 내부에서 Tomcat 서버가 실행되고, .war 파일이 자동으로 배포된다.
docker run -d -p 8081:8080 <원하는 컨테이너명> -t <커스텀 생성한 이미지명>
여기서 포트 번호의 의미를 설명하자면 다음과 같다.
<로컬에서 원하는 컨테이너로 접근하고자 할 때 사용하는 포트 #>:<컨테이너에서 원하는 프로세스로 접근하고자 할 때 사용하는 포트 #>
따라서 로컬 컴퓨터가 톰캣이 작동될 수 있는 가상의 컴퓨터에 접근하기 위해서는 자기 자신의 8081 포트를 통해 접근해야 한다.
그리고 그 가상의 컴퓨터가 톰캣이라는 프로세스에 접근하기 위해서는 8080 포트를 통해 접근해야 한다.
브라우저에서 http://localhost:<로컬에서 원하는 컨테이너로 접근하고자 할 때 사용하는 포트 #> 에 접속하여 스프링 애플리케이션이 정상적으로 실행되는지 확인한다.
그렇게 하면 원하던 화면이 나의 Chrome 창에 뜨는 것을 확인할 수 있게 된다.

내가 클론한 리포지토리의 코드는 자연적으로 products/list 로 리다이렉트 해주기 때문에 다음과 같은 화면으로 바로 넘어갔다.
끝!
[Railway, Docker, Tomcat, MySQL, DBeaver, IntelliJ] 스프링프로젝트 Railway 배포해보기