티스토리 뷰

[허재 코치님이 깨달은 것]

- "나는 지금까지 뭘 하고 있었던거지??" 라는 생각을 했다고 함.

- 조금 더 체계적으로 개발을 하도록 미리 알았으면 좋지 않을까라는 생각을 했다고 함.

- 체득을 하고 나서 개발하는 속도나 역량은 기하급수적으로 늘어났다.

- 핵심 : 아키텍쳐, TDD 방식 등 체계적으로 개발하는 방법을 알면 더 코딩 실력을 높일 수 있다.

 

[우리가 말하는 도메인이란 무슨 뜻이지????]

1. 도메인 : 특정 기능과 관련된 속성, 기능들을 "응집화" 시켜 놓은 개념.

예시1 : 도메인 이해도가 높아야 한다 ==> 해당 기능을 구성하는 응집화된 비즈니스 로직들에 대한 이해가 깊어야 한다.

예시2 : 도메인 모델 ==> 일반적으로 기능을 군집화 시킨 도메인의 객체, 엔티티 등을 의미

예시3 : 도메인 uri ==> 하위 uri를 그룹핑할 수 있는 응집화된 url.   /cafe.naver.com, /blog.naver.com은 모두 naver.com의 상위 도                                      메인을 바라보고 있다.

 

이렇게 크게 3가지의 방식으로 "도메인"이라는 용어를 설명할 수 있다.

 

[그럼 엔티티는 무슨 뜻일까???]

2가지로 설명할 수 있다

1. 도메인 관점에서 엔티티 : 특정 주제나 기능에 대해서 응집화 시켜놓은 도메인 모델

2. DB 관점에서 엔티티 : DB 테이블이나 그 테이블에 매핑되는 객체

 

이렇게 엔티티는 2가지 관점에서 다른 뜻으로 사용될 수 있다.

 

[중요!!!!! 패키지 구조는 어떻게 가져가야 할까?????]

 

*** 도메인별로 응집도가 강한 패키지 구조 ***

api/
  도메인/
	  controller
	  dto/
		  (request, response models)
domain/
	도메인/ (user, lecture, comment, ...)
		(Models)
		- Lecture
		- ApplicationHistory // 얘가 순수 객체든 DB Entity 든 상관이 없다.
												// 왜 ? ORM 이 주는 Entity 는 사실 그들이 인지할 수 있는 객체.
		(business - Application)
		- LectureApplicationService // 강의 서비스, 유저 서비스 -> 비즈니스 로직
		(business - Service)
		- LectureService // 강의에 대한 기본 기능
		(business - Repositories)
		- LectureReaderRepository (I/F) // 읽기 전용
		- LectureStoreRepository (I/F) // 쓰기 전용
		infrastructure/
			- LectureCoreReaderRepository (IMPL)
			- LectureCoreStoreRepository (IMPL)
			- LectureJpaRepository (JPA)
			- LectureCustomRepository (QueryDSL)

interface LectureReaderRepository {
	fun findByName(name: String)
}

interface LectureJpaRepository: JpaRepository<Lecture, Long>

class LectureCoreReaderRepository(
	private val lectureJpaRepository: LectureJpaRepository
) : LectureReaderRepository {
	기능 제공
	
	override fun findByName(name: String)
}

위 패키지 구조의 장점은 "도메인별로 강한 응집도"를 가지고 있다는 점이다.

User 관련된 모든 Component, Repository는 User domain 폴더에 있다. Lecture와 관련된 모든 기능은 Lecture domain 폴더에 있다. 이렇게 도메인별로 응집도가 강한 패키지 구조여서, 프로젝트를 따로 개발할 때 필요한 도메인 패키지만 똑 떼어서 가져갈 수 있다.

api : Presentation 레이어로서 Controller가 여기에 해당한다

domain : 주요 비즈니스로직이 존재하는 곳.

 

- Repository 추상화 이유 : 

=> 비즈니스 로직은 주방에서 일하는 것과 같다. 내가 주방에서 일하는데 재료가 어디서 재배되는지 알 필요 없다. 그냥 나는 재료를 가지고 요리만 만들면 된다. 너무 많이 알고 있으면 그건 오히려 나의 책임이 너무 크다는 것이다.

문제가 생긴다면 재료의 원산지를 잘못 알아서 그런지 등등 원인 파악이 어렵다.

그래서 비즈니스로직<->DB간의 상호작용에 대해서 몰라야 함.

 

ORM : 데이터베이스와 소통하기 위해서 도와주는 것이다. 개발자가 어떤 DB를 쓰는지에 대해서 궁금하지 않다. => DB 종류에 종속적이지 않다. Entity는 이것을 도와주는 것임.

 

꿀팁! : 실무에서는 레포지토리에 대해서 Read / Write를 분리한다. 왜냐하면 조회에 부하가 많이 걸리는 경우가 많기 때문이다.

Read DB와 Write DB가 분리되어 있다. 조회는 많은데 update가 별로 없다고 한다면 update 할 때 락을 걸어버리면, 조회 요청이 모두 대기 상태가 되기 때문에 트래픽 부하가 높아진다.

 

위와 같이 허재코치님은 도메인이 다르다고 하면 탑 레벨의 폴더(domain)에서 구분한다고 함.

다음 번 개발에서는 이렇게 구분해서 해보기

 

* 위 패키지 구조의 문제점

배치서비스, 연계서비스 등의 기능이 생기면 그런 배치 프로그램들 또한 도메인별로 위치해야 하므로

기능이 생길 때마다 비즈니스로직 도메인이 점점 뚱뚱해진다.


위의 문제점을 개선한 부페식 구조!! 뭐가 필요한지 모르겠지만 일단 다 차려놨어!

 

개선된 패키지 구조(부페식 구조)

admin/
	도메인/
		view/
		usecase/
			- ModifyLectureUseCase
			- GetMyApplicationsUseCase
				// 강의 목록 + 보여주는 정보가 더 많음.
			- GetLecturesUseCase
api/
  도메인/
	  controller
	  dto/
		  // request 객체 - 무조건 필요 ( 우리가 제공하는 Controller 기능 수 만큼 )
		  (request, response models)
	  usecase/
		  (Usecase = 각 비즈니스에 맞춰 component 조립)
			  // 사용자가 수강신청을 하는 기능
		  - ApplyLectureUseCase(lectureReader, userReader, applicationManager)
			  - execute()
			  // 강의 목록을 조회하는 기능
		  - GetLecturesUseCase
			  - execute()
domain/
	도메인/ (user, lecture, comment, ...)
		(Models)
		- Lecture
		- ApplicationHistory
		(Components) // 작은 단위의 비즈니스 로직
		- LectureReader
		- LectureModifier
		- ApplicationManager
		(Repositories)
		- LectureReaderRepository (I/F)
		- LectureStoreRepository (I/F)
		infrastructure/
			- LectureCoreReaderRepository (IMPL)
			- LectureCoreStoreRepository (IMPL)
			- LectureJpaRepository (JPA)
			- LectureCustomRepository (QueryDSL)

 

UseCase 레이어를 추가한다. 그래서 domain 로직에 영향 없이 UseCase에 추가하고 싶은 기능을 추가할 수 있다.

- 예시 : 새로운 기능 추가해줘~  => UseCase에 새로운 기능을 추가하고, domain에 있는 기능들을 갖다 써서 기능을 구현하면 된다.

- Controller와 UseCase는 강결합이 되어있다. UseCase가 사실상 Service 같은 역할인데, Service보다 좀 더 잘게 쪼개진 것.

- 기능별로 UseCase가 만들어진다. UseCase에서는 domain의 로직들을 필요한 걸 갖다가 써서 구현하면 된다.

 

UseCase 구조가 생기는 이유는 api 서버뿐만 아니라 배치서버, 어드민서버 등도 생길 경우에 Service가 뚱뚱해지기 때문에, Service에 해당하는 로직이 UseCase 폴더로 올라온 것이라고 보면 된다.

 

==> 이번 시나리오 구축시에는 이런 방식으로 개발을 해보자

 

[서버구축 시나리오]

1. 이커머스

- 장바구니 기능

- 남은 재고가 표시되게 하기 위해서 어떻게 해야할지 고민하기. 실시간으로 잔여 재고를 성능을 저하시키기 않게 구현

 

2. 맛집

- 네이버가 장애가 났을 때 카카오 API로 정보를 줘야함

- 인기 키워즈 조회, 저장하는 기능이 검색기능에 영향을 주면 안된다.

- H2 코드는 지역 코드

 

3. 콘서트 티케팅

- 대기열 시스템을 맛볼 수 있는 과제

- 유저토큰이 있어야 예약 가능 => 인터셉터 기능이 필요

- 해당 좌석이 임시로 5분간 배정

- 배정과 임시배정을 구현하는게 중요

- 대기열을 구현하는게 첫번재 관문

 

 

 

 

 

 

 

댓글