묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
@NaturalIdCache에 대한 보충 설명 및 사용법 공유
'25. 엔티티의 자연키 지정' 영상의 후반부에 적용한 @NaturalIdCache에 대해 추가로 학습한 내용이, 저처럼 해당 애노테이션을 처음 접한 분들에게 도움이 될 것 같아서 글을 작성합니다. 강의에서 오해가 있을 수 있는 부분, 그리고 자연키에 캐시를 적용하는 방법을 정리해 보았습니다. 강의 내용과 실제 동작의 차이점강의에서는 “같은 트랜잭션 안에서 같은 아이디 값을 가지고 여러 번 조회 시 Persistence Context 에 캐시된 값을 꺼내오는 것 처럼. @NaturalIdCache를 적용하면 이것도 영속 컨텍스트에 캐싱이 된다.”고 말씀하셨습니다. 해당 내용에 대한 이해를 돕기 위해 Hibernate의 두 가지 캐시에 대해 간단히 짚고 넘어가겠습니다.1차 캐시 (First-Level Cache): 세션(영속성 컨텍스트) 범위의 캐시입니다. 같은 트랜잭션 안에서만 유효하며, 트랜잭션이 끝나면 사라집니다. Spring Data JPA에서는 기본적으로 @Id 에 대한 조회를 1차 캐시합니다. 2차 캐시 (Second-Level Cache): 세션 팩토리 범위의 캐시로, 여러 세션에서 데이터를 공유할 수 있습니다. 적용하려면 별도의 의존성 추가 및 캐시 관련 설정(@Cache 등)이 필요합니다. 따라서, "같은 트랜잭션 안에서 캐시된 값을 꺼내온다."는 말은 세션 범위의 1차 캐시로 해석됩니다. 하지만 제가 직접 테스트해 본 결과, @NaturalIdCache는 1차 캐시가 아닌 2차 캐시와 관련이 있었으며, 1차 캐시를 적용하기 위해서는 다른 방법이 필요했습니다. 테스트를 통한 확인자연키에 대한 1차 캐시 동작을 확인하기 위해, 강의에서 적용한 Member 엔티티의 @NaturalIdCache 를 제거하고, 자연키(Email)에 @NaturalId만 적용한 상황에서 두 가지 방식으로 테스트를 진행했습니다. 테스트1: findByEmail 메서드를 사용한 조회Java@Test void NaturalIdFirstLevelCache() { Member member = Member.register(createMemberRegisterRequest(), createPasswordEncoder()); memberRepository.save(member); entityManager.flush(); entityManager.clear(); System.out.println("회원 저장 및 persistence context 초기화 완료"); // 같은 email(Natural ID)로 두 번 조회 Member findMember1 = memberRepository.findByEmail(member.getEmail()).get(); Member findMember2 = memberRepository.findByEmail(member.getEmail()).get(); assertThat(findMember1).isSameAs(findMember2); } Spring Data의 쿼리 메서드를 사용하여 이메일로 조회하는 findByEmail 메서드를 만들고, 한 트랜잭션에서 같은 회원을 두 번 조회했습니다. 자연키에 대한 1차 캐시가 동작한다면, SELECT 쿼리는 한 번만 실행되어야 합니다.결과는 SELECT 쿼리가 두 번 실행되었습니다. 즉, 자연키에 대한 1차 캐시가 동작하지 않았습니다. 테스트2: Hibernate의 자연키 관련 API를 사용한 조회@NaturalId를 다루는 글들을 찾아본 결과 Hibernate가 제공하는 자연키 관련 API가 있다는 것을 확인했고, 이를 적용하기 위해 커스텀 리포지토리를 구현했습니다.Java@Repository @RequiredArgsConstructor public class CustomizedMemberRepositoryImpl implements CustomizedMemberRepository { private final EntityManager entityManager; @Override public Optional<Member> findByNaturalId(Email naturalId) { return entityManager.unwrap(Session.class) .bySimpleNaturalId(Member.class) .loadOptional(naturalId); } } 그리고, 테스트 1과 같은 방식으로 테스트를 진행하였습니다. @Test void NaturalIdApi() { Member member = Member.register(createMemberRegisterRequest(), createPasswordEncoder()); memberRepository.save(member); entityManager.flush(); entityManager.clear(); System.out.println("회원 저장 및 persistence context 초기화 완료"); Member findMember1 = memberRepository.findByNaturalId(member.getEmail()).get(); Member findMember2 = memberRepository.findByNaturalId(member.getEmail()).get(); assertThat(findMember1).isSameAs(findMember2); }결과는 SELECT 쿼리가 한 번만 실행되었습니다. 이를 통해 자연키에 대한 1차 캐시는 @NaturalIdCache 애노테이션과 무관하게, 전용 API를 사용해야만 동작하는 것을 확인했습니다. @NaturalIdCache의 용도@NaturalIdCache Javadoc에는 다음과 같은 설명이 있습니다.Specifies that mappings from the natural id values of the annotated entity to the corresponding entity id values should be cached in the shared second-level cache.…중략This annotation is usually used in combination with Cache, since a round trip may only be avoided if the entity itself is also available in the cache.대략 “natural id와 상응하는 id에 대한 매핑을 2차 캐시에 저장하는 애노테이션이고, 엔티티가 캐시되어있어야 하기 때문에 일반적으로 Cache와 함께 사용된다.”라고 해석됩니다. 즉, 1차 캐시가 아닌 2차 캐시를 위한 애노테이션입니다. 정리2차 캐시 관련 설정 및 테스트를 마저 진행한 후 최종 정리한 내용은 다음과 같습니다. 자연키의 1차 캐시@NaturalIdCache 애노테이션과 관련 없습니다. 자연키에 @NaturalId만 붙이면 됩니다.반드시 Hibernate Session의 bySimpleNaturalId() 같은 전용 API를 사용해야 적용됩니다. 자연키의 2차 캐시@Cache와 @NaturalIdCache를 함께 사용해야 동작합니다.@Cache만 사용 시 @Id로 조회할 때만 2차 캐시가 동작합니다.@NaturalIdCache만 사용 시 자연키와 ID에 대한 매핑 정보는 캐시 히트되는 걸 확인했지만, ID와 엔티티에 대한 캐시가 없어서 캐시가 적용되지 않았습니다. @Cache와 @NaturalIdCache 모두 사용 시 ID를 통한 조회와 자연키를 통한 조회 모두 2차 캐시가 적용됩니다. 참고 자료Hibernate6.6 공식 문서NaturalCache javadocsbaeldung: Hibernate Natural IDs in Spring BootSpring Custom Repository 글의 오류나 부족한 내용을 알고 계신 분은 코멘트를 달아주시면 감사하겠습니다.
-
미해결악성코드 분석 중급과정 (유형별분석)
2025년 로컬 컴퓨터(윈도우11)에서 가상환경으로 드래그앤드롭 안됨
선생님이 강의하신 환경 구성을 그대로 했습니다.클립보드 공유, 드래그 앤드롭 다 양방향으로 설정했습니다. 근데 실습파일을 가상환경에 옮길려고 했는데 드래그앤드롭이 되지 않아서 질문드립니다!이런 경우 어떻게 해야될까요?버츄얼박스 버전은 7.0입니다..!!
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
인라인 스타일 리렌더링 관련
인라인 스타일 사용 시 style이라는 객체 prop이 매번 달라져 리렌더링이 발생한다고 해주신 부분 관련하여 질문드립니다 부모가 리렌더링되는 상황이라 이와 무관하게 자식의 리렌더링도 유발하게 될텐데요자식 컴포넌트 자체에 memo를 적용하는 경우가 아니라면, useMemo를 쓰더라도 최적화 효과가 없을 것으로 보이는데 맞을까요?
-
해결됨[Rookiss University] UE5 Lyra 클론 코딩 (Haker)
UPROPERTY매크로 AllowedType이 동작하지 않습니다.
사진에 보이는 에디터 화면은 UserFacingExperience상속받아 만든 DataAsset인데 MapId나 Experienceid를 눌렀을때 AllowedType대로 동작하지 않고 에셋매니저에 등록된 모든 에셋을 불러옵니다.혹시 제가 사진에 올린거 말고도 다른것들을 해줘야했나요?
-
미해결
코딩 소모임에서 같이 공부하실 분 구합니다!
🔥 같이 성장할 사람 찾습니다 - [코딩존]에서 신규부원 모집합니다!! 🔥 혼자 공부하다 멘붕 온 사람 토이 프로젝트 같이 만들 사람 찾는 사람 CS 기본기나 알고리즘, 면접 준비까지 하고 싶은 사람 그런 당신을 위한 진짜 실속형 스터디,<코딩존>에서 같이 공부해요!! 💻 스터디 소개💡 목적: 실력 있는 개발자 되기 위한 꾸준한 성장💡 방식: 오프라인 OT, 온라인 + 선택적 오프라인 / 협업 툴 활용💡 대상: 개발을 진지하게 공부하고 싶은 누구나 (초보도 환영!)💡 스터디 커리큘럼:CS 기본기 (운영체제, 네트워크, 자료구조 등)알고리즘 문제풀이 (백준/프로그래머스 중심)토이 프로젝트 기획 및 협업코드리뷰 & 발표 스킬 향상개인 목표 점검 및 피드백※ 주제별 소그룹 운영 예정 💻 모집대상서울 거주하는 분들 중 자격증이나 취준 준비 중인데 같이 공부할 팀이 필요한 분 “혼자 공부는 잘 안 돼요…” 싶은 동기부여가 필요한 분 사이드 프로젝트 하고 싶은데 디자이너/프론트/백 구하는 중인 분 단순 스터디가 아닌, 함께 성장하는 커뮤니티를 원하는 분 📌 신청 방법📅 마감: 선착순 6명 (진짜로 소수 정예로 갑니다)📍 지원링크: [https://docs.google.com/forms/d/1aoKEz2ppgUvGmC5jf_jgeid0BjBk6CwVMROEp503Zv0/edit]📩 문의사항은 댓글에 남겨주세요!
-
해결됨넓고 얕게 외워서 컴공 전공자 되기
format 시 0-0트랙 섹터에 관해
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 빠른 포멧 후에 0-0트랙 섹터에 존재 했던 운영체제에 관한 메모리들도 사라지게 될텐데 그 후 부팅은 어떻게 가능한지 궁금합니다
-
해결됨2025 언리얼 공인강사 – UE5 스파르타 클래스: 실전편
수강 전 질문
안녕하세요.강의 초반 버전 관련 영상을 보고 질문 드립니다. 강의마다 언리얼 버전이 바뀌는데, 영상에서 언리얼 버전을 올리면 다시 내릴 수 없다고 말씀 주셨습니다.그럼 강의를 따라가며 버전을 올렸을 경우, 다음 파트가 낮은 버전이 필요 할 때는 어떻게 진행하면 될까요?언리얼버전을 5.0버전 부터 5.6버전까지 다 깔아둬야하나요?유료강의와 다르게 무료강의(실전편)에는 파트마다 버전 표시가 안되어있는데, 이는 전체 버전이 다 호환되는건가요?
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
검증 실패 후 값이 빈칸인 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 아니오3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]@PostMapping("/add") public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { //검증 오류 결과를 보관 log.info("item.price1 = {}", item.getPrice()); //검증 로직 if (!StringUtils.hasText(item.getItemName())) { bindingResult.addError(new FieldError("item","itemName","상품 이름은 필수입니다.")); } if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) { bindingResult.addError(new FieldError("item","price","가격은 1,000 ~ 1,000,000 까지 허용합니다.")); } if (item.getQuantity() == null || item.getQuantity() >= 9999) { bindingResult.addError(new FieldError("item", "quantity", "수량은 최대 9,999 까지 허용합니다.")); } //특정 필드가 아닌 복합 룰 검증 if (item.getPrice() != null && item.getQuantity() != null) { int resultPrice = item.getPrice() * item.getQuantity(); if (resultPrice < 10000) { bindingResult.addError(new ObjectError("item","가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = "+resultPrice)); } } //검증에 실패하면 다시 입력 폼으로 if (bindingResult.hasErrors()) { log.info("errors = {} ", bindingResult); log.info("item.price2 = {}", item.getPrice()); return "validation/v2/addForm"; } //성공 로직 Item savedItem = itemRepository.save(item); redirectAttributes.addAttribute("itemId", savedItem.getId()); redirectAttributes.addAttribute("status", true); return "redirect:/validation/v2/items/{itemId}"; }addItemV1에서 폼의 가격에 1원을 입력 후 저장했을 때 log.info("item.price1 = {}",item.getPrice()) 와 log.info("item.price2 = {}",item.getPrice())로 검증시작 전과 검증 실패 후(뷰 반환 직전)에 item.getPrice()의 값을 로그로 확인했는데, 둘다 1이 뜨더라구요.그럼 검증 실패후 뷰로 넘어갔을 때 뷰에서는 똑같이 1이 남아있어야 하는거 아닌가요? 뷰의 th:field="*{price}"는 item.getPrice()로 값을 가져오는데 왜 1이 아니라 null인건지 이해가 안됩니다..!-> 강의뒷편에 내용이 나오네요 ㅎㅎ해결했습니다.
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
유형8번18분30초 질문있습니다
자식앞에 스태틱을 지웠을땐 오류가발생하는건 이해했는데 어느줄에서 발생하냐고물으면 어떻게답해야하나요?
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
14:21 업캐스팅문제 예시 5
이해를 못해서 질문하게되어 죄송합니다. 예시5번문제는 생성자 of A생성자BB1 은 알겠는데 그다음ACBD가 아니고 CD인 이유를 모르겠습니다
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
웹에서 실시간 코드반영이 안돼요
jsx파일의 코드를 수정하면 영상처럼 바로바로 바뀌어야하는데 웹을 클릭하면 새로고침되고 클릭안하면 업뎃이 안돼요
-
해결됨아바타 커뮤니티앱 만들기 (React Native Expo)
33. 강의 로그인 연동 중 에러
안녕하세요, 33. 강의 로그인 연동 중 에러가 발생하여 질문드립니다..! 코드 작성 이후 회원가입 시연을 시도하였는데, pgAdmin4에 데이터가 쌓이지 않고 터미널에 다음과 같은 에러가 발생하였습니다. iOS Bundled 788ms node_modules/expo-router/entry.js (1383 modules)λ Bundled 449ms node_modules/expo-router/node/render.js (1084 modules)Web node_modules/expo-router/entry.js ▓▓▓▓▓▓▓▓▓▓▓░░░░░ 69.8% (666/797)λ node_modules/expo-router/node/render.js ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░ 98.7% (1077/1084)Web Bundled 1009ms node_modules/expo-router/entry.js (797 modules)Web node_modules/expo-router/entry.js ░░░░░░░░░░░░░░░░ 0.0% (0/1)λ WARN "shadow*" style props are deprecated. Use "boxShadow". λ Bundled 24ms node_modules/expo-router/node/render.js (1 module)Web Bundled 191ms node_modules/expo-router/entry.js (1 module) 해당 문제 해결 방법을 알려주시면 정말 감사하겠습니다!
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
13:14 업캐스팅 문제예시4 질문입니다
정답이 Constructor of AACBD가 아닌가요? 어렵네요
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
4:07 업캐스팅 예제 해섷주신거봐도 잘 모르겠어서 질문합니다
다른 분이 질문해서 해설 올려주신거 봤는데도저는 아직 이해를 못했습니다.car.start()는void start-Tesia Model3시동걸기인데 car.stop()는 왜 Tesia Model3정지가 아니고 Tesia Model3정지 및 전원끄기인가요?용기내서 질문하는거니까 귀찮으셔도 해설 부탁드립니다
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
25분에 빈칸채우기 문제
I는 배열의 숫자들인거 알겠는데J는 무엇인가요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]
app.use질문
강의 영상 2분에 보면 app.use('/users', require('./routes/users'));가 있는데 전 영상들에서 저런 코드는 없었는데 따로 추가해야하나요
-
해결됨(2025) 일주일만에 합격하는 정보처리기사 실기
연산자 우선순위
안녕하세요 연산자 우선순위 강의에서 9:00쯤에포인터(*) ++전위연산자 보다 우선순위가 높다고 하셨는데 같은 우선순위 아닌가요?
-
미해결김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍
스트림 중복 에러 관련 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요 영한님 🙂스트림 중복 여부의 경우 왜 컴파일 에러가 아닌 런타임 에러로 자바가 만들어진 이유를 알 수 있을까요?챗지피티에 질문을 해봤는데 잘 이해가 되지 않아 질문드리는점 양해 부탁드립니다(_ _)감사합니다.
-
미해결[실전취업] 구글&아마존 출신이 알려주는 취업/이직에 관한 실전강의 + 취업 전자책(p144)
경력직 백엔드 개발자 이직도 포폴 중요할까요
안녕하세요.경력직 분들은 회사에서 한 결과물을 회사 내 비즈니스가 안 나오도록 각색해서 올려도 괜찮은 걸까요? 간혹 했던 업무에 대한 아키텍처가 필요하면 그리라는 경우가 있는데, 미리 포트폴리오로 제출하면 안 되는 걸까요?
-
해결됨350개의 개인 앱을 만들어 월급의 7배 수익을 달성한 방법
figma first draft 기능에 관해 궁금한 점이 있어요.
안녕하세요 선생님 수강 잘 하고 있습니다.다름이 아니라 이번 섹션에서 보여주신 figma에서 제공하는 first draft 기능을 사용을 할 수가 없어 찾아보니 Beta기능인데, 현재는 베타 신청을 받고 있지는 않는 것 같더라구요. 구독을 하면 사용 가능한가 해서 찾아봤는데 또 그런 것 같지는 않네요..!혹시 figma의 first draft를 사용할수 있는 방법 혹은 비슷한 대안이 있는 지 알 수 있을까요~?