Spring - JDBC, 3 Layer Architecture

김상엽·2024년 1월 24일
0

Spring

목록 보기
5/26
post-thumbnail

TIL

JDBC

  • JDBC는 Java Database Connectivity로 DB에 접근할 수 있도록 Java에서 제공하는 API이다.
  • JDBC에 연결해야하는 DB의 JDBC 드라이버를 제공하면 DB 연결 로직을 변경할 필요없이 DB 변경이 가능하다.
    • DB 회사들은 자신들의 DB에 맞도록 JDBC 인터페이스를 구현한 후 라이브러리로 제공하는데 이를 JDBC 드라이버라 부른다.
  • 서버를 변경할때 드라이버만 교체하면 손쉽게 DB 변경이 가능하지만, DB에 연결하기 위해서는 아직 여러가지 작업이 필요하다.

JdbcTemplate

  • 이러한 불편함을 해결하기 위해 커넥션 연결, statement 준비 및 실행, 커넥션 종료 등의 반복적이고 중복되는 작업들을 대신 처리해주는 JdbcTemplate이 등장했다.

JdbcTemplate 사용방법

  1. application.properties에 DB에 접근하기 위한 정보를 작성한다.
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password={비밀번호}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  1. build.gradle에 JDBC 라이브러리와 MySQL을 등록한다.
implementation 'mysql:mysql-connector-java:8.0.28'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
  1. DB연결이 필요한 곳에서 JdbcTemplate을 주입받아와 사용한다.
private final JdbcTemplate jdbctemplate;
public memoRepository(JdbcTemplate jdbctemplate) {
        this.jdbctemplate = jdbctemplate;
}
  • 생성자의 파라미터를 통해 JdbcTemplate 객체가 자동으로 넘어와 jdbctemplate 변수에 저장된다.

INSERT

String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
jdbcTemplate.update(sql, "KIM_TABLE_NEXT", "오늘 하루도 화이팅!");
  • INSERT SQL을 작성해 String 변수에 저장한 후 update() 메서드 첫 번째 파라미터에 넣어준다.
    • 이때, 넣고자 하는 데이터 부분에 ?를 사용하면 유동적으로 데이터를 넣어줄 수 있다.
  • jdbcTemplate.update() 메서드는 INSERT, UPDATE, DELETE 와 같이 생성, 수정, 삭제에 사용될 수 있는데 첫 번째 파라미터로 SQL을 받고 그 이후에는 ?에 들어갈 값을 받는다.

UPDATE

String sql = "UPDATE memo SET username = ? WHERE id = ?";
jdbcTemplate.update(sql, "KIM_TABLE_NEXT", 1);
  • UPDATE SQL을 작성해 String 변수에 저장한 후 update() 메서드 첫 번째 파라미터에 넣어준다.

DELETE

String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, 1);
  • DELETE SQL을 작성해 String 변수에 저장한 후 update() 메서드 첫 번째 파라미터에 넣어준다.

SELECT

String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
    @Override
    public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
        // SQL 의 결과로 받아온 Memo 데이터들을 MemoResponseDto 타입으로 변환해줄 메서드
        Long id = rs.getLong("id");
        String username = rs.getString("username");
        String contents = rs.getString("contents");
        return new MemoResponseDto(id, username, contents);
    }
});
  • SELECT SQL을 작성해 String 변수에 저장한 후 query() 메서드 첫 번째 파라미터에 넣어준다.
  • SELECT의 경우 결과가 여러 줄로 넘어오기 때문에 RowMapper를 사용하여 한 줄씩 처리 할 수 있다.
    • RowMapper는 인터페이스 이기 때문에 익명 클래스를 구현하여 처리한다.
    • 오버라이딩 된 mapRow 메서드는 제네릭스에 선언한 MemoResponseDto 타입으로 데이터 한 줄을 변환하는 작업을 수행한다.

3 Layer Architecture

  • 전에 진행한 일정관리 프로젝트는 Controller 클래스 하나로 모든 API를 처리하고 있다.
  • 현재는 API 수가 적고 기능이 단순하여 코드가 복잡해 보이지 않을 수 있지만 앞으로 기능이 추가되고 복잡해진다면 문제가 발생할 수 있다.
    • 한 개의 클래스에 너무 많은 양의 코드가 존재하기 때문에 코드를 이해하기 어렵다.
    • 현업에서는 코드의 추가 혹은 변경 요청이 계속 생길 수 있다.
    • 문제가 발생했는데 해당 Controller 클래스를 구현한 개발자가 퇴사한다면?

이러한 문제점들을 해결하기 위해 서버 개발자들은 서버에서의 처리과정이 대부분 비슷하다는 걸 깨닫고, 처리 과정을 크게 Controller, Service, Repository 3개로 분리했다.

1. Controller

  • 클라이언트의 요청을 받는다.
  • 요청에 대한 로직 처리는 Service에게 전담한다.
    • Request 데이터가 있다면 Service에 같이 전달한다.
  • Service에서 처리 완료된 결과를 클라이언트에게 응답한다.

2. Service

  • 사용자의 요구사항을 처리 ('비즈니스 로직') 하는 실세 중에 실세다.
    • 따라서 현업에서는 서비스 코드가 계속 비대해지고 있다.
  • DB 저장 및 조회가 필요할 때는 Repository에게 요청한다.

3. Repository

  • DB 관리 (연결, 해제, 자원 관리) 한다.
  • DB CRUD 작업을 처리한다.

3 Layer Architecture 의 전체 구조

오늘의 회고

강의를 더 듣고나니 더욱더 저번 일정관리 프로젝트를 잘못 설계했다는 생각이 들었다.
오늘 공부했던 내용과, 앞으로 배울 내용을 종합하여 다음 프로젝트부터는 더욱 예쁘게 설계해봐야겠다.
생각보다 Spring이 많은 기능을 도와주는것 같다.

profile
개발하는 기록자

0개의 댓글