안녕하세요. 트랜잭션 메시징에 대해 궁금한 것이 생겨 질문드립니다. 트랜잭션 메시징은 데이터베이스 작업과 메시지 발행 작업을 원자적으로 수행하여 데이터의 일관성을 보장하는 것으로 알고 있습니다. 강의 내용 중 '트랜잭션 메시징의 한계'에서 분산 트랜잭션을 완벽하게 보장하지는 않는다고 하셔서 이를 DB의 트랜잭션과 메시지 전송의 트랜잭션이 서로 독립적으로 작동한다고 이해했습니다. 그럼 RabbitMQ에서 트랜잭션 메시징을 지원한다고 할 수 있나요?
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 안녕하세요? 강의 계속 잘 듣고 잇습니다. 이제거의 막바지에 이르렀네요 ㅎㅎ.. 게시글 목록조회 최적화와 관련하여 질문드리고자 합니다. 제가 처음에 이해한 바는 최신의 천개의 데이터를 레디스에 적재하고, 그 외의 데이터는 직접 articleServcie를 통해 가져오자 라고 이해를 했었습니다.(hot, cold Data) 그런데 이후의 결과적으로는 아래 두가지 캐시가 존재하게 되었더라구요 1.zset을 활용한 인기글 데이터 관리(목록 조회 최적화) 2.실제 데이터 queryModel(단건 조회 최적화) 이런 구조에서는 zset에서 천개의 데이터를 관리하긴 하지만 실제로 queryModel에는 데이터가 있을지 없을지 확신을 할 수 없는 상황이라는 생각이 듭니다. 즉 실제로 zset에 있는 데이터라 해도 하루가 지났다면 queryModel이 있을지 없을지 모르는 상황이라고 인지했습니다. 질문1) 제가 이해한바가 맞을까요? 맞다면 이 구조를 선택하신 이유가 조금 궁급합니다. 두 캐시를 합쳐서, queryModel자체를 하나의 캐시에서 천개의 데이터만 관리하면 되지않나? 라는 의문이 생겨가지구요 어차피 천개의 데이터만 관리한다면 메모리를 그렇게 크게 차지 하지 않을 것 같기도 하구요 질문2) 지금과 같은 구조에서는 zset을 활용한 article_id가 그렇게 큰 의미가 있는 부분인가? 라는 생각이 듭니다. - 어차피 최신순(1000개이하)의 데이터에 대해서 id를 추출하는거면 DB에서 offset을 세어도 그렇게 안느린 거 아닌가? 하는 생각이 들구요 - zset에 포함되어 있더라도, 실제 데이터(QueryModel)가 있는지 없는지 확답을 할 수 없는 상황이니 큰 의미가 있는건가? 하는 의문이듭니다. 차라리 최신 천개의 데이터에 대해서는 조회에 필요한 모든 데이터를 캐싱해둔다면 큰 의미가 있을거라고 생각이 드는데, 지금의 경우에 대해서는 잘 모르겠네요 ㅠㅠ -결론적으로, 현재 회사에서 RDB를 주로 쓰고 있는 주니어 개발자 입장에서 관련해서 레디스를 도입해본다면.. 아키텍처 복잡도가 올라가는 부분에 비해 엄청 크게 이득이 되는 부분이 있나?? 라는 생각이 많이 들었습니다. 질문3)추가로, 이거는 좀 다른 부분이긴 한데 read-service에서 like, unlike등 업데이트 이벤트 핸들러의 경우 동시요청에 대해서 lostupdate처럼 동작하는 부분이 있을 것 같은데 이부분은 배제하신건지, 혹은 제가 잘못생각하고 있는건지 궁금합니다. 양질의 강의 정말 감사드립니다
해당 강의를 수강하고 하루죙일 찾아봤지만 실질적으로는 문제를 해결하지 못했습니다. ㅜㅜ 문제가 왜 발생했는지 추적한 결과 실제로 xml를 불러들일때, fk 관련 속성을 잘 갖고 오지만, @JoinColumn 을 생성할 때 fk 속성을 삽입하는 코드가 실질적으로 존재하지 않고, fk제약 조건 생성을 위해 alter 시에 @JoinColumns로 지정됩니다. 실제 어노테이션 기법으로 작성 할 경우 @JoinColumn으로 수집이 되지만, -참고- @JoinColumns 으로 수집 시 xml 스펙에서 join-column 태그는 Unbounded로 스펙이 정해져 그렇게 처리 된 거 같아요. 하이버네이트 6.6 버전에서는 jpa 매핑 관련해서 xml 3.1 버전으로 관리되고, 7.0 버전부터는 xml 7버전으로 매핑이 관리될 것 같습니다. 하이버네이트 6.6 버전에선 실질적으로 버그라고 생각되고, 7.0 버전에는 JPAXMLOverridenAnnotationReader 클래스가 사라진 상황이라 7 버전으로 올려서 확인해봐야 할 것 같지만, 스프링 부트 3.x.x버전은 아무래도 하이버네이트 6.6 버전 기준으로 버저닝이 될 거 같아 해당 문제의 해결 방법은 실질적으로 찾진 못했습니다. ㅜ
Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
안녕하세요, 짐코딩님. 덕분에 재밌는 수업 듣고 있습니다. :) 현재 저는 짐코딩 님의 깃허브에서 => 최종 코드를 clone해서 모두 받은 후 그 중에서 Notion API만 변경해서 제 notion과 연결을 한 후 수업을 수강하고 있습니다. (API 연결 활성화가 되어 있는 캡처본/.env에서도 환경변수로 설정 완료) 혼자서 노션 블로그 게시물 등록 및 조회 테스트를 해보다가 2가지 문제점이 발생했습니다. 제가 직접 노션에 추가한 게시물의 경우 '게시물 목록'에는 뜨지만 상세페이지 클릭했을 경우 404 에러 발생 예를 들어) localhost:3000/blog/web (web은 slug 값) 이렇게 타이핑하면 상세 페이지에 잘 들어가는데, 해당 블로그를 클릭해서 들어가면 아직 url에 localhost:3000/blog/243888f~~ 이런식으로 뜨네요 ㅜㅜ 반영이 늦는걸까요 직접 노션에 추가한 게시물을 노션에서 삭제한 후 브라우저에서 보면 사라지지 않고 '게시물 목록'에 뜨고, 상세페이지를 클릭했을 경우 '404 에러 발생' 제가 직접 올린 노션 게시물만 저런 현상이 발생하고. 짐코딩님께서 미리 작성해놓으신 '웹 개발 학습 가이드'나 'Git 시작하기' 등은 상세 페이지를 클릭하면 잘 뜹니다. 이유를 모르겠습니다 ㅜㅜ 코드를 전달 드리고 싶은데, 짐코딩님 코드를 모두 클론한 걸 사용하고 있어서 어떻게 전달드려야 할지 모르겠어서 우선은 404 에러가 뜨는 이미지와 상황 설명만 먼저 전달 드립니다! 참고로 현재까지 저는 remark and rehype 플러그인 설치 강의까지 학습했습니다! 제가 왕초보라 많이 미흡합니다. 최대한 쉽게 설명해주시면 너무나 감사드리겠습니다! 항상 친절한 답변과 강의 감사드립니다.
앞서 생성자, 소비자 강의에서 생산자가 데이터를 생성하면 다음과 같이 데이터를 넣었고 queue.offer(data); 소비자는 큐에서 생산자가 생산한 데이터를 꺼내어 소비하였습니다. queue.poll(); 이번 강의에서는 큐에 작업을 넣고, 빼서 처리합니다. 생산자 소비자에서는 데이터를 넣고 빼고 이번 스레드풀 강의에서는 작업을 넣고 빼니 처음에는 작업을 넣고 빼는 큐와 생산자,소비자가 사용하는 큐가 별도로 있는 건가? 했는데 강의를 들어보니 별도로 있는건 아니고 같은 큐인것 같더라구요. 그런데 생산자,소비자에서는 어떤 작업의 결과인 데이터를 생산 하여 큐에 넣고 꺼내어 소비 한다는 것이 직관적이어서 이해가 잘되었는데요. 이번 강의에서는 생산자가 '작업'을 큐에 넣고 빼서 소비자가 큐에서 작업을 빼는데 큐에 넣는 주체가 ' 데이터 '에서 ' 작업 '으로 바뀌어 설명하니 무엇을 생산하는 것이지? 하며 헷갈린다고나 할까요. 생산자소비자 강의에서처럼 어떤 작업의 결과를 큐에 넣고 빼는 것이 아니라 실제로는 작업 자체를 생산하여 큐에 넣는건가요? 그러니까 앞선 생산자와 소비자는 단순 이해를 위한 것이고 실제로는 Runnable 이라던지 Callable 같은 작업 객체 자체가 생산되어 큐에 들어가는 것인가요? 감사합니다
AtomicInteger.get()을 CAS 연산 후 반환값으로 사용하면 안 되는 이유 🚨 핵심 문제: 원자성에 대해서 다시 생각해보기 CAS 연산의 원자성은 compareAndSet() 호출 자체에만 적용됨 CAS 성공 후 get() 호출 은 완전히 별개의 연산 두 연산 사이에 다른 스레드가 개입 가능 멀티스레드 환경에서는 언제든지 다른 스레드가 개입 가능 개발자는 OS가 중간에 어떤 스레드를 호출할지 알 수 없음 🔍 문제 발생 메커니즘 1. 시간적 틈(Time Gap) 존재 result = atomicInteger.compareAndSet(getValue, getValue + 1); // ✅ 원자적 // ← 이 시점에서 다른 스레드가 값을 변경할 수 있음 return atomicInteger.get(); // ❌ 별개의 연산, 원자성 보장 안됨 2. 스레드 스케줄링의 불확실성 sleep(100) 동안 CPU가 다른 스레드로 전환 CAS 성공 직후에도 스케줄러가 해당 스레드를 중단 시킬 수 있음 먼저 시작된 스레드가 먼저 완료된다는 보장 없음 📊 실제 문제 시나리오 초기값: atomicInteger = 0 Thread A: getValue = 0 Thread A: compareAndSet(0, 1) 성공! → atomicInteger = 1 Thread A: CPU 스케줄러에 의해 중단됨 Thread B: getValue = 1 Thread B: compareAndSet(1, 2) 성공! → atomicInteger = 2 Thread A: 재개됨 Thread A: atomicInteger.get() 호출 → 2 반환 ❌ 결과 : Thread A가 실제로는 0→1로 증가시켰지만, 2를 반환하게 됨 ✅ 올바른 해결책: getValue + 1 사용 동작 원리 private static int incrementAndGet(AtomicInteger atomicInteger) { int getValue; boolean result; do { getValue = atomicInteger.get(); // 현재값 저장 result = atomicInteger.compareAndSet( // CAS 연산 getValue, getValue + 1 ); } while (!result); return getValue + 1; // CAS에서 사용한 기댓값 + 1 } 장점 CAS 연산 시점의 값 고정 : getValue 는 CAS 연산에서 사용한 정확한 기댓값 다른 스레드 개입 무관 : 이후 다른 스레드가 값을 어떻게 변경하든 영향받지 않음 메서드 의미 보장 : "이 메서드가 실제로 설정한 값"을 정확히 반환 🎯 핵심 교훈 ❌ 잘못된 가정 "CAS 성공 후 바로 get()을 호출하면 방금 설정한 값을 가져올 것이다" ✅ 올바른 이해 원자성은 단일 연산에만 적용 연산 간의 순서나 연속성은 보장되지 않음 멀티스레드 환경에서는 언제든지 다른 스레드가 개입 가능 개발자는 OS가 중간에 어떤 스레드를 호출할지 알 수 없음 💡 실무 적용점 AtomicInteger의 내장 메서드 활용 // 직접 구현하지 말고 내장 메서드 사용 int result = atomicInteger.incrementAndGet(); CAS 패턴 사용 시 주의사항 연산 결과는 CAS에서 사용한 값을 기준으로 계산 별도의 get() 호출로 "현재값"을 가져오려 하지 말 것 원자성의 범위 명확히 이해 단일 메서드 호출 = 원자적 여러 메서드 호출의 조합 = 원자적이지 않음
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 교재 챕터7(중첩클래스, 내부클래스) 16쪽에서 "실제로는 내부 인스턴스는 바깥 인스턴스의 참조를 보관"이라고 나와있는데, 정확히 어느 공간에 저장하는건가요?
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요?아니오 [질문 내용] libs파일이 없어서 gradlew.bat을 해봤는데 결과창이 나오질 않고 아무런 반응이 없습니다..
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 아니오 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 아니오 [질문 내용] 경로까진 들어왔는데 gradlew.bat, gradlew, ./gradlew을 해도 아무것도 되지 않고 내부 또는 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아니라고 뜹니다.
Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
안녕하세요, 선생님. 현재 블로그 상세 목차 UI까지 강의 수강했는데 코드 수정한 후 local에 띄어보니 스타일이 적용 안되는 문제가 발생했습니다. 선생님 github에서 해당 강의 관련 코드 다 가져와서 복붙 했는데도 저러네요... 제가 왕초보라서 도와주시면 감사하겠습니다!
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. AssignedShard 클래스의 목적이 샤드를 균등하게 분배하는 것이라고 보이는데요 저는 처음에 스레드가 처리할 일을 분할해주는 거라고 생각했는데 찾아보니까 앱 인스턴스를 기준으로 샤드를 나누는 것이라고 하더라고요. 근데 앱 인스턴스는 말하자면 각각의 서버? 예를 들어서 포트 9000번을 A,B,C 서버에서 실행하면 그 각각을 앱 인스턴스라고 부른다고 봤습니다. 그리고 이렇게 각각 다른 서버에서 하나의 포트를 실행하려면 운영 환경에서 서버의 부담이 커질때 서버를 늘려주는 로드밸런싱?같은 기법을 쓸때 필요한 샤드 분배 기능같은데 나중에 운영환경에서 이런때를 대비해서 미리 구현하신건가요? 아니면 이런 지금 강의 환경 안에서도 이렇게 앱 인스턴스가 늘어나는? 상황이 있는건가요.. 아직 공부중이고 모르는 부분도 좀 있다보니 설명이 두서없었습니다 ㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] casacade 사용시 주의할 점으로 특정 엔티티가 개인소유하는 자식일 경우에만 쓰는게 좋다 라고 말씀하셨는데, 여기서 특정 엔티티라는것이 엔티티의 구분을 말씀하시는건지 아니면 하나의 레코드를 말씀하시는건지 헷갈립니다. 아마 특정 레코드를 말씀하신것 같은데, 멤버와 페런트 엔티티가 child라는 같은 엔티티를 참조 한다고하지만, 결국에는 멤버와 페런트가 각각 개인의 child 레코드만을 참조한다면 문제가 없을것 같은데 맞을까요? 같은 레코드를 참조하는게 아니니까요!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 강의 보기 전에 미리 만들어 본 코드입니다. 3번째 줄에서 afterNode를 안 만들고 주석처리한 코드를 afterNode 자리에 넣으니 오류가 발생하네요 그리고 수업중 코드에서도 2번째줄 코드 위치만 바껴도 위와 똑같은 오류가 발생하네요 왜그런걸까요?
질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 변수 선언과 초기화 챕터를 보는 중에 궁금증이 생겨 질문합니다. System.out.println() 이 괄호 안에는 무조건 변수가 하나만 들어가야 하나요? 두개 이상은 들어가지 못하나요? 예를 들면 int c = 3, d = 4; System.out.println(c,d) 이렇게 하면 안되는건지요 만약 못한다면 왜 안되는것인가요? 궁금합니다!