유튜브 제미니의 개발실무를 운영하고 있습니다.
강의
수강평
- 제미니의 개발실무 - 지속 성장 가능한 소프트웨어를 만들어가는 방법
- 제미니의 개발실무 - 지속 성장 가능한 소프트웨어를 만들어가는 방법
- 제미니의 개발실무 - 지속 성장 가능한 소프트웨어를 만들어가는 방법
게시글
질문&답변
동일 계층의 애플리케이션 서비스가 서로의 인터페이스를 사용하여 의존하는 경우에 대해서
안녕하세요 :D 토비님에게 해당 질문에 대해서 전해들어서 저도 짤막히 생각을 달아봅니다🙂그 전에 먼저 오래 된 글인데도 봐주시고 언급까지 해주셔서 감사합니다!핵심 질문에 대한 얘기를 먼저 해보면 (다만,, 제가 현실이 너무 바빠서 강의를 아직 못 봤습니다ㅜㅜ 이 점 양해를... 토비님 사랑합니다)같은 계층에서 인터페이스 포트를 통해서 호출하는 것은 괜찮을까 고민이 들었습니다. 적어 주신 질문 글의 맥락으로 보면 저런 케이스의 호출에 대한 것은 전략을 정할 수 있는 영역으로 보입니다. 코드를 못 봤지만 맥락 기준으론 허용이 충분히 가능하다고 봅니다, 특히 구현체가 아닌 인터페이스 기반이라면 더욱 허용이 쉬워진다고 생각합니다. 다만, 이런 호출의 기반에는 올바른 개념(도메인)의 정립과 아래 설명한 '격벽'(단어와 상관없이 개념간 경계 영역 의 대하여 고민이 선제 되어야한다 생각합니다.(단순히 해당 규칙을 허용하는 순간 잘못 된 개념끼리도 엮일 수 있으니까요, 물론 이 부분도 코드 리뷰나 도메인 리뷰가 철저하다면 괜찮겠지만요)[해당 글의 '레이어'에 대하여]과거의 제 글에서 ‘레이어’라고 소개 된 부분은 사실 '레이어드 아키텍처' 를 강조하고 설명하고자 한 글은 아닙니다사실 이런 오해(?) 때문에 저는 요즘 ‘격벽’(2024인프콘 에서 발표한..) 이라는 용어를 더 많이 쓰는데요 결국 다양한 관점이 있지만 공통 분모로 개발자들이 말하는 것은 우리가 소중히 여겨야하는 부분(그걸 '개념'이라 부르건 '도메인'이라 부르건)을 어느정도 의존시키고, 어떻게 협력시킬지에 대하여 어떤 전략을 가져갈지 결정하는 것이 핵심인 것 같습니다. 저는 이런 측면에서 레이어드 / 포트&어뎁터 이렇게 무 자르듯이 아키텍처 결정하고 나누는 것은 선호하지 않습니다제 기준에서는 잘 만든 레이어드가 진화하면 건강한 도메인이 나올 수 있고 필요에따라 포트&어뎁터로 진화하는 것은 상당히 쉬운 일이라고 생각하기 때문입니다. 추가로 해당 글의 비즈니스로직 + 레이어 챕터의 핵심은 토비님이 적어 주신 것이 정확합니다.상세 구현 로직은 잘 모르더라도 비즈니스의 흐름은 이해 가능한 로직이어야 한다. 제가 여러 조건 때문에 현재 강의를 찍을 순 없지만, 추후에 이런 내용을 종합하여 한번 강의로 찍어보고 싶네요 :D [동일 레이어 참조 허용 규칙 관련]저도 재민님께서 저렇게 제안하신 이유는 아마 설계의 단순성을 통해서 여러사람이 같은 영역을 작업하기 편하게 한 것 같다는 생각이 듭니다.MASKUN 님이 답변 주신 것 처럼 해당 글의 저 규칙은 특정 현실 상황에 상당히 유리한 면이 있습니다.개발 팀원 수개발 팀원들의 역량 수준개발 팀원들을 코드 리뷰/코칭 해줄 수 있는 여유가 있는가각개전투로 인당 프로젝트를 1개씩 해야하진 않는가 등등 개발할때에는 현실적인 상황을 종합적으로 고려해서 해야합니다, 그렇다면 저 글의 최대 효율은 언제 나올까를 생각해보면 대부분의 조건이 열악한 상황에서 최선의 효율정도 까지는 보장이 됐던 것 같습니다 .(온전히 제 경험 기준입니다 :D )최악의 경우로 말하면... 누군가 코드를 망쳐놔서 그로인해 회사에 심각한 문제가 있을때, 제가 직접 가서 해결해야하는 상황에서 그나마 최선의 코드를 만날 수 있습니다. 😅 모쪼록 좋은 질문과 토비님의 깔끔한 답변과 질문자 분의 정리까지 즐거운 글 같습니다 :D제 글 뿐만 아니라 토비님의 강의에서도 장점과 단점 트레이드 오프에 대하여 충분히 이해하시고 처해계신 상황에 맞는 전략을 결정해서 펼쳐나가보시길 바라겠습니다. 다양한 관점을 융합해서 시도해보고 실험하다보면 MASKUN님 만의 새로운 전략 및 철학이 탄생할 수 있을 것이라고 생각하고, 저는 그런 것이 수 많이 이미 정립된 이론 보다 멋진 것 이라고 생각합니다 다시 한번 알찬 질문과 글 언급 감사드립니다 :D 추가로 아래 내용은 저는 잘 만들면 이런 문제는 없다 라고 생각하긴 하는데ㅎㅎ (그런 문제가 생기기 쉬운 것은 팩트이긴합니다) 이건 저도 추후에 코드로 보여줄 수 있으면 좋을 것 같네요!도메인 모델의 빈혈을 유발할 수 있겠다는 생각이 드네요.
- 5
- 2
- 1.2K
질문&답변
Business Logic!
외부에서 주입받도록 분리한 로직들이 의미하는 부분이 어떤 로직을 말하시는 건지 애매한 것 같습니다! 외부 라이브러리나, 외부 통신을 위한 클라이언트를 의미하시는 걸까요? 그렇다면 Data Access Layer 에 해당합니다!
- 0
- 2
- 345
질문&답변
Business Layer 인자 처리
1. 클라이언트로부터 전달되는 presentation layer 에서 바로 전달받는 것을 기대하셨는지2. 아니면 리팩토링 전과 같이 payRequest 로 controller에서 전달 받은 뒤 다른 layer (business 혹은 presentation) 에서 dto 로 변경한 뒤 businessPay() 메서드를 호출하여 인자를 입력해주는 것을 기대하셨는지3. 아니면 다른 방법으로 진행이 되는지2번입니다!PayRequest 가 Presentation Layer 에 있는 상황에서, Business, Implement Layer 에 파라미터로 넘어온다는 것 자체가 레이어를 지키는 규칙을 위반하는 '레이어 역류' 에 해당 되버리기 때문입니다. 그래서 흐름 상으로 보면 외부 랑 가장 가까운 Presentation Layer 에서 PayRequest 를 받고 Presentation Layer 에서 Business Layer 로 가기전에 Business, Implement Layer 의 객체로 변환을 하고 넘겨준다고 이해하시면 될 것 같습니다. 제 유튜브에도 있을 것 같은데 저도 못 찾겠네요;; 관련해서는 예전에 제가 발표했던 내용을 참고해 보시면 좋을 것 같습니다!https://youtu.be/RVO02Z1dLF8?si=Wj4ZhsYESDE2T5xS&t=508 질문 감사드립니다!
- 1
- 2
- 360
질문&답변
모듈에 대한 단방향 의존
제가 생각하는 구조는 1번 코드와 2번 코드 모두 아닙니다.이 강의 설명 기준에서는 API 모듈이 자체적으로 디비 접근 의존성을 갖지 않고 DB 모듈을 사용하는게 핵심입니다.그렇기에 인터페이스 없이 API 모듈이 DB 모듈을 의존하고 있는 형태가 전부 입니다.(강의 중간에 인터페이스를 맞춘다는 얘기는 메소드 시그니처를 맞춘다는 의미로 이해하시면 됩니다.)그래서 대략 이러한 구조라고 보시면 될 것 같습니다.// Payments-API 모듈 //// 의존성 implementation(project(":storage:db-core")) //// 코드 class PaymentAppender(val paymentRepository: PaymentRepository){ fun append(user: User, payment: NewPayment): Payment { // ... 중략 } } // db-core 모듈 //// 의존성 implementation(project("...:spring-boot-starter-data-jpa")) /** * 의존성이 변경된다면 * implementation(project("...:hyper-persistence")) **/ //// 코드 class PaymentRepository( val paymentJpaRepository: PaymentJpaRepository /** * 의존성이 변경된다면 * val paymentHyperRepository: PaymentHyperRepository **/ ){ fun newPayment(paymentPersist: PaymentPersist): PaymentPersistResult { val saved = paymentJpaRepository.save(paymentCommand.toEntity()) /** * 의존성이 변경된다면 * val saved = paymentHyperRepository.insert(paymentCommand.toEntity()) **/ return saved.toResult() } } PaymentDB, PaymentDB2 가 별도 모듈이 있는게 아니라, DB-Core 안에서 변경을 대응하는 관점입니다.--소프트웨어는 단계적으로 진화해야 하기 때문에 이 강의에서는 초반 단계 정도의 기본적으로 생각해 볼거리를 중심으로 설명하고 있으므로 완전한 예제가 적절히 나오지 않습니다.초반 단계 프로젝트 구조는 https://github.com/team-dodn/spring-boot-kotlin-template 를 참고하시면 됩니다. 실제 더 진화한 인터페이스(코드 상에서 쓰는 Interface를 의미)와 구현 방향성 관련해서는직접적으로 설명 및 표현하고 있지 않지만, 좀 더 진화된 기준의 구조를 참고하시려면 아래 영상의 후반 부 모듈 구조에 대한 걸 참고하시면 좋을 것 같습니다.https://youtu.be/RVO02Z1dLF8?si=FQdWoLdoBntwTfFS 또 이 아래 영상에서도 참고하실 부분이 있을 것 같습니다https://youtu.be/p5ZMF2bpE6A?si=EE4JB5X2h6HS4F18질문 남겨주셔서 감사합니다 :D
- 0
- 2
- 558