26/07/20 IL(I Learned) - Step 3

Repository와 Service 계층을 활용한 비즈니스 로직 구현

Repository와 Service 계층을 분리하여 사용하는 이유를 학습하였다. 이전 JDBC 프로젝트에서는 Main 클래스가 Repository를 직접 호출하여 데이터를 처리했지만, 이번 프로젝트에서는 Controller → Service → Repository 구조를 적용하여 계층별 역할을 명확하게 분리하였다.

또한 JdbcTemplateRowMapper를 이용하여 기존 JDBC 코드보다 훨씬 간결하게 데이터베이스를 다루는 방법을 익혔으며, @Transactional을 통해 여러 작업을 하나의 트랜잭션으로 관리하는 방법도 함께 학습하였다.

그리고 Spring은 단순히 JDBC를 대신해 주는 프레임워크가 아니라 객체 간의 역할을 명확하게 나누고 유지보수성을 높여주는 구조를 제공하는 프레임워크라는 점을 이해하게 되었다.


1) AccountRepository

학습 내용상세 내용
Repository Interface데이터 접근 기능을 정의하는 인터페이스이다.
CRUDCreate, Read, Update, Delete 기능을 하나의 인터페이스에서 관리한다.
인터페이스구현체가 바뀌어도 사용하는 코드는 변경하지 않아도 된다.
추상화구현 방법보다 기능 자체를 먼저 정의하는 객체지향 설계 방식이다.
public interface BankAccountRepository {

    void save(Account account);

    void update(Account account);

    List<Account> findAll();

    Account findById(long id);

    void deleteById(long id);

}

이번 프로젝트에서는 Repository를 인터페이스로 먼저 작성하였다.

인터페이스에는

  • 저장
  • 조회
  • 수정
  • 삭제

기능만 정의하였다.

실제 SQL은 작성하지 않는다.

즉,

무엇을 할 것인가

만 정의한다.

실제로

어떻게 할 것인가

는 구현 클래스가 담당한다.


인터페이스를 사용하는 이유

예를 들어

현재는

SQLAccountRepository

를 사용하지만

나중에는

MongoRepository

또는

RedisRepository

로 변경할 수도 있다.

Controller와 Service는

Repository가 어떻게 구현되어 있는지 알 필요가 없다.

오직

save()

findAll()

findById()

만 알고 있으면 된다.


Repository 추상화 구조

Controller

↓

Service

↓

AccountRepository

↓

SQLAccountRepository

이러한 구조를

다형성(Polymorphism)

이라고 한다.

느낀 점내용
인터페이스구현보다 기능을 먼저 설계하는 객체지향 방식을 이해하였다.
유지보수구현체가 변경되어도 다른 코드를 수정하지 않아도 되는 장점을 알게 되었다.
다형성인터페이스를 사용하는 이유를 실제 프로젝트를 통해 이해하였다.

2) SQLAccountRepository

학습 내용상세 내용
JdbcTemplateSpring에서 제공하는 JDBC 도우미 클래스이다.
RowMapper조회 결과(ResultSet)를 객체로 변환하는 인터페이스이다.
query()여러 데이터를 조회한다.
queryForObject()하나의 데이터를 조회한다.
update()INSERT, UPDATE, DELETE를 수행한다.
@Repository
@RequiredArgsConstructor
public class SqlAccountRepository
        implements AccountRepository {

    private final JdbcTemplate jdbcTemplate;

}

기존 JDBC에서는

Connection

PreparedStatement

ResultSet

을 모두 직접 생성해야 했다.

하지만 Spring에서는

JdbcTemplate

하나만 있으면

이 모든 과정을 내부에서 자동으로 처리해 준다.

즉,

개발자는

SQL만 작성하면 된다.


JdbcTemplate 내부 동작

JdbcTemplate

↓

Connection 생성

↓

PreparedStatement 생성

↓

SQL 실행

↓

ResultSet 반환

↓

Connection 종료

이 과정을 Spring이 모두 대신 수행한다.


INSERT

jdbcTemplate.update(query, account.getName());

update() 메서드는

INSERT

UPDATE

DELETE

모두 수행할 수 있다.

반환값은

영향 받은 행(Row)의 개수이다.


SELECT

여러 개 조회

jdbcTemplate.query()

한 개 조회

jdbcTemplate.queryForObject()

를 사용하였다.


RowMapper

Repository에는

private static final RowMapper<Account>

가 존재한다.

RowMapper는

ResultSet을

객체로 변환하는 역할을 수행한다.

즉,

ResultSet

↓

Account 객체

변환기 역할을 한다.


RowMapper 흐름

SELECT

↓

ResultSet

↓

RowMapper

↓

Account

↓

List<Account>

JdbcTemplate의 장점

기존 JDBCJdbcTemplate
Connection 직접 생성자동 생성
Statement 생성자동 생성
close() 호출자동 처리
SQLException 처리Spring이 관리

느낀 점내용
코드 간결화반복되던 JDBC 코드가 크게 줄어들었다.
RowMapperResultSet을 객체로 변환하는 과정이 매우 편리하였다.
Spring의 역할Spring이 반복적인 작업을 자동으로 처리해 준다는 점을 체감하였다.

3) BankService & BankServiceImpl

학습 내용상세 내용
Service Layer비즈니스 로직을 담당하는 계층이다.
@ServiceService Bean으로 등록한다.
@Transactional여러 작업을 하나의 트랜잭션으로 관리한다.
DTO → Entity사용자의 입력을 Entity로 변환한다.
Entity → DTO조회 결과를 ViewDTO로 변환한다.
@Service
@RequiredArgsConstructor
public class BankServiceImpl implements BankService{

    private final AccountRepository repository;

}

Service는

Controller와 Repository 사이에서

중간 역할을 수행한다.

즉,

Controller는

Repository를 모른다.

Repository 역시

Controller를 모른다.

둘 사이를

Service가 연결한다.


Service 흐름

Controller

↓

BankService

↓

Repository

계좌 생성

Account account =
        Account.builder()

        .name(dto.name())

        .build();

FormDTO를

Entity로 변환하였다.

그 이후

repository.save(account);

를 호출한다.


계좌 조회

Repository는

Entity를 반환한다.

하지만

Controller는

ViewDTO를 원한다.

그래서

AccountViewDTO.fromEntity(...)

를 호출하여

DTO로 변환하였다.


계좌 수정

수정 과정은

조금 더 복잡하다.

DTO

↓

Repository.findById()

↓

Entity

↓

이름 변경

↓

Repository.update()

즉,

기존 Entity를 조회한 뒤

필드만 변경하여

Repository에게 전달한다.


@Transactional

@Transactional

여러 작업을

하나의 작업처럼 처리한다.

예를 들어

계좌 생성

↓

로그 저장

↓

알림 발송

세 작업 중

하나라도 실패하면

모두 취소된다.

이를

Rollback이라고 한다.


Transaction 흐름

BEGIN

↓

SQL1

↓

SQL2

↓

SQL3

↓

COMMIT

(실패 시 ROLLBACK)

Service 계층을 사용하는 이유

ControllerService
요청 처리비즈니스 로직
화면 연결업무 처리
View 반환Repository 호출

Service를 분리하면

Controller가 훨씬 단순해지고

비즈니스 로직을 한곳에서 관리할 수 있다.


느낀 점

느낀 점내용
Service Layer단순히 Repository를 호출하는 것이 아니라 비즈니스 규칙을 관리하는 계층이라는 점을 이해하였다.
Transaction여러 작업을 하나의 작업 단위로 묶는 이유를 배웠다.
Spring 구조Controller, Service, Repository를 분리하면 유지보수성과 확장성이 크게 향상된다는 점을 느꼈다.
profile
예 마 함 가보입시더

0개의 댓글