스프링 DB 1(김영한 강의) - 섹션 2 : 커넥션 풀과 데이터소스 이해

섹션 목적 : 커넥션 풀과 데이터소스를 이해해보자

 

1. 커넥션 풀의 등장 배경

   (1) DriverManager를 통해 DB 커넥션을 획득하는 과정은 다음과 같다

      ① DB와 TCP/IP를 통해 연결

      ② DB에 ID, PASSWORD 등 부가정보 전달

      ③ 커넥션 획득

   (2) 위와 같이 복잡하고 긴 과정을 거침. SQL 실행시간 뿐만 아니라 커넥션을 생성하는 시간도 추가되기 때문에 응답 속도에 영향을 미침

   (3) 이러한 문제를 해결하기 위해서 '커넥션 풀' 등장

 

2. 커넥션 풀 이해

   (1) 커넥션 풀이란 DB 커넥션을 여러개 생성해서 Pool에 두고 관리하는 방식임(커넥션 수영장)

   (2) 커넥션 풀 안에 있는 커넥션은 TCP/IP로 미리 DB와 연결되어있는 상태이므로, 언제든지 즉시 SQL을 DB로 전달할 수 있음

   (3) 그래서, 애플리케이션 로직은 매번 새로운 커넥션을 획득하는 것이 아니라, 커넥션 풀에 있는 커넥션을 가져다가 사용하고 반납함

   (4) 커넥션 풀은 대부분 Hikari를 사용

 

3. DataSource 이해

   (1) 커넥션을 획득하는 방법은 살펴본 것처럼, DriverManager을 사용하거나 커넥션 풀을 사용하는 등 여러 방법이 존재함

   (2) 그런데, 우리가 개발할 때 DriverManager를 이용해서 커넥션을 획득하다가 커넥션 풀로 변경하게 되면, 기존 코드를 모두 변경해야하는 문제점이 발생함

   (3) 따라서, 이러한 문제를 해결하기 위해서 'DB 커넥션을 획득하는 방법을 추상화'한 DataSource가 등장함

   (4) 사용방법 : Connection connection = dataSource.getConnection() 

   (5) DataSource의 등장으로 DriverManager에서 Hikari로 변경할 때, 애플리케이션 코드를 모두 변경할 필요 없이, DataSource의 구현체만 갈아끼우면 됨

 

4. DataSource 적용

   (1) MemberRepositoryV1에서는 DataSource를 주입받는 것으로 변경

   (2) MemberRepositoryV1의 getConnection 메서드를 dataSource.getConnection()으로 변경

   (3) close 메소드는 JdbcUtils.closeResultSet, closeStatement, closeConnection으로 변경

   (4) Test에서는 DataSource의 구현체를 DriverManagerDataSource나 HikariDataSource로 갈아끼움

   (5) DriverManagerDataSource는 항상 새로운 커넥션을 생성하는 반면, HikariDataSource는 미리 만들어 놓은 커넥션들을 사용하므로 사용하고 반환되었다면 같은 커넥션을 계속해서 사용함


이펙티브 자바 - 아이템 3 : private 생성자나 열거 타입으로 싱글턴임을 보증하라

1. 싱글턴이란?

   : 인스턴스를 오직 하나만 생성할 수 있는 클래스

 

2. 싱글턴을 만드는 방법

   (1) private 생성자, public static final Elvis INSTANCE = new Elvis();

   (2) private 생성자, private static final Elvis INSTANCE = new Elvis();, public static Elvis getInstance() { return INSTANCE; }

   (3) public enum Elvis3 {  INSTANCE; public void leaveTheBuilding() { //... } }

   (4) 중요한 포인트 : private 생성자 또는 Enum 타입으로 싱글턴임을 보장하라!


코테준비

1. 프로그래머스 - 모의고사

- 패턴에 맞게 점수를 체크하고, 점수가 최대인 사람을 반환

- for문을 이용한 완전탐색

 

2. 프로그래머스 - 소수 찾기

- 주어진 종이로 모든 수를 만들어보고, 그 중 소수의 갯수를 찾기

- 재귀를 이용해서 모든 수를 만들어보고, 소수 판별 알고리즘으로 소수를 판별한 후, Set을 이용해서 중복을 없앤 후에 갯수를 반환

 

3. 프로그래머스 - 카펫

- 모든 카펫의 경우를 해보며 계산

- 간단한 수학문제


이펙티브 자바에서 싱글턴을 만드는 방법을 소개하고 각각의 장단점을 소개했으나, 이해하지 못했다ㅜㅜ

모두 이해하지 못하더라도 핵심을 파악하여 하나씩 이해해보자

'TIL(Today I Learned)' 카테고리의 다른 글

2023.06.28  (0) 2023.06.29
2023.06.27  (0) 2023.06.27
2023.06.23  (0) 2023.06.23
2023.06.22  (0) 2023.06.22
2023.06.21  (0) 2023.06.21
스프링 DB 1(김영한 강의) - 섹션 1 : JDBC 이해

섹션 목적 : JDBC를 이해해보자

 

1. JDBC는 어떻게 등장하게 되었는가?

   (1) 클라이언트 -> 서버 -> DB, 이 흐름에서 서버가 DB에 데이터를 저장하거나 조회함

   (2) 그래서 서버는 

      ① DB와 커넥션을 연결

      ② SQL을 전달

      ③ 결과를 응답

   하는 흐름을 가짐

   (3) 그런데 DB마다 ①, ②, ③ 방식이 모두 다르다보니, DB를 변경하면 방법을 학습해야하고 코드를 바꿔야함

   (4) 이러한 문제를 해결하기 위해 JDBC가 등장

 

2. JDBC

   (1) JDBC는 위에서 발생한 3가지 문제를 interface로 제공함

   (2) 그래서 각 DB들은 이 interface를 구현해서 드라이버(ex. MySQL JDBC Driver, Oracle JDBC Driver)로 제공하고, 개발자는 이 interface에 의존해서 개발하면 됨

   (3) JDBC 등장으로 DB가 바뀌더라도, 새로 학습하거나 코드를 바꿔야할 필요가 없어짐

   (4) 하지만, DB마다 기본적으로 SQL, 일부 사용법들이 다르기 때문에 이 부분은 변경해야함

   (5) JPA는 이런 부분도 많이 해결할 수 있도록 도와줌

 

3. JDBC와 최신 데이터 접근 기술

   (1) JDBC는 오래된 기술이어서 사용방법이 복잡함. 그래서 이러한 JDBC를 편리하게 사용할 수 있도록 도와주는 기술이 등장함. 대표적으로 SQL Mapper 기술과 ORM 기술이 있음

   (2) SQL Mapper(ex. JDBC Template, MyBatis)

      ① SQL 응답결과를 객체로 편리하게 변환해줌

   (3) ORM(ex. JPA)

      ① 객체를 관계형 DB 테이블과 매핑해주는 기술임

   (4) 하지만 이 기술 모두 JDBC를 편리하게 사용할 수 있도록 도와주는 기술임. 내부적으로 모두 JDBC를 사용한다는 뜻

 

4. 애플리케이션과 DB를 연결

   (1) Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD)

   (2) Connection은 JDBC 표준 커넥션 인터페이스임

   (3) DriverManager.getConnection(...)은 H2 JDBC Driver가 제공하는 H2 전용 커넥션임(현재 H2를 사용하고 있으므로)

 

5. JDBC DriverManager 이해

   (1) DriverManager는 라이브러리에 등록된 DB 드라이버들을 관리함(말 그대로)

   (2) DriverManager는 라이브러리에 등록된 DB 드라이버들에게 (URL, USERNAME, PASSWORD)를 넘겨서 커넥션을 획득할 수 있는지 확인하고, 그 DB 드라이버에서 커넥션을 획득함

 

6. JDBC를 이용해서 CRUD 구현

   (1) DB 커넥션을 가지고 온다 - Connection

   (2) 커넥션에 SQL을 세팅한다 - Statement

   (3) DB에 커넥션을 전달하고 결과를 가져온다 - ResultSet

   (4) 사용한 자원(Connection, Statement, ResultSet)은 닫아준다


이펙티브 자바 - 아이템 2 : 생성자에 매개변수가 많다면 빌더를 고려하라

1. 생성자에 매개변수가 많은 경우 보통 점층적 생성자 패턴을 이용한다

   (1) 그렇지만, 이렇게 될 경우 매개변수가 많아지면 두 가지 문제점이 발생함

      ① 코드를 작성하거나 읽기가 매울 어려워짐

      ② 매개변수의 순서를 바꿔 입력해도 컴파일러는 알아채지 못하고 버그가 발생

 

2. 이 때 사용하기 좋은 방법은 빌더 패턴

   (1) 해당 class에 static class로 Builder를 만들고, 이 빌더에 값을 세팅하는 형식으로 바꿈

   (2) 사용방법은 NutritionFacts cocacola = new NutritionFacts.Builder(240, 8).calories(100).sodium(25).build(); 와 같음

   (3) 이렇게 하면 위의 두 가지 문제점을 해결할 수 있음

 

3. 또한 빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기 좋음

   (1) 예를 들어 Pizza 추상 클래스를 상속한 NewYorkPizza와 CalzonePizza가 있음

   (2) Pizza.Builder를 상속해서 각각 피자에 Builder를 만드는 방식임


스프링 DB1을 다시 보면서, 어떻게 스프링에서 DB와 연결짓는지 확실하게 구조를 이해해보자.

이펙티브 자바 예제 코드 꼭 직접 작성해보자. 백문이 불여일타!!!

'TIL(Today I Learned)' 카테고리의 다른 글

2023.06.28  (0) 2023.06.29
2023.06.27  (0) 2023.06.27
2023.06.26  (0) 2023.06.26
2023.06.22  (0) 2023.06.22
2023.06.21  (0) 2023.06.21
스프링 DB 2(김영한 강의) - 섹션 : 스프링 전파2

섹션 목적 : 실제 예제를 통해 어떻게 스프링 전파가 활용되는지 알아보자

 

1. 세팅

   (1) 요구사항 : 회원등록시, 회원 저장 및 DB에 로그를 남기는 것

   (2) 새롭게 알게된 점 

      ① JPA의 구현체인 하이버네이트가 테스트에서 테이블을 자동으로 생성

      ② 별도의 설정이 없을 경우, Test에서는 메모리 DB로 동작

      ③ 메모리 DB 생성 -> 모든 테스트 동작 -> 메모리 DB 삭제

      ④ JPA를 통해서 데이터를 변경할 경우 Transaction이 필요. 데이터 조회시 Transaction이 불필요

   (3) 구조 : memberService 안에서 memberRepository.save()와 logRepository.save() 가 동작함

 

2. memberRepo와 logRepo에는 @Transactional이 있고, memberService에는 없는 경우, 커밋 or 롤백

   (1) memberRepo에서 트랜잭션 하나 가져와서, 커밋 or 롤백하고 트랜잭션 반환.

   (2) logRepo에서 트랜잭션 하나 가져와서, 커밋 or 롤백하고 트랜잭션 반환.

   (3) 두 개의 트랜잭션은 독립적인 것이므로 서로에게 영향을 주지 않음(하나 커밋, 하나 롤백 가능)

   -> 이럴 경우 회원은 저장됐는데 로그는 저장이 되지 않는 데이터 정합성 문제 발생

   -> 따라서, 트랜잭션을 하나로 묶을 필요가 있음

 

3. 트랜잭션을 하나로 묶는 방법 첫번째 : 단일 트랜잭션

   (1) memberService에만 @Transactional을 두고, 나머지 repo에는 빼는 방법

   (2) 이렇게 하면 애초에 트랜잭션이 service에만 생성되므로, 하나의 흐름으로 동작함

   -> 그런데 이렇게 하면 repo 각각에서 트랜잭션이 필요한 요구사항이 있을 경우, 너무 많은 메소드를 따로 만들어야함.

 

4. 트랜잭션을 하나로 묶는 방법 두번째 : 트랜잭션 전파

   (1) memberService와 repo 모두 @Transactional을 사용, 기본 전파 옵션은 REQUIRED

   (2) 이렇게 하면, service에서 새로운 트랜잭션을 하나 가져옴

   (3) 이후 repo에서는 기존에 생성된 트랜잭션을 받아서 처리

 

5. 만약 logRepo에서 롤백되면?

   (1) logRepo가 예외를 던지고, 기존 트랜잭션에 rollbackOnly = true로 바꿈

   (2) memberService는 logRepo에서 예외가 발생해서 올라와서 자기도 예외가 발생했으므로, 롤백

 

6. 새로운 요구사항 : log가 저장이 안되더라도 회원은 저장시키자

   (1) 단순히 memberService가 logRepo에서 올라온 예외를 잡아서 처리하면 될까? 아니다

   (2) logRepo가 예외를 던지면서 트랜잭션에 rollbackOnly = true로 해놓았기 때문이다

   (3) 그래서 memberService가 예외를 잡아서 처리하더라도, 트랜잭션에 rollbackOnly가 true이므로 롤백하고 UnexpectedRollbackException이 발생한다

 

7. 그렇다면 어떻게? REQUIRES_NEW 전파 옵션을 이용해서, logRepo의 트랜잭션을 분리하자

   (1) logRepo의 트랜잭션 전파 옵션을 REQUIRES_NEW로 변경

   (2) logRepo에서는 기존 트랜잭션을 잠시 미뤄두고, 새로운 트랜잭션이 생성됨

   (3) logRepo는 이 트랜잭션에 커밋 or 롤백을 하고 트랜잭션 반환

   (4) memberService는 logRepo의 예외만 처리하면, 정상적으로 커밋 수행

   -> REQUIRES_NEW는 하나의 요청에 두개의 DB 커넥션을 사용하므로, 성능이 중요한 곳에서는 주의해서 사용해야


코테준비

1. 프로그래머스 - 최소 직사각형

- 간단한 수학문제


이펙티브 자바 - 아이템 1 : 생성자 대신 정적 팩터리 메서드를 고려하라

1. 클래스의 인스턴스를 얻는 전통적인 수단 -> public 생성자

 

2. 정적 팩터리 메서드란 public static Boolean valueOf(Boolean b) 와 같은 메서드

 

3. 얻을 수 있는 장점

   (1) 이름을 가질 수 있다

      : new Boolean(true) 보다 Boolean.valueOf(true)가 더 가독성이 뛰어나다

   (2) 호출할 때마다 인스턴스를 새로 생성하지 않아도 된다 

      : Boolean.valueOf(true)는 Boolean 클래스에 이미 만들어진 static 객체를 반환한다. 이렇게 되면 생성비용이 큰 객체가 자주 요청되는 상황에서 좋다. 또한, 인스턴스를 통제할 수 있다(ex. 싱글턴)

   (3) 반환 타입의 하위 타입 객체를 반환할 수 있다

      : 만약 interface에서 static 메서드로 구현체를 반환하면, 사용자는 실제 구현체가 무엇인지 알 필요가 없다. 유연하게 사용할 수 있음

   (4) 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다

      : (3)과 비슷한 뜻이라고 생각

   (5) 정적 팩토리 메소드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다

      : 무슨말인지 잘 모르겠다...

 

4. 팩토리 메소드에서 흔히 사용되는 명명 방식들(ex. from, of, valueOf, ...)


테니스

이번주 토요일에 서울시협회장배 테니스 대회 양천구 20대 대표로 나가게 돼서, 목동레인보우 클럽에서 같이 연습함

최애 파트너가 다치는 바람에ㅜㅜ 다른 아는 형님이랑 나가게 됐음

오늘 처음 맞춰봤는데, 하... 왜 하필 이 형님이랑 파트너한 경기만 지는거야ㅜㅜ 이 형님이랑 해서 이겨야되는데ㅋㅋ쿠ㅜㅜㅜㅜ

대회 때는 중요한 순간에 더 천천히 침착하게 해서, 상대가 포인트를 어렵게 따도록 해야겠다


TIL을 작성하면서 공부한 것을 한번 더 돌아볼 수 있어서 좋다.

한번 더 머릿속에 넣는 느낌도 들고, 다시 보면서 새롭게 알게되거나 더 자세히 알게되는 것도 있다.

'이펙티브 자바' 책은 아직 많이 어려운 것 같으니, 아이템 1씩 예제를 만들어가면서 해봐야겠다.

'TIL(Today I Learned)' 카테고리의 다른 글

2023.06.28  (0) 2023.06.29
2023.06.27  (0) 2023.06.27
2023.06.26  (0) 2023.06.26
2023.06.23  (0) 2023.06.23
2023.06.21  (0) 2023.06.21
스프링 DB 2(김영한) 강의 - 섹션 : 스프링 트랜잭션 전파1 

섹션 목적 : 트랜잭션이 둘 이상일 때 어떻게 동작하는지 알아보기

 

1. 기본

   (1) 트랜잭션이 동작하는 순서는 아래와 같다

      ① 트랜잭션 매니저로부터 트랜잭션 하나 획득(실제 DB에는 setAutoCommit(false)로 설정)

      ② 로직 실행

      ③ 트랜잭션 커밋 or 롤백

 

2. 트랜잭션 두 번 사용하기

   (1) 트랜잭션 하나 획득해서 커밋 or 롤백

      ① 커넥션 풀에서 DB와 커넥션 하나 가져와서 프록시로 감싸서 트랜잭션을 반환

      ② 로직 실행

      ③ 커밋하고 커넥션 풀에 커넥션을 반환

   (2) 트랜잭션 하나 획득해서 커밋 or 롤백

      ① 위랑 똑같이 진행. 커넥션 풀에서 가져오는 것이므로 위 트랜잭션과 실제 물리 커넥션을 같을 수 있다. 하지만 애초에 다른 트랜잭션임.

 

3. 트랜잭션 안에 트랜잭션이 있다면?

   (1) 전파 기본 옵션인 REQUIRED를 기준으로 설명

   (2) 외부 트랜잭션 안에 내부 트랜잭션이 있다면, 하나의 트랜잭션으로 진행됨

      이 때, 이렇게 두 개로 나누어진 트랜잭션을 논리 트랜잭션. 실제로 DB에 진행되는 트랜잭션은 물리 트랜잭션이라고 불림.

   (3) 원칙

      ① 모든 논리 트랜잭션 커밋 -> 물리 트랜잭션 커밋

      ② 하나라도 논리 트랜잭션 롤백 -> 물리 트랜잭션 롤백

 

4. Outer 트랜잭션 커밋, Inner 트랜잭션 커밋일 경우

   (1) Outer에서 새로운 실제 물리 트랜잭션 획득

   (2) Inner에서는 Outer에서 만들어진 트랜잭션을 위임받고, 커밋. 하지만, 이 트랜잭션은 위임받은 것이므로, 커밋하더라도 실제 물리 트랜잭션이 커밋되는 것이 아님.

   (3) Outer에서 커밋하면, Outer와 Inner 이 때 커밋됨.

 

5. Outer 롤백, Inner 커밋

   (1) Outer에서 물리 트랜잭션 획득

   (2) Inner에서 커밋하더라도 이는 실제 물리 트랜잭션의 커밋이 아님

   (3) Outer에서 롤백되면, Outer와 Inner 모두 롤백

 

6. Outer 커밋, Inner 롤백

   (1) Outer에서 물리 트랜잭션 획득

   (2) Inner에서 롤백되면, 트랜잭션에 rollback-only를 true로 변경함

   (3) Outer는 커밋할 때, rollback-only를 확인하고 true로 되어있으므로 롤백함.

      ① rollback-only가 true라는 뜻은 내부 트랜잭션 어딘가에서 rollback이 됐음을 의미.

   (4) 개발자는 커밋을 요청했는데 롤백이 됐으므로 이 현상을 알려야함. 그래서 UnexpectedRollbackException을 발생

 

7. Outer와 Inner의 트랜잭션을 분리할 수 있는 전파 옵션 : REQUIRES_NEW

   (1) Outer에서 물리 트랜잭션 획득

   (2) Inner에서도 새로운 물리 트랜잭션 획득

      ① 기존 Outer의 물리 트랜잭션은 잠시 미뤄둠

      ② 이후 Inner가 커밋 or 롤백하면, 미뤄둔 Outer 트랜잭션 시작

   (3) Outer 커밋 or 롤백

   (4) Outer와 Inner는 마치 두 개의 다른 트랜잭션을 사용하듯이 사용할 수 있음

 

8. 그 외에 기타 여러가지 전파 옵션이 존재한다.


   코테 준비

1. 프로그래머스 - 게임 맵 최단거리

- 평범한 BFS 문제. 한번에 맞추지는 못했는데, 조건을 꼼꼼하게 읽자

 

2. 프로그래머스 - 여행경로

- 시간이 남아서 한 문제 더 풀어봄. 그래프를 맵으로 표현하는 것을 떠올릴 수 있는 것이 중요.

 

3. 프로그래머스 - 아이템 줍기

- 한 문제 더. 좌표를 어떻게 표현할 것인가가 중요했던 문제. 힌트는 x2.


내일 '이펙티브 자바' 책이 오니깐, 코테 줄이고 이 책도 읽어보자

'TIL(Today I Learned)' 카테고리의 다른 글

2023.06.28  (0) 2023.06.29
2023.06.27  (0) 2023.06.27
2023.06.26  (0) 2023.06.26
2023.06.23  (0) 2023.06.23
2023.06.22  (0) 2023.06.22

+ Recent posts