티스토리 뷰

https://ekeprl.tistory.com/56

 

서버호스팅 (4) – [Ubuntu] 서버에 Git으로 프로젝트 배포하기

https://ekeprl.tistory.com/55 서버호스팅 (3) – [Ubuntu] Nginx 설치https://ekeprl.tistory.com/54 서버호스팅 (2) – [Ubuntu] 서버 초기 세팅이번 포스팅은 지난 https://ekeprl.tistory.com/52 서버호스팅 (1) – [Ubuntu] OS 업

ekeprl.tistory.com

 

지난번에 이어서 포스팅을 작성해보려 합니다.

 

그전에 현재 프로젝트의 환경설정을 짧게 소개하자면

개발 환경

  • 로컬: Windows, Spring Boot 3.3.2 (Kotlin)
  • 서버: Ubuntu 24, MariaDB, Nginx
  • 빌드 도구: Gradle

프로젝트 구조

- application.kt: 환경변수(SERVER_ENV)로 프로파일 전환
- properties-local.xml: 로컬 개발 환경 설정
- properties-op.xml: 운영 환경 설정
- ProfileConfig.kt: 프로파일별 설정 로드
- MyBatisConfig.kt: DataSource 및 MyBatis 설정

이렇게 구성했습니다.

 

먼저, 지난 포스팅 끝에 오류가 발생했다고 했는데...

저 상황에서 실행이 되질 않고 그냥 종료되어 버리는 게 문제였습니다.

 

우선 분명히 실행이 되지 않고 종료가 되는 이유를 확인하기 위해 프로젝트 내부의 logback-spring.xml의 설정을 수정했습니다.

<!-- 각 패키지에 대한 로거 설정 -->
<logger name="jdbc" level="OFF" />
<logger name="jdbc.audit" level="OFF" />
<logger name="jdbc.sqlonly" level="OFF" />
<logger name="io.undertow" level="WARN" />
<logger name="jdbc.resultset" level="OFF" />
<logger name="jdbc.connection" level="OFF" />
<logger name="io.netty" level="WARN" additivity="false" />
<logger name="io.lettuce" level="WARN" additivity="false" />
<logger name="org.xnio.nio" level="WARN" additivity="false" />
<logger name="org.thymeleaf" level="WARN" additivity="false" />

<!-- 기존 WARN에서 DEBUG / INFO로 변경 -->
<logger name="com.zaxxer.hikari" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>
<logger name="org.mybatis.spring" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>
<logger name="org.springframework" level="INFO" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>
<logger name="org.springframework.boot" level="INFO" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>

<!-- DB 연결 관련 상세 로그 -->
<logger name="org.springframework.jdbc" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>
<logger name="org.mariadb.jdbc" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>

<logger name="com.steamchk.ekeprl" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
</logger>

<logger name="jdbc.sqltiming" level="INFO"/>
<logger name="jdbc.resultsettable" level="INFO"/>

어디서 어떤 문제가 발생하는지 확인을 하기위해 수정했습니다. 

수정 후에 다시 서버에서 프로젝트를 실행해 보니,

 

에러 로그

위 사진과 같은 에러로그가 출력되었습니다.

 

PROPERTIES - LOCAL

<properties>
    <comment><![CDATA[로컬 설정값]]></comment>
        
    <!-- Mybatis설정정보 -->
    <entry key="spring.datasource.driver-class-name"><![CDATA[org.mariadb.jdbc.Driver]]></entry>
    <entry key="spring.datasource.url"><![CDATA[jdbc:mariadb://localhost:3306/DB이름]]></entry>
    <entry key="spring.datasource.username"><![CDATA[root]]></entry>
    <entry key="spring.datasource.password"><![CDATA[비밀번호]]></entry>
    <entry key="spring.datasource.minPoolSize"><![CDATA[5]]></entry>
    <entry key="spring.datasource.maxPoolSize"><![CDATA[10]]></entry>
</properties>
PROPERTIES - OP

<properties>
    <comment><![CDATA[운영환경 설정값]]></comment>
        
    <!-- Mybatis설정정보 -->
    <entry key="spring.datasource.driver-class-name"><![CDATA[org.mariadb.jdbc.Driver]]></entry>
    <entry key="spring.datasource.url"><![CDATA[jdbc:mariadb://localhost:3306/DB이름]]></entry>
    <entry key="spring.datasource.username"><![CDATA[ekeprl_admin]]></entry>
    <entry key="spring.datasource.password"><![CDATA[비밀번호]]></entry>
    <entry key="spring.datasource.minPoolSize"><![CDATA[5]]></entry>
    <entry key="spring.datasource.maxPoolSize"><![CDATA[20]]></entry>
</properties>

 

운영, local을 구분 지어놨는데도 불구하고 properties-op를 인식을 못하고 자꾸 local로 연결을 하는 게 문제였습니다.

 

단계별로 무엇이 문제인지 찾아가는 과정입니다.

 

1.DB사용자 권한 확인

--DB접속
mysql -h localhost -u ekeprl_admin -p DB이름
--권한 확인
SHOW GRANTS FOR 'ekeprl_admin'@'localhost';
--권한 부여
GRANT ALL PRIVILEGES ON DB이름.* TO 'ekeprl_admin'@'localhost';
--적용
FLUSH PRIVILEGES;

위 과정을 통해 권한확인 및 적용을 마쳤고

 

2. 설정파일 점검

설정파일을 확인하며 누락된 코드가 있나 확인했습니다.

### 문제 상황 ```

Cannot invoke "String.startsWith(String)" because "name" is null at MyBatisConfig.mariadbDataSource

DataSource 생성 시 driver-class-name이 null로 들어가 종료가 되었다는 얘기인데..

분명히 위에 로컬 / 운영환경을 나눠 properties를 작성했음에도 불구하고 원인을 찾지 못했습니다.

 

2.1 프로젝트 내부의 config 파일의 흐름

 

3. 원인 파악

Application.kt

fun main(args: Array<String>) {
    val profile : String? = System.getProperty("spring.profiles.active")
    if(profile == null) {
        // 환경변수로 구분
        val env = System.getenv("SERVER_ENV") ?: "local"

        when(env) {
            "production", "op" -> {
                System.setProperty("spring.profiles.active", "op")
            }
            else -> {
                System.setProperty("spring.profiles.active", "local")
                System.setProperty("spring.thymeleaf.cache", "false")
                System.setProperty("spring.devtools.restart.enabled", "true")
                System.setProperty("spring.devtools.livereload.enabled", "true")
            }
        }
    }

    var runPort : String? = System.getProperty("server.port")
    if(runPort == null) {
        runPort = "8080"
        System.setProperty("server.port", runPort)
    }
}

가장 먼저 실행되는 applicaion.kt입니다.

2.1의 그림을 보면 먼저 application에서

spring.profiles.active = "op" / "local"

어느 분기점으로 향할 건지 체크를 합니다. 

 

그 체크를 하는 ProfileConfig.kt를 보면

@Configuration
class ProfileConfig {

    @Autowired
    private lateinit var env : Environment

    @Configuration
    @Profile(value=["local"])
    @PropertySource(value = [("classpath:properties-local.xml")], encoding = "UTF-8")
    inner class ProfileDev {
        private val logger = LoggerFactory.getLogger(this::class.java)
        init {
            logger.info("개발 환경 프로파일로 : " + env.getProperty("server.port") + "포트로 구동 되었습니다.")
        }
    }

    // 운영 부분이 누락되어있었음 -> 추가
    @Configuration
    @Profile(value=["op", "production"])
    @PropertySource(value = [("classpath:properties-op.xml")], encoding = "UTF-8")
    inner class ProfileOp {
        private val logger = LoggerFactory.getLogger(this::class.java)
        init {
            logger.info("운영 환경 프로파일로 : " + env.getProperty("server.port") + "포트로 구동 되었습니다.")
        }
    }

}

 

기존에는 value=["local"]만 작성되어 있었고

@Profile(value=["op", "production"]) op로 실행되는 부분이 작성되어있지 않아 name = null로 받아 오류가 발생했었습니다.

 

아래 op일 때의 설정을 추가해 주고, 다시 프로젝트를 재시작을 했더니..

 

정상 화면

해당 화면으로 올바르게 접속되는 것을 확인할 수 있었습니다.

 

오류를 확인하고 굉장히 많은 검색, 코드 확인을 진행했었는데

생각보다 간단하게 해결할 수 있었습니다.

 

이런 오류들을 해결해 나가며 한 단계 더 발전할 수 있지 않나 생각합니다.

 

이번 포스팅은 여기서 마치겠습니다.

감사합니다.

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함