인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

백엔드 지망생님의 프로필 이미지

작성한 질문수

순수 JDBC 강의 화이트라벨 에러

작성

·

911

·

수정됨

0

안녕하세요. 코드로 8080에 접속해서 회원가입하고 등록하는건 잘 되었습니다. 또한 h2-database에서
http://localhost:8082/login.do?jsessionid=573840fda7971b85bee554c496227dcd
로 들어가서도 문제없이 하였습니다.

@Bean
public MemberRepository memberRepository() {
  // return new MemoryMemberRepository();
    return new JdbcMemberRepository(dataSource);
}

하지만 return new JdbcMemberRepository(dataSource); 이렇게 하고 이름을 입력하고 등록을 누르거나 조회를 누르면 화이트라벨 에러가 발생합니다.

spring.application.name=hello-spring
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa

properties는 문제없이 입력하였습니다.

2024-06-16T14:47:06.989+09:00 ERROR 15340 --- [hello-spring] [nio-8080-exec-3] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Exception during pool initialization.

org.h2.jdbc.JdbcSQLNonTransientConnectionException: Connection is broken: "java.net.ConnectException: Connection refused: getsockopt: localhost" [90067-224]

2024-06-16T14:47:07.004+09:00 ERROR 15340 --- [hello-spring] [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalStateException: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection] with root cause

java.net.ConnectException: Connection refused: getsockopt

에러가 길어서 핵심적인 에러들만 가져왔습니다. 스프링도 3. 이상이여서 h2를 2.1.214 버전 이상 사용하였습니다. 밑에 코드들은 저의 인텔리제이에 있는 코드들입니다. 대부분 복붙해서 문제는 없는거 같아요.

package hello.hello_spring.repository;

import hello.hello_spring.domain.Member;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class JdbcMemberRepository implements MemberRepository {
    private final DataSource dataSource;
    public JdbcMemberRepository(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    @Override
    public Member save(Member member) {
        String sql = "insert into member(name) values(?)";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            pstmt.setString(1, member.getName());
            pstmt.executeUpdate();
            rs = pstmt.getGeneratedKeys();
            if (rs.next()) {
                member.setId(rs.getLong(1));
            } else {
                throw new SQLException("id 조회 실패");
            }
            return member;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }

    @Override
    public Optional<Member> findById(Long id) {
        String sql = "select * from member where id = ?";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setLong(1, id);
            rs = pstmt.executeQuery();
            if(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return Optional.of(member);
            } else {
                return Optional.empty();
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    @Override
    public List<Member> findAll() {
        String sql = "select * from member";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();
            List<Member> members = new ArrayList<>();
            while(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                members.add(member);
            }
            return members;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    @Override
    public Optional<Member> findByName(String name) {
        String sql = "select * from member where name = ?";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, name);
            rs = pstmt.executeQuery();
            if(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return Optional.of(member);
            }
            return Optional.empty();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    private Connection getConnection() {
        return DataSourceUtils.getConnection(dataSource);
    }
    private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (pstmt != null) {
                pstmt.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (conn != null) {
                close(conn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    private void close(Connection conn) throws SQLException {
        DataSourceUtils.releaseConnection(conn, dataSource);
    }
}

 

package hello.hello_spring.repository;

import hello.hello_spring.domain.Member;
import org.springframework.stereotype.Repository;

import java.util.*;


public class MemoryMemberRepository implements MemberRepository {
    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;
    @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }
    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }
    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }
    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }
    public void clearStore() {
        store.clear();
    }
}


 



 

답변 1

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다.

이현준님, 스프링 부트 애플리케이션에서 H2 데이터베이스 접속 시 발생하는 ‘화이트라벨 에러’와 관련된 문제에 대해 답변 드리겠습니다. 에러 로그를 살펴보면, HikariCP를 통한 데이터베이스 연결 초기화 과정에서 ‘Connection refused: getsockopt’ 오류가 발생하고 있습니다. 이는 스프링 부트 애플리케이션에서 설정한 데이터베이스 접속 정보와 실제 데이터베이스의 상태 또는 설정이 일치하지 않음을 나타냅니다.

properties 설정 내용을 보면, 스프링 데이터 소스 URL이 ‘jdbc:h2:tcp://localhost/~/test’로 설정되어 있는데, 이 주소로의 연결이 거부되고 있습니다. H2 데이터베이스가 TCP 서버 모드로 실행 중이고 해당 주소와 포트(localhost:9092가 기본값)에서 대기하고 있는지 확인해야 합니다.

문제 해결을 위한 몇 가지 확인 사항을 안내해 드리겠습니다:

  1. H2 데이터베이스가 실제로 실행 중인지, 그리고 TCP 서버 모드로 구동되고 있는지 확인하십시오. H2 데이터베이스를 스프링 부트 애플리케이션과 동일한 호스트에서 실행 중이라면, 해당 TCP 서버 모드에 대한 설정(예: 포트 번호)이 올바른지 확인해야 합니다.

  2. 스프링 데이터 소스 URL 주소에 명시된 경로와 포트 번호가 정확한지 검증하십시오. ~/test 경로는 사용자 홈 디렉토리에 위치한 test 데이터베이스를 가리키며, 이 경로가 올바른지 확인하십시오.

  3. 포트 번호가 명시되지 않았다면, H2 데이터베이스의 기본 포트인 9092를 사용하고 있는지, 아니면 커스텀 포트 번호를 사용하고 있다면 해당 포트가 올바르게 설정되었는지 확인하십시오.

에러 메시지의 ‘Connection refused’ 부분은 대개 네트워크 연결 문제, 즉 클라이언트(여기서는 스프링 부트 애플리케이션)가 데이터베이스 서버에 접속하려 할 때 해당 서버가 요청을 받을 준비가 되어 있지 않을 때 발생합니다. 이는 데이터베이스 서버가 아직 시작되지 않았거나, 서버의 방화벽이나 보안 설정으로 인해 접속이 차단되었거나, 주소나 포트 정보가 잘못되었을 수 있습니다.

따라서, 위의 점검 사항을 바탕으로 설정을 다시 한 번 확인하시고, 필요하다면 H2 데이터베이스 서버의 실행 상태나 설정을 재검토하십시오.