인프런 커뮤니티 질문&답변

asdkfur님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

간단한 주문 조회 V4: JPA에서 DTO로 바로 조회

궁금합니다.

20.04.06 21:11 작성

·

3.7K

26

안녕하세요 진짜 좋은 강의와 선생님의 답변으로 많이 배우고 있습니다. 강의를 따라 하다보니 몇가지 궁금증이 생겼습니다.

1. controller에서 responseEntity 를 안쓰시던데 딱히 이유가 있을까요?

2.계층끼리의 의존성을 낮쳐주기 위해서 dto를 저는 계층끼리 통신할때 쓴다고 알고있었고 entity 가 business layer인 서비스 계층을 벗어나면 좋지않다고 알고있었습니다. 그래서  service에서 controller 로 넘겨줄때 항상 entity를 dto로 만들어서 넘겨주는 방식으로 사용했습니다. 하지만 선생님은  service 계층에서는  controller에 값을 넘겨주지 않거나 id 정도만 넘겨주고 controller 에서 다시조회 하던지 해서 그값으로 resposne dto를 만들어주는 방식으로 하셨습니다. 제가 기존에 하던 방식은 잘못된건가요? 

3.OrderSimpleApiController 같은경우는 orderSerivce를 전혀 사용하지 않았더라구요 대부분의 조회가 바로 OrderRepository에서 가능한 부분이었지만 이렇게 바로 가능하면 서비스 계층을 안통하고 하는방식이 나은건가요? 혹시 언제는 단순 위임이라도 서비스 계층을 통해 repository를 사용하는게 좋고 언제는 바로 조회하는게 좋은지 궁금합니다. 

답변 9

28

김영한님의 프로필 이미지
김영한
지식공유자

2020. 04. 09. 22:35

네 추가 답변을 드리면

1. 그럼 헤더 값이나 status code를 설정해줘야 할때만 쓰시나요?

네 맞습니다. HttpEntity 정보를 변경해야할 필요가 있을 때 사용하시면 됩니다.

2. 엔티티를 service 계층에서만 써야 되는 이유는 엔티티의 지연 로딩이 가능한 범위 이기 떄문이라고 하셨는데 그럼 jpa 를 안쓰는 경우에는 엔티티가 전 계층에서 사용해도 발생되는 문제는 없나요?

엔티티를 전 계층에서 사용해도 문제될 것은 없습니다. 다만 아키텍처를 도메인 계층(엔티티)을 컨트롤러를 포함한 모든 계층에서 접근 가능한 아키텍처로 가져갈 것인지, 아니면 좀 딱딱해도 서비스 계층에서만 도메인 계층에 접근하게 할 것인지 규칙을 정하는 것 뿐입니다. 좀 딱딱한 방식으로 가면 아무래도 DTO를 더 많이 만들고 엔티티를 DTO로 변환하는 과정을 많이 거쳐야겠지요? 다만 프고젝트 규모가 크다면, 충분히 고려해볼만한 방식입니다.

엔티티의 변경이 controller layer까지 영향을 안주기 위해 service 계층에서 엔티티를 반환하지 않도록 하는게 실무에서는 크게 이점이 없다는 말씀으로 이해하면 될까요?

네 이미 대부분의 계층이 엔티티에 의존하는데, 컨트롤러 계층에서 단순히 엔티티를 모른다고 해서 얻는 이점은 적습니다. 다만 강의에서 설명드렸듯이, 엔티티를 API로 외부에 공개하는 것은 좋지 않습니다.

3.아직 초보자이고 많은 사람과 같이 공동으로 하나의 프로젝트를 해본경험이 없어 코드공유가 잘된다는 기준이 정확히 감이안오지만.. 어떤 경우에는 service 를 이용하고 어떤 경우에는 repository를 이용하고 이런게 더 헷갈리지 않을까요? 그리고 규모 가 커진다는 기준을 혹시 패키지가 서로 분리 될정도로 커진다 정도 이고 그때는 한 서비스를 통해 특정 엔티티에 접근하도록 강제하는 방법이 시스템 복잡도를 줄이기위해서 나은 선택 이라고 이해하면 될까요?

사실 반대로 생각해보면 왜 꼭 서비스를 통해서 리포지토리에 접근해야하지? 라는 근본적인 의문을 품는 것이 필요합니다. 이렇게 추가 코드를 만들고 비용을 들여서 얻을 수 있는 이점이 과연 무엇인가? 라는 점에 의문을 품는 것이지요. 정말 서비스 로직이 거의 없고, 단순 조회로 가득한 프로젝트인데, 서비스 계층을 꼭 만들어야 하는가? 라고 생각해보면 이 문맥에서는 크게 얻는 이점이 없을 거에요. 반대로 프로젝트가 정말 복잡하고, 모듈이 매우 많은 상황이고, 서비스 계층에서 중간에 중요한 로그를 남긴다거나, 중요한 이벤트를 외부에 발행한다거나 하면, 꼭 서비스 계층을 타야겠지요. 이런 부분들을 균형있게 잘 판단하는 것이 좋은 개발자의 역량이라 생각합니다.

애플리케이션 아키텍처는 큰 건물을 짓는 것과 다르고, 마치 도시계획을 하는 것과 비슷합니다. 구획을 잘 나누고, 점진적으로 발전시키고, 규모가 커짐에 따라서 또 일부 지역은 재개발하고, 구획을 더 크게 잘 나누고... 규모에 따라서 다른 정책과 결정이 필요한 것이지요. 인구가 10명만 사는 도시라면 그에 맞는 정책이 필요하고, 인구가 100만이 사는 도시라면 또 거기에 맞는 다른 정책이 필요합니다. 애플리케이션 아키텍처도 이와 같습니다. 처음부터 100만이 사는 도시를 생각하고, 계획했는데, 인구가 10명만 사는 도시라면 낭비가 정말 심하고 개발자들도 힘들겠지요^^

18

김영한님의 프로필 이미지
김영한
지식공유자

2020. 04. 07. 22:01

안녕하세요. asdkfur님

오랜만에 질문을 주셔서 반갑네요^^

1. controller에서 responseEntity 를 안쓰시던데 딱히 이유가 있을까요?

-> 네 저는 필요할 때만 사용합니다. responseEntity가 필수는 아니니까요.

2.계층끼리의 의존성을 낮쳐주기 위해서 dto를 저는 계층끼리 통신할때 쓴다고 알고있었고 entity 가 business layer인 서비스 계층을 벗어나면 좋지않다고 알고있었습니다. 그래서  service에서 controller 로 넘겨줄때 항상 entity를 dto로 만들어서 넘겨주는 방식으로 사용했습니다. 하지만 선생님은  service 계층에서는  controller에 값을 넘겨주지 않거나 id 정도만 넘겨주고 controller 에서 다시조회 하던지 해서 그값으로 resposne dto를 만들어주는 방식으로 하셨습니다. 제가 기존에 하던 방식은 잘못된건가요? 

-> 이 질문은 사실 엔티티를 어느 계층까지 허용할 것인가에 대한 질문으로 정리할 수 있습니다.

엔티티를 서비스 계층안에서만 사용해야 한다 vs 엔티티를 모든 계층에서 사용할 수 있게 한다. 이렇게 정리할 수 있지요.

이 부분은 사실 둘다 장단점이 있습니다. 먼저 엔티티를 서비스 계층 안에서만 사용해야 한다는 주장은 엔티티의 지연 로딩이 가능한 범위 때문입니다. 엔티티를 지연 로딩하려면 영속성 컨텍스트가 필요한데, 이 영속성 컨텍스트는 일반적으로 트랜잭션 범위에 맞추어 사용합니다. 트랜잭션을 시작할 때 영속성 컨텍스트를 생성하고, 트랜잭션이 끝날 때 영속성 컨텍스트도 종료되는 것이지요. 이렇게 사용하는게 일반적인 방법이다. 문제는 이렇게 했을 때 서비스 계층을 넘어선 컨트롤러 계층에서는 트랜잭션이 끝나버리므로 영속성 컨텍스트 종료되고, 더이상 지연로딩을 할 수 없는 문제가 있습니다. 그래서 엔티티를 서비스 계층 안에서만 사용하는게 안전합니다.

하지만 소위 OSIV(Open Session In View) 또는 OEIV(Open EntityManager In View)라 불리는 기능을 사용하면 영속성 컨텍스트의 생존 범위를 UI 계층까지 가져갈 수 있습니다. 이 방법은 단점도 존재하지만, 엔티티의 지연 로딩을 컨트롤러나 View까지 가지고 갈 수 있는 장점이 있습니다. 활용2편의 섹션5에서 OSIV와 성능 최적화에서 장단점에 대한 내용을 들으실 수 있습니다^^

추가로 의존성에 대한 부분을 말씀드리면, 도메인 모델을 사용하면 엔티티가 도메인 모델이 되고, 모든 계층에서 도메인 모델을 의존합니다. 도메인 모델이 가장 중요한 핵심이 되는 것이지요. 그래서 컨트롤러 계층만 도메인 모델을 모른다고 해서 큰 이득을 얻지는 못합니다. (이건 저희 개인적인 생각입니다.)

저는 기본적인 방향은 모두 도메인 모델을 사용할 수 있게 실용적인 방향으로 설계하고, 프로젝트가 커지고 성능이 점점 중요해지면, 그때 OSIV를 사용하지 못하게 합니다. 이렇게 되면 UI 계층에서는 지연 로딩이 어렵기 때문에, 엔티티 사용 비중이 줄어듭니다. 그래도 간단간단한 엔티티는 직접 조회해서 처리합니다.

3.OrderSimpleApiController 같은경우는 orderSerivce를 전혀 사용하지 않았더라구요 대부분의 조회가 바로 OrderRepository에서 가능한 부분이었지만 이렇게 바로 가능하면 서비스 계층을 안통하고 하는방식이 나은건가요? 혹시 언제는 단순 위임이라도 서비스 계층을 통해 repository를 사용하는게 좋고 언제는 바로 조회하는게 좋은지 궁금합니다. 

-> 이건 프로젝트 진행 상황에 따라서 다르다 생각합니다. 팀 규모가 작고, 코드 공유가 원할하게 잘 되면, 실용적인 관점에서 필요하지 않은 서비스 계층을 사용하지 않아도 된다 생각합니다. 그런데 팀 규모가 크고, 코드 공유가 원할하게 안되면, 강제 하는 것도 필요합니다. 이 부분은 결국 유연한 아키텍처를 사용하는가, 계층을 항상 통과해야 하는 딱딱한 아키텍처를 사용해야 하는가입니다. 상황이 좋다면, 제가 선호하는 방법은 유연한 아키텍처를 사용하고, 서로 코드 공유가 잘 되는 상황이니, 중간에 이 모듈은 항상 서비스 계층에서 공통 로직이 들어가야 한다면, 그 부분만 서비스 계층을 통해서 처리하도록 방향을 잡는게 좋다 생각합니다. 결국 실용적으로 하되, 프로젝트 규모가 커짐에 따라서 아키텍처를 유연하게 변경해 가는 것이 중요합니다.

12

김영한님의 프로필 이미지
김영한
지식공유자

2020. 04. 11. 01:51

저도 과거에는 항상 정답이 있을 것이라고 생각했는데, 시간이 지날수록 그리고 더 많이 경험할 수 록 딱 정답이 있다기 보다는 결국 객체지향의 기본 원칙과 응집도 결합도 같은 기본적인 개념들이 더 중요하다는 것을 느끼고, 이것을 메서드이든, 클래스이든, 모듈이든, 마이크로서비스이든 기본 원칙을 가지고 고민하는게 중요하다고 생각하게 되었습니다.

asdkfur님께는 클린코더(http://www.yes24.com/Product/Goods/29241448)  라는 책을 추천해드리고 싶어요^^

감사합니다. ㅎㅎ

8

asdkfur님의 프로필 이미지
asdkfur
질문자

2020. 04. 10. 00:09

처음 스프링을 사용 했을 때느 왜 이렇게나 많은 계층이 필요하나 생각했으나 시간이 지남에 따라 많은 예제가 그러하니 관습처럼 controller 에서 service 그리고 다시 repository 이렇게만 생각없이 쓰다가 선생님 말씀을 듣고 다시 근본적인 것 부터 되돌아보게 되는 계기가 되었습니다. 제가 아직 많이 부족해서 항상 이런 류?의  질문들은 선생님의 답변을 몇번이나 읽어보면서 이해하고 상황을 그려보려 하고 있습니다.  항상 이런 정성스러운 답변 그리고 어디에서 쉽게 들을수 없는 조언들 보면 정말 정말 감사하고 한편으로는 너무 귀찮게 하는거 아닌가 라는 죄송스러운 마음도 듭니다 ㅎㅎ .  정말 강의 수강하길 잘했다고 생각합니다. ㅎㅎ

1

maurizio님의 프로필 이미지

2023. 06. 30. 12:29

질문 글 쓰기전에 검색 한번 해보다가 100프로 이해는 못했지만 많은걸 배웠습니다 질문자님과 답변자님 감사합니다.

1

강성욱님의 프로필 이미지

2022. 01. 21. 22:56

눈팅하는 것만으로도 많은 걸 배울 수 있었습니다. 감사합니다 ㅎㅎ

1

asdkfur님의 프로필 이미지
asdkfur
질문자

2020. 04. 11. 22:04

 책까지 추천해주시다니 정말 감사합니다. ㅎㅎㅎ 

1

asdkfur님의 프로필 이미지
asdkfur
질문자

2020. 04. 09. 10:04

답변 정말 감사합니다. 추가적으로 질문을 드리자면..

1. 그럼 헤더 값이나 status code를 설정해줘야 할때만 쓰시나요?

2. 엔티티를 service 계층에서만 써야 되는 이유는 엔티티의 지연 로딩이 가능한 범위 이기 떄문이라고 하셨는데 그럼 jpa 를 안쓰는 경우에는 엔티티가 전 계층에서 사용해도 발생되는 문제는 없나요?

엔티티의 변경이 controller layer까지 영향을 안주기 위해 service 계층에서 엔티티를 반환하지 않도록 하는게 실무에서는 크게 이점이 없다는 말씀으로 이해하면 될까요?

3.아직 초보자이고 많은 사람과 같이 공동으로 하나의 프로젝트를 해본경험이 없어 코드공유가 잘된다는 기준이 정확히 감이안오지만.. 어떤 경우에는 service 를 이용하고 어떤 경우에는 repository를 이용하고 이런게 더 헷갈리지 않을까요? 그리고 규모 가 커진다는 기준을 혹시 패키지가 서로 분리 될정도로 커진다 정도 이고 그때는 한 서비스를 통해 특정 엔티티에 접근하도록 강제하는 방법이 시스템 복잡도를 줄이기위해서 나은 선택 이라고 이해하면 될까요?

0

Son원철님의 프로필 이미지

2024. 08. 21. 16:34

갓영한 개추...

asdkfur님의 프로필 이미지

작성한 질문수

질문하기