Debug Log

debugLog_Spring Boot + MySQL 연동 시 Access denied for user 오류 해결

밍미a 2025. 6. 29. 00:04
728x90

[문제개요]

OOP 프로젝트의 첫걸음으로 초기 환경설정 세팅을 하다 문제가 발생했다.

팀원과 회의결과, DB는 MySQL을 사용하고 세션을 사용하기로 했다. 그리고 이번에 새롭게 사용해보는 기술이 있었는데 바로 flyway이다. 나는 flyway를 처음 사용해보기 때문에 좀 더 공부가 필요했기 때문에 DB, 세션, 로그 등과 같은 기본적인 초기 세팅은 함께 하는 팀원분께서 설정해주시기로 했다.

초기 설정이 끝난 뒤, 프로젝트 파일을 git에서 받아와서 DB를 연결하는데

인텔리제이에서 직접 연결할때는 연결이 잘 되었지만, 어플리케이션을 실행할때는 계속 데이터베이스에 접속하지 못하고 실패하는 현상이 발생했다.

따라서 해당 에러의 해결과정을 기록으로 남겨두려고 한다.


[에러로그]

 

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'flywayInitializer' defined in class path resource 
[org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: 
Unable to obtain connection from database: Access denied for user 'root'@'localhost' (using password: YES)

Caused by: org.flywaydb.core.internal.exception.FlywaySqlException: 
Unable to obtain connection from database: Access denied for user 'root'@'localhost' (using password: YES)

Caused by: java.sql.SQLException: 
Access denied for user 'root'@'localhost' (using password: YES)

[시도과정]

1. 버전 확인

처음에는 버전문제인가 싶어 버전들을 확인해봤다. 프로젝트의 MySQL의 버전은 8.0으로 되어 있었지만 내 MySQL버전은 9.2였다.

하지만 다른 프로젝트에서 9.2를 이미 사용하고 있었기 때문에 8.0으로 다운그레이드 하여 다시 깔 수는 없었다.

도커를 사용하는 방법도 있었지만, MySQL 버전 8.0은 9.2에서도 호환이 되기 때문에 그 문제가 아니란걸 알 수 있었다.

다음으로 생각한게 지금 연결이 안되고 있으니까, 어플리케이션과 DB을 연결하는 JDBC의 버전문제인가 싶어서 JDBC드라이버를 최신버전으로 업그레이드 해주었다.

→ 하지만 이렇게 해도 해결되지 않았다.

2. 계정과 비밀번호 확인

계정과 비밀번호가 잘못되었나 싶어서 계정과 비밀번호를 다시한번 확인해주었다.

→ root계정으로 되어있었고, 비밀번호도 알맞게 되어있었다.

3. JDBC URL확인

계정이름도 맞고, 비밀번호도 맞는데 연결이 안되는건 내 DB까지 타고들어갈 주소가 잘못되었을수도 있겠다라는 생각이 들었다. yml파일에서 JDBC URL이

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/~~~ 블라블라

이런식으로 되어 있었다.

127.0.0.1:3306 이 부분을 보면 [호스트]:[포트] 이렇게 되어있는건데 DB에 설정되어있는 내 호스트가 어떻게 되어있는지 알 수 없었다. 따라서 터미널에서 MySql에 접속한 뒤, 다음의 명령어를 실행하였다.

SELECT user, host, plugin FROM mysql.user WHERE user = 'root';

결과는

+------+-----------+-----------------------+
| user | host      | plugin                |
+------+-----------+-----------------------+
| root | localhost | caching_sha2_password |
+------+-----------+-----------------------+
1 row in set (0.00 sec)

이런식으로 나왔다. 127.0.0.1 이 아니었다. localhost랑 127.0.0.1랑 같은것 아닌가..?

MySQL 연결 설정 방법 차이점 : Localhost, 127.0.0.1

이 블로그를 참고해봤을 때, 127.0.0.1 이 아니었다. localhost랑은 미묘한 차이가 있다고 한다.

  • localhost: Unix socket 파일을 통한 연결 (더 빠름)
  • 127.0.0.1: TCP/IP를 통한 네트워크 연결

나는 127.0.0.1이 없고 localhost가 있으니 localhost로 수정해주었다. 아마 MySQL에서는 두개의 미묘한 차이로 인해서 다른게 인식하는게 아닐까..?

→ 테스트 코드를 만들어서 테스트 해봤다.

public class test {
    @DisplayName("DB커넥션 연결 테스트")
    @Test
    void DB_test() throws SQLException {
        String url = "jdbc:mysql://localhost:3306/oop?useSSL=true&requireSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
        String username = "username";
        String password = "password";

        String url2 = "jdbc:mysql://127.0.0.1:3306/oop?useSSL=true&requireSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
        String username2 = "username";
        String password2 = "password";

        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            assertTrue(connection.isValid(5));
            System.out.println("localhost 데이터베이스 연결 성공!");
        }
        try (Connection connection = DriverManager.getConnection(url2, username2, password2)) {
            assertTrue(connection.isValid(5));
            System.out.println("127.0.0.1 데이터베이스 연결 성공!");
        }
    }
}

결과는 둘다 연결 성공… 이게 원인은 아닌것 같다..

나는 고민하다가 문득 사용자를 root로 사용하는것에 의구심이 들었다. 왜냐하면 root계정은 최상단의 계정으로 데이터베이스의 모든 권한을 갖고있을 뿐만 아니라, 프로젝트 데이터베이스 외에도 다른 데이터베이스와 연관되어있을 가능성이 존재할것이라고 생각했다. 실제로 다른 프로젝트에서 root를 쓰고 있다.

그러면 아예 프로젝트를 위한 사용자를 하나 따로 파서, 연결을 해주어야겠다고 생각했다.

CREATE USER 'oop.project'@'localhost' IDENTIFIED WITH caching_sha2_password BY '비밀번호는비밀';
GRANT ALL PRIVILEGES ON oop.* TO 'oop.project'@'localhost';
FLUSH PRIVILEGES;

이 명령어를 이용해서 새로운 사용자를 만들어주었고. yml의 유저이름과 비밀번호를 수정해서 연결하였더니

커넥션 연결이 완료되었다.


[문제원인]

root 계정은 모든 DB에 대한 모든 권한을 가지고 있는데, 운영환경에서 root계정을 사용하려고 했던것이 문제가 된 것 같다.


[해결 방안]

애플리케이션을 위한 전용 계정을 만들어서 사용하자.

  • 계정생성 명령어 분석
CREATE USER 'oop.project'@'localhost' IDENTIFIED WITH caching_sha2_password BY '비밀번호는비밀';
GRANT ALL PRIVILEGES ON oop.* TO 'oop.project'@'localhost';
FLUSH PRIVILEGES;

구문 의미

CREATE USER 새로운 사용자 계정을 생성
'oop.project'@'localhost' 사용자 이름은 oop.project, 접속 가능한 host는 localhost 한정
IDENTIFIED WITH caching_sha2_password 인증 플러그인은 caching_sha2_password 사용 (MySQL 8.x의 기본이자 보안성이 높음)
BY '비밀번호는비밀' 사용자 비밀번호는 비밀번호는비밀로 설정

구문 의미

GRANT ALL PRIVILEGES DB 작업에 필요한 모든 권한을 부여 (SELECT, INSERT, UPDATE, CREATE, DROP 등)
ON oop.* oop 데이터베이스의 모든 테이블(*)에 대해 적용
TO 'oop.project'@'localhost' 위 권한을 해당 사용자에게 부여

명령어 설명

FLUSH PRIVILEGES 위에서 부여한 사용자/권한 변경을 즉시 적용

GRANT ALL 은 모든 권한을 부여하는건데, 일부 권한만 부여해줄수도 있다.

MySQL :: MySQL 8.0 Reference Manual :: 8.2.2 Privileges Provided by MySQL

 

MySQL :: MySQL 8.0 Reference Manual :: 8.2.2 Privileges Provided by MySQL

MySQL 8.0 Reference Manual  /  ...  /  Security  /  Access Control and Account Management  /  Privileges Provided by MySQL 8.2.2 Privileges Provided by MySQL The privileges granted to a MySQL account determine which operations the account can perf

dev.mysql.com


[최종결과]

잘 돌아감