본문 바로가기
Blog/Education

1주차 멘토링

by 코젼 2024. 6. 20.
728x90
반응형

🔶Layered Architecture

🔶동시성 테스트

🔶Git


목차


Layered Architecture

presentation layer -> domain layer -> infra layer

문제점: domain layer에서 DTO를 Mapper를 통해 타입을 변경할 수 없다. presentation layer에서만 적용 가능함.

 

DIP를 적용할 경우 domain layer에서 infra에 접근할 수 있다: domain layer <- infra layer

  • presentation layer
    • Controller, Request, Response
    • interface http api protocol
Request, Response
프로토콜 네이밍 규약에 따른 네이밍 지정
UserDTO.Request, UserDTO.Response 처럼 지정할 경우 가독성 Good~
  • domain(application) layer
    • Service, UserRepository(interface), User
    • DIP를 적용해서 Repository가 infra layer에서 올라오도록 한다.
  • infra layer
    • UserRepositoryImpl, UserEntity(jpa)
class UserService {
	User getUser() {
    	User user = userRepository.findById();
        return user;
        
        //UserEntity userEntity = userRepository.findById();
        //return UserMapper.toDomain(userEntity);
    }
}

interface UserRepository {
	User findByID();
}

class UserRepositoryImpl implements UserRepository {
	
    //생성자를 통해 구현체를 가져와서 사용할 수 있다.
    UserJpaRepository jpaRepo;

	UserRepositoryImpl(UserJpaRepository jpaRepo) {
    	this.jpaRepo = jpaRepo;
    }
    
    @Override
    User findById() {
    	UserEntity userEntity = jpaRepo.findById();
        
        //User user = User.of(userEntity); //주의* DIP 위반
        //return UserEntitMapper.toDomain(userEntity);
        
        User user = UserEntity.toUser(userEntity);
        return user;
    }
}

 

QNA

[기존 계층 흐름도]

UserController -> UserService -> UserRepository

 

[DIP 적용]

UserController -> UserService - UserRepository(interface) <- UserRepositoryImpl - UserEntity

 

0. DIP 적용하면 (클린 아키텍처 + 레이어드 아키텍처) 인가요?

-> 정확히는 아님 나중에 추가적 설명

1. UserRepository interface를 UserService와 함께 domain 계층에 둔다.

2. UserRepositoryImpl은 UserRepository의 구현체이다. (method overriding 진행)

  2-1. 생성자를 통해 주입 받을 구체적인 Repository를 지정한다 (예시: jpa, querydsl)

  -> UserJpaRepository interface 선언

3. UserEntity -> User 변환 작업이 필요할 경우 UserRepositoryImpl에서 진행한다.

  -> DIP 하고나서 양방향 참조가 생기지 않기 위해 진행 (꼬이지 않으려면)

  3-1. 주의* UserRepositoryImpl에서 변환 작업 시, User 객체에서 직접 메서드를 호출해서 변환하면 안된다.(DIP 위반)

  -> import 되기 때문에 (참조 발생)

  3-2. UserEntity의 메서드나 Mapper 클래스를 통해 User 객체로 변환한다.

  -> of로 하는 게 더 일반적이긴 함 (취향 차이~!)

  3-3. 질문: Mapper 클래스도 infra 계층에 두는 것이 맞나요?

  -> 각각 변환이 필요해서 infra controller에 각각 mapper가 필요함. 양쪽에서 변환해주기 때문에 도메인은 mapper 필요없음


테스트

  • controller E2E 테스트
    • mockMVC 사용
  • service 단위 테스트 -> repository stub/mock
  • service 통합 테스트 -> impl 물려서 테스트
  • repository 단위 테스트 X

Stub vs Mock

  • stub: 구현체 필요
  • mock: 재사용 불가

동시성 테스트

동시에 요청이 들어온 걸 정합성을 지키면서 처리한다.

동일한 요청자가 여러 번 시도하거나, 공유 자원에 대해서 동시성이 발생할 경우 문제가 발생한다.

userA: a 요청
userB: b 요청

주의* 네트워크 스펙(라우팅 등)이 다르기 때문에 동시에 요청하더라도 어떤 요청이 수행될지 알 수 없음
TCP는 데이터를 순차적으로 전송한다.
  • Lock
    • Lock을 오래 기다리는 요청 스레드가 많아질 경우 메모리에 문제가 생긴다.
    • ReetrantLock (ex. id 별 Lock 지정)
  • 메모리
    • ConcurrentHashMap (순차적 보장 해시맵)
  • CountDownLanch.await()
  • CompletableFuture.allOf({병렬로 수행할 함수 집합}).join()
    • 병렬로 스레드 열에서 작업시킬 수 있다.
  • synchronized atomic
  • mutex
  • valitile
  • semaphore
  • CyclicBarrier
  • StampedLock
  • 등등등.......................

 

Addition

Timestamp -> Queueing

셀레니움

시나리오 테스트

DTO - Mapper 클래스, of, from 메서드

샤딩? 분산?


Git

git switch -c branch

현재 있는 브랜치 기반으로 새로운 브랜치 생성

728x90
반응형

댓글