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

고운 코끼리님의 프로필 이미지
고운 코끼리

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

엔티티 설계시 주의점

JPA와 Java 주의사항에 대한 여러 가지 질문

작성

·

304

3

이번 강의에서는 평범한 도큐먼트만으로는 알 수 없는 정보를 알게 된 것 같아, 감사의 말씀드립니다.!

이 강의에서 몇 가지 JPA와 Java 사용에 대한 질문이 있습니다. 

 

1. 전부 지연로딩으로 바꾸는 것이 좋다고 거듭 강조 주셨는데, 그렇다면 JPA는 왜 default로 EAGER를 사용하는 것인가요? EAGER를 default로 사용한다는 것은, 이렇게 사용하는 경우도 있고 장점도 있다는 것을 의미하는 것 같아 여쭤봅니다.! LAZY를 쓰지 않았을 때의 장점은 어떤 것들이 있나요?

 

2. Setter를 사용하지 않는 멤버변수에 한해 final을 사용하지 않는 이유는 무엇인가요? 아래 컬렉션 질문과 별개로 setter가 없는 모든 변수에 대해 궁금합니다.

 

3. 지금까지 필드 초기화는 생성자에서의 초기화와 다른 점이 우선순위만 다르다고 알고 있었습니다. 필드 초기화 -> 생성자 순으로 호출된다고 알고 있고, 단지 스타일 차이라고만 알고 있었습니다. 혹시 필드 초기화가 생성자 초기화보다 안전한 이유가 있을까요? 단순히 여러 생성자가 있을 때에 코드가 빠지는 실수를 막아준다는 이유 밖에 떠오르지 않는데, 다른 이유가 있는지 궁금합니다.

 

4. 양방향 연관관계 메서드에서 한 쪽만 연관관계 메서드를 적용시키면, 이를 모르고 호출하는 입장에서는 연관관계 메서드가 적용되지 않은 쪽을 호출하여 문제가 될 수도 있을 것 같다는 생각이 듭니다. Delivery <-> Order 관계를 예를 들면, 지금은 Order쪽에만 넣어서 Order에서 setDelivery할 때 자동으로 Delivery쪽도 해주었는데, “연관관계 메서드 해놨겠지”하며 Delivery에서 setOrder를 호출하면 문제가 될 것 같습니다. 물론 의미상 Order에서 Delivery와 OrderItem을 관리하는 것이 맞지만, 이렇게 직관적인 관계만 있지는 않을 것 같아서 그럴 때엔 어떻게 하는지 궁금합니다.

 

5. Address 부분 설명하실 때, 가볍게 "기본 생성자는 안 썼으면 좋겠지만 private으로 하면 안 되니 protected로 한다."라고 말씀주셨는데, 이러한 부분은 실제로 document를 읽지 않는 이상 알 수 없을 것 같아요. 강의를 듣는 사람 입장에서는 그렇구나 하고 넘길 수 있지만, 처음에 protected를 써야한다는 것은 그냥 단순히 private을 썼을 때 컴파일 오류를 통해 알게 되신건가요? (JPA에서 protected를 써야하는지 어떻게 알았냐가 메인 질문이라기보단, 이렇게 minor하지만 직관을 깨는 것들을 어떻게 보통 알게 되시는지가 궁금합니다.) 이 부분은 개인적으로 백엔드 팀장님으로의 김영한 선생님께 드리는 질문인데, 백엔드 쪽 공부를 하면서 느끼는 부분 중 하나가, 이렇게 tool을 사용하다보면 제 로직을 논리적으로 단단하게 짜는 시간도 있겠지만 그에 못지 않게 tool을 사용하기 위해 알아보는 시간도 적지 않게 쓰일 것 같은 느낌이 듭니다. 이러한 부분은 백엔드 개발이면 당연하게 받아들이는 부분인지 궁금합니다.

 

정말 길지만, 업무에 차질이 가지 않는 시간에 답변주시면 정말 감사하겠습니다. :)

답변 5

4

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

안녕하세요. t님

1. 전부 지연로딩으로 바꾸는 것이 좋다고 거듭 강조 주셨는데, 그렇다면 JPA는 왜 default로 EAGER를 사용하는 것인가요? EAGER를 default로 사용한다는 것은, 이렇게 사용하는 경우도 있고 장점도 있다는 것을 의미하는 것 같아 여쭤봅니다.! LAZY를 쓰지 않았을 때의 장점은 어떤 것들이 있나요?

-> 네 정말 놀랍게도 장점이 거의 없습니다. 스펙을 처음 정의한게 너무 오래되어서 그때 당시와 지금 상황이 많이 달라졌을 수도 있구요. 아마도 처음에는 일대다 관계는 데이터 조회가 많이 되니 기본을 LAZY로 하고, 다대일 관계는 데이터가 하나 조회되니 EAGER로 했을 것 같아요. 그런데 점점 실무에서 하드하게 사용되면서, LAZY로 하는 것을 관례로 사용하게 되었습니다. (그렇다고 지금 시점에 스펙을 변경하면 과거 시스템들이 다 영향을 받게 되니, 변경하기가 참 어렵겠지요. 그래서 스펙을 한번 잘 정하기가 참 어려운 것 같아요)

 

2. Setter를 사용하지 않는 멤버변수에 한해 final을 사용하지 않는 이유는 무엇인가요? 아래 컬렉션 질문과 별개로 setter가 없는 모든 변수에 대해 궁금합니다.

-> 엔티티는 프록시 기술들이 들어가기 때문에 final을 사용하면 안됩니다. 프록시 기술에서 정상 동작하지 않을 수 있습니다.

 

3. 지금까지 필드 초기화는 생성자에서의 초기화와 다른 점이 우선순위만 다르다고 알고 있었습니다. 필드 초기화 -> 생성자 순으로 호출된다고 알고 있고, 단지 스타일 차이라고만 알고 있었습니다. 혹시 필드 초기화가 생성자 초기화보다 안전한 이유가 있을까요? 단순히 여러 생성자가 있을 때에 코드가 빠지는 실수를 막아준다는 이유 밖에 떠오르지 않는데, 다른 이유가 있는지 궁금합니다.

-> 네 이 부분은 특별한 이유는 없습니다. 컬력센의 경우 필드에서 초기화 하는 것이 더 편리해서 그렇게 사용합니다.

4. 양방향 연관관계 메서드에서 한 쪽만 연관관계 메서드를 적용시키면, 이를 모르고 호출하는 입장에서는 연관관계 메서드가 적용되지 않은 쪽을 호출하여 문제가 될 수도 있을 것 같다는 생각이 듭니다. Delivery <-> Order 관계를 예를 들면, 지금은 Order쪽에만 넣어서 Order에서 setDelivery할 때 자동으로 Delivery쪽도 해주었는데, “연관관계 메서드 해놨겠지”하며 Delivery에서 setOrder를 호출하면 문제가 될 것 같습니다. 물론 의미상 Order에서 Delivery와 OrderItem을 관리하는 것이 맞지만, 이렇게 직관적인 관계만 있지는 않을 것 같아서 그럴 때엔 어떻게 하는지 궁금합니다.

-> 그래서 연관관계 메서드를 잘 정의하는게 중요합니다. 이런 부분은 핵심 엔티티 설계에 대한 부분이기 때문에 모든 개발자들이 잘 알 수 있게 공유되어야 합니다.

 

5. Address 부분 설명하실 때, 가볍게 "기본 생성자는 안 썼으면 좋겠지만 private으로 하면 안 되니 protected로 한다."라고 말씀주셨는데, 이러한 부분은 실제로 document를 읽지 않는 이상 알 수 없을 것 같아요. 강의를 듣는 사람 입장에서는 그렇구나 하고 넘길 수 있지만, 처음에 protected를 써야한다는 것은 그냥 단순히 private을 썼을 때 컴파일 오류를 통해 알게 되신건가요? (JPA에서 protected를 써야하는지 어떻게 알았냐가 메인 질문이라기보단, 이렇게 minor하지만 직관을 깨는 것들을 어떻게 보통 알게 되시는지가 궁금합니다.) 이 부분은 개인적으로 백엔드 팀장님으로의 김영한 선생님께 드리는 질문인데, 백엔드 쪽 공부를 하면서 느끼는 부분 중 하나가, 이렇게 tool을 사용하다보면 제 로직을 논리적으로 단단하게 짜는 시간도 있겠지만 그에 못지 않게 tool을 사용하기 위해 알아보는 시간도 적지 않게 쓰일 것 같은 느낌이 듭니다. 이러한 부분은 백엔드 개발이면 당연하게 받아들이는 부분인지 궁금합니다.

-> JPA 스펙에서 private을 허용하지 않고, protected까지만 허용하기 때문입니다. 이 부분은 사실 설계에 대한 부분인데요. 자바 언어와 객체지향, 좋은 설계에 대해서 공부하면 자연스럽게 많은 것을 공유하는 것 보다는 최대한 적을 것을 공유하는 게 좋고, 컴파일 언어를 잘 활용해서 막을 수 있는 것은 미리 막아두는게 좋다는 생각을 하게 됩니다. tool의 사용이라기 보다는 사실 자바 언어와 설계 자체에 대한 고민이라고 생각해주시면 될 것 같아요. 마음 같아서는 private이지만, JPA 스펙에서 허용하지 않기 때문에 차선책인 protected를 선택하는 것이지요.

도움이 되셨길 바래요^^

1

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

ㅎㅎ 진짜 문제 해결을 위한 tool이네요^^

좋은 하루 되세요.

0

위 답변 모두 감사드립니다. 

 

5번에 있어 이미 답변이 되었지만, 제가 상세히 적지 않고 질문드린 것 같아 아래에 추가 설명만 드리겠습니다.!

제가 생각하기에 tool이라고 하면, framework나 library 같이 현업에서 서비스를 위해 도와주는 도구가 생각이 먼저 나서 질문드렸습니다. 제가 너무 모호하게 여쭤봤네요, 죄송합니다! 

지금 사용하고 있는 Spring, JPA 등 (작게는 lombok 까지도) 이 모두 결국 원하는 일을 서비스하도록 개발하기 위해 도와주는 도구라고 생각합니다. (다른 관점으로 봐야할 필요가 있다면 말씀해주세요!) 이 tool들을 배워 사용함에 있어 tool이 나오게 된 배경을 이해하고, 왜 사용해야 하는 지, 어떻게 사용해야 하는 지 등은 꼭 배워야한다고 생각합니다.

하지만, 위에서 JPA는 private을 사용하면 안 된다는 부분과 같이 정말 작지만 모르면 동작을 안 하는 부분은 그 tool의 큰 컨셉 (Spring의 경우 DI, IoC와 같이..) 과는 별개로 알기 어렵다고 생각하여 질문드린 내용이었습니다.

이 부분은 공부하면서 경험으로 많이 깨닫게 되는 부분이군요. 충분한 답변이 되었고, 이해도 되었습니다. 이에 대해서는 추가적으로 답변 안 주셔도 괜찮습니다!

 

위 질문 모두 친절하게 답변 주셔서 정말 감사드립니다. 특히, 경험으로만 알 수 있는 부분들을 여쭤볼 수 있어 좋았던 것 같습니다. 감사합니다.

0

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

1. 과거의 영향이군요. 경험이 많으신 분께만 들을 수 있는 답변 주셔서 정말 감사드립니다.

-> 네^^

 

2. 혹시 Address 객체의 멤버변수에 final을 붙이면 문제가 생길까요? 이것도 Entity로 봐야하는지 궁금합니다.

-> Address 객체가 값 객체인데요. JPA에서 사용하기 때문에 final을 붙이면 안됩니다.

 

4. 그럼 실무에서는 연관관계 메서드를 양쪽에 전부 정의하는 경우는 없는지 궁금합니다. 단순하게 생각했을 때, 서로 overwrite을 하니 문제 없을거란 생각이 들어서요.

-> 양쪽에 전부 정의할 수도 있습니다. 그런데 실제 해보면, 잘못하면 무한루프에 빠질 수 있기 때문에 주의해서 잘 설정해주셔야 합니다. 그런데 양쪽에 이렇게 두는 게 막상 해보면, 더 혼란을 가중하더라구요. 비즈니스 관계는 하나만 있는게 경험상 더 좋았습니다.

 

5. 말씀 감사드립니다. 다만, 제가 여쭤본 내용과 살짝 다른 것 같습니다. :) 배우면서 최소한의 공유의 중요성을 체감하고 있고, 좋은 설계를 위해 노력하고 있지만, 위 상황에서 저라면 private으로 쓰고 문제가 왜 생겼는지 알아보기 위해 헤맸을 것 같다는 생각이 듭니다. JPA에서 private을 허용하지 않고 protected까지만 쓸 수 있다는 것은, 자연스럽게 컴파일 오류를 고치다보니 알게 된 것인지, tool을 배워 시간 투자를 한 부분인지 궁금합니다.! (이 부분에서 tool을 위한 시간이 많이 쓰이는지 궁금하여 여쭤본 질문이었습니다.) 

-> tool이라는 것이 어떤 것을 말씀하시는지 정확히 모르겠어요. IDE를 말씀하시는지, 라이브러리를 말씀하시는지 등이요. 저의 경우는 JPA 공부를 하면서 자연스럽게 private을 사용하면 안된다는 것을 알게 되었고, 그래서 차선으로 protected를 선택했습니다. tool을 위한 시간이라는 것이 어떤 것인지 자세히 설명해주시겠어요?

0

안녕하세요.

친절한 답변 정말 감사드립니다. 몇 가지 추가 질문이나 말씀드릴 부분이 있어 아래 내용 남겨드립니다.

 

1. 과거의 영향이군요. 경험이 많으신 분께만 들을 수 있는 답변 주셔서 정말 감사드립니다.

 

2. 혹시 Address 객체의 멤버변수에 final을 붙이면 문제가 생길까요? 이것도 Entity로 봐야하는지 궁금합니다.

 

4. 그럼 실무에서는 연관관계 메서드를 양쪽에 전부 정의하는 경우는 없는지 궁금합니다. 단순하게 생각했을 때, 서로 overwrite을 하니 문제 없을거란 생각이 들어서요.

 

5. 말씀 감사드립니다. 다만, 제가 여쭤본 내용과 살짝 다른 것 같습니다. :) 배우면서 최소한의 공유의 중요성을 체감하고 있고, 좋은 설계를 위해 노력하고 있지만, 위 상황에서 저라면 private으로 쓰고 문제가 왜 생겼는지 알아보기 위해 헤맸을 것 같다는 생각이 듭니다. JPA에서 private을 허용하지 않고 protected까지만 쓸 수 있다는 것은, 자연스럽게 컴파일 오류를 고치다보니 알게 된 것인지, tool을 배워 시간 투자를 한 부분인지 궁금합니다.! (이 부분에서 tool을 위한 시간이 많이 쓰이는지 궁금하여 여쭤본 질문이었습니다.) 

고운 코끼리님의 프로필 이미지
고운 코끼리

작성한 질문수

질문하기