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 플러그인 설치 강의까지 학습했습니다! 제가 왕초보라 많이 미흡합니다. 최대한 쉽게 설명해주시면 너무나 감사드리겠습니다! 항상 친절한 답변과 강의 감사드립니다.
추가할 todo에 공백이 포함된 상태로 엔터를 입력하면 위와 같이 추가가 되는데 제가 잘못한 부분이 있을까요? https://github.com/juan-rybczinski/learn-react/commit/dba6aab43a96601fed941edfa652e4508f6a88e9
앞서 생성자, 소비자 강의에서 생산자가 데이터를 생성하면 다음과 같이 데이터를 넣었고 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() 호출로 "현재값"을 가져오려 하지 말 것 원자성의 범위 명확히 이해 단일 메서드 호출 = 원자적 여러 메서드 호출의 조합 = 원자적이지 않음
강의에서 function Header () {} 와 const Header = () => {} 이 식이 똑같다고 하셔서 function Header () {} 이 식으로 컴포넌트 header.jsx파일에 붙혀넣었더니 페이지오류가 나오더라구요 import로 연결할땐 차이가 있는걸까요?
Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
안녕하세요, 선생님. 현재 블로그 상세 목차 UI까지 강의 수강했는데 코드 수정한 후 local에 띄어보니 스타일이 적용 안되는 문제가 발생했습니다. 선생님 github에서 해당 강의 관련 코드 다 가져와서 복붙 했는데도 저러네요... 제가 왕초보라서 도와주시면 감사하겠습니다!
https://inf.run/zqFYv 이 게시글과 실패 로그가 완전히 동일하고 댓글대로 했지만 해결되지 않았습니다. 파이썬 32bit 와 호환이 잘 안되는 것 같은데 32bit 파이썬으로 꼭 설치해야하는 것이죠? 혹시 패키지별로 어떤 버젼들을 설치하셨는지, requirements.txt 알려주실 수 있으실까요? 감사합니다.
https://inf.run/wLydT 해당 질문과 동일한 오류가 생겨서 답변을 참고해 PATH 등록을 했습니다만 여전히 동일한 오류코드가 뜨며 인식 불가능한 명령어라고 뜹니다. 다른 문제가 있을까요? 위 답변에서 알려준 확인 명령어들을 사용했을 때에는 설치되었다고 뜹니다. 참고로 현재 영상을 수강하는 시점에서는 아나콘다의 최신버전 설치에 따라 python 또한 3.13.5 버전으로 설치되었습니다.
[Error: Make sure to complete the guide at https://docs.expo.dev/push-notifications/fcm-credentials/ : Default FirebaseApp is not initialized in this process com.lukasdiego.retrythreads. Make sure to call FirebaseApp.initializeApp(Context) first.] npx expo run:android로 앱을 실행하니 위 처럼 FirebaseApp 초기화 부분이 안됩니다. 우선 Credentials는 등록된 것을 확인했습니다 !
포맷팅 복습하다가 질문드립니다. print('나는 {}호선을 타고 학교를 가'.format(6)) print('나는 {0}호선을 타고 학교를 가'.format(6)) 동일한 출력 값인데, {}안에 인덱스(위치 숫자)를 넣어주면 그 값이 들어가게 된다고 하셨는데 그럼.. print('나는 {1}차를 타고 학교를 가'.format('우리집')) print('나는 {1}호선을 타고 학교를 가'.format(643)) 이면 첫번째 줄은 포맷함수의 문자열의 인덱스 1번 위치인 리 두번째 줄은 포맷함수의 숫자열 인덱스 1번 위치인 4 가 각각 출력되어 중괄호 안에 들어가게 되나요?
if 사용시 작성 관련하여 반드시 아래의 형식을 따라야 값이 제대로 출력되는지요 if 1: print('true') else: print('false') 한줄로 입력하거나 if'sojin': print('true') else:print('false') 아니면 띄어쓰기를 틀리면 아래와 같이, if 1: print('true') else: print('false') 오류로 나옵니다. 문법과 같이 작성양식도 정해져 있어서 if사용시는 if 1: print('true') else: print('false') 표시 형식을 따라야 하는지 질문 드립니다.
안녕하세요! 강의 2분 35초에 post_list.html에서 post_create.html로 폼 분리하고 path 따로 만들었는데 form action은 그대로 'posts'라고 둬도 되는건가요,,? 저는 'post_create'로 변경해줘야 올바르게 연결이 되는데 혹시 제가 놓친 부분이 있나 해서 질문 드립니다.