본문 바로가기
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
    반응형

    댓글