안녕하세요. 과제를 잘 못 이해한건가 싶기도 하지만 아래와 같은 조건하에 구현을 해 봤습니다. 수업 과정에서 Front-end는 고정인 상황이기 때문에 기존 API는 변경이 없다는 가정하에 변경 해 봤습니다. 시간대1개와 요일n개의 설정이 하나의 row로 묶여있는 상태로는 요일별 시간대 변동에 대응하기 까다로운 것 같아 요일별 개별 row로 저장하도록 일부 수정 하였습니다. API endpoint 모델 변경을 피하기 위해서 내부적으로 여러개의 요일별 row로 나누어 저장하도록 했습니다. 고민중에 작가님께서 올려 놓으신 레퍼런스 코드를 봤는데, 책에서 언급하신 것 처럼 postgres 경우와 sqlite 경우로 코드가 분기 되는 것을 보았고, 지금은 교육 과정이기 때문이라고 생각 하지만 배포 코드와 개발 환경 코드가 다른것은 여러모로 좋지 않은 것 같아 현재는 sqlite 기준으로 개별 DB구현에서만 지원하는 것은 배제하는 방향으로 구현 했습니다. 1과 같이 변경 함으로써, 기 등록된 정보의 수정에서는 개별 날짜 별 시간대 설정 면에서 자유도가 생겼다고 생각 됩니다. 타임슬롯의 변경과 삭제에 관해서는 내부적으로는 time-slot으로 관리하지만, 외부공개 id는 아니므로, 키 로서 start-time, end-time, weekday (API형태로서는 리스트)조합으로 정의 해서 동작 하도록 구현했습니다. 특히 삭제의 경우는 부득이 delete method의 경우는 payload가 포함되는것이 받아들여지지 않는 경우도 있는것을 고려해서, 새 등록 값 두가지(new_start_time과, new_end_time) 값이 모두 제공되고 같은 경우를 특정하여 삭제 동작으로 정의하여 동작하도록 구현했습니다. class TimeSlotUpdateByGroupIn(SQLModel): start_time: time end_time: time weekdays: Weekdays new_start_time: time | None = None new_end_time: time | None = None new_weekdays: Weekdays | None = None @model_validator(mode="after") def check_update_fields(self): update_fields = { "new_start_time": self.new_start_time, "new_end_time": self.new_end_time, "new_weekdays": self.new_weekdays, } if not any(value is not None for value in update_fields.values()): raise ValueError("최소 하나의 수정 필드는 반드시 제공되어야 합니다.") return self @router.post("/time-slots", status_code=status.HTTP_201_CREATED, response_model=TimeSlotOut) async def create_time_slot( user: CurrentUserDep, session: DbSessionDep, payload: TimeSlotCreateIn, ) -> TimeSlotOut: if not user.is_host: raise GuestPermissionError() weekdays = sorted(set(payload.weekdays)) # dup. check with already exist one stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.weekday.in_(weekdays), TimeSlot.start_time < payload.end_time, TimeSlot.end_time > payload.start_time, ) ) result = await session.execute(stmt) existing_time_slot = result.scalars().first() if existing_time_slot: raise TimeSlotOverlapError() time_slots = [ TimeSlot( calendar_id=user.calendar.id, start_time=payload.start_time, end_time=payload.end_time, weekday=weekday, ) for weekday in weekdays ] session.add_all(time_slots) await session.commit() if not time_slots: raise TimeSlotOverlapError() return TimeSlotOut( start_time=time_slots[0].start_time, end_time=time_slots[0].end_time, weekdays=weekdays, created_at=time_slots[0].created_at, updated_at=time_slots[0].updated_at, ) @router.get( "/time-slots/{host_username}", status_code=status.HTTP_200_OK, response_model=list[TimeSlotOut], ) async def get_host_timeslots( host_username: str, session: DbSessionDep, ) -> list[TimeSlotOut]: stmt = ( select(User) .where(User.username == host_username) .where(User.is_host.is_(true())) ) result = await session.execute(stmt) host = result.scalar_one_or_none() if host is None or host.calendar is None: raise HostNotFoundError() stmt = select(TimeSlot).where(TimeSlot.calendar_id == host.calendar.id) result = await session.execute(stmt) time_slots = result.scalars().all() grouped: dict[tuple[time, time], TimeSlotOut] = {} for time_slot in time_slots: key = (time_slot.start_time, time_slot.end_time) if key not in grouped: grouped[key] = TimeSlotOut( start_time=time_slot.start_time, end_time=time_slot.end_time, weekdays=[time_slot.weekday], created_at=time_slot.created_at, updated_at=time_slot.updated_at, ) continue grouped[key].weekdays.append(time_slot.weekday) if time_slot.created_at < grouped[key].created_at: grouped[key].created_at = time_slot.created_at if time_slot.updated_at > grouped[key].updated_at: grouped[key].updated_at = time_slot.updated_at if not grouped: raise TimeSlotNotFoundError() for time_slot in grouped.values(): time_slot.weekdays = sorted(set(time_slot.weekdays)) return list(grouped.values()) @router.patch( "/time-slots", status_code=status.HTTP_200_OK, response_model=TimeSlotOut | None, ) async def update_time_slot( user: CurrentUserDep, session: DbSessionDep, payload: TimeSlotUpdateByGroupIn, ) -> TimeSlotOut | None: if not user.is_host: raise GuestPermissionError() current_weekdays = sorted(set(payload.weekdays)) stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.start_time == payload.start_time, TimeSlot.end_time == payload.end_time, ) ) result = await session.execute(stmt) current_slots = result.scalars().all() if not current_slots: raise TimeSlotNotFoundError() existing_weekdays = sorted({slot.weekday for slot in current_slots}) if existing_weekdays != current_weekdays: raise TimeSlotNotFoundError() delete_only = ( payload.new_start_time is not None and payload.new_end_time is not None and payload.new_start_time == payload.new_end_time ) if delete_only: current_ids = [slot.id for slot in current_slots] await session.execute(delete(TimeSlot).where(TimeSlot.id.in_(current_ids))) await session.commit() return None new_start_time = payload.new_start_time or payload.start_time new_end_time = payload.new_end_time or payload.end_time new_weekdays = sorted(set(payload.new_weekdays or payload.weekdays)) if new_start_time >= new_end_time: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, detail="시작 시간은 종료 시간보다 빨라야 합니다.", ) current_ids = [slot.id for slot in current_slots] stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.weekday.in_(new_weekdays), TimeSlot.start_time < new_end_time, TimeSlot.end_time > new_start_time, TimeSlot.id.not_in(current_ids), ) ) result = await session.execute(stmt) existing_time_slot = result.scalars().first() if existing_time_slot: raise TimeSlotOverlapError() await session.execute(delete(TimeSlot).where(TimeSlot.id.in_(current_ids))) new_time_slots = [ TimeSlot( calendar_id=user.calendar.id, start_time=new_start_time, end_time=new_end_time, weekday=weekday, ) for weekday in new_weekdays ] session.add_all(new_time_slots) await session.commit() return TimeSlotOut( start_time=new_start_time, end_time=new_end_time, weekdays=new_weekdays, created_at=new_time_slots[0].created_at, updated_at=new_time_slots[0].updated_at, )
안녕하세요. 좋은 강의 감사합니다. 강의를 듣다 몇가지 의문이 있어 글을 작성합니다. 애드몹 광고는 비공개 테스트시에도 적용을 해야하나요. 비공개 테스트시에도 애드몹광고를 추가한 상태에서 진행해야하나요? 비공개 테스트가 완료된 상태에서 애드몹광고를 추가하고 출시가 가능한가요? 비공개 테스트시에는 애드몸광고를 넣지않고 앱을 개시할때 추가해도되나요 애드몹 공고로 등록한 모바일 폰은 비공개 테스트 시 12개중한개의 모바일폰에 포함되나요.
안녕하세요 짐코딩님 덕분에 좋은 기능 배우고 있습니다! 일단 윈도우11서 claude code의 pro 이용을 하고 있습니다. 다름 아니라, 계획 검토 및 수정 요청 부분이 궁금해서 질문드립니다...! 저 같은 경우, 처음부터 interactive Question 기능이 나오는 것을 봤을 때, 이 기능이 default인 거 같더라고요 근데 계획을 다 보고, 계획 내용을 수정하고 싶은데, 따로 수정사항을 요청하는 선택지는 없고, esc를 누르면 아예 취소가 되서 미션 중의 3단계를 어떻게 할 수 있을지 궁금해서 질문드립니다!
저는 강사님의 refer & earn 주소로 runpod.io 사이트 열고, 영상에 나온 팝업창 누르고 구글 계정으로가입하고 10달러 결제까진 순조롭게 되었습니다....만 5달러는 안들어왔고 딱 결제한만큼 10달러만 있네요! 다른 분들은 어떻게... 추가로 5달러 받으셨는지 궁금합니다.
강의 수강 방법에 대해서 질문이 있습니다. 저는 Blind75를 순서대로 풀고 있는데 강의 순서랑은 Blind75 순서랑 조금 다르더라구요 자료구조 알고리즘을 모르는 상태로 강의를 시작해도 되는지 1번과 연계되는 질문으로 일단 문제 풀이를 시도하되 한 문제당 어느정도의 시간을 두고 풀면 되는지 보통 10분 정도 고민해보고 정말 모르겠다면 문제풀이 강의를 바로 들어보는 편입니다. Blind75 순서대로 문제를 풀면서 풀지 못한 문제에 대해서만 강의를 시청하면 되는지 좋은 강의 만들어주셔서 감사합니다.
'섹션 2. Next.js를 소개합니다' - '7. 1.3) 실습용 백엔드 서버 세팅하기' 강의 10:04 에서 npm i 하면 ' 30 vulnerabilities (9 low, 7 moderate, 13 high, 1 critical) '라고 취약점이 많이 떠서 AI를 활용해서 취약점을 제거 했습니다. AI가 권하는대로 npm audit fix npm install @nestjs/common@latest @nestjs/core@latest @nestjs/platform-express@latest @nestjs/swagger@latest @nestjs/cli@latest @nestjs/testing@latest 명령어를 사용하여 취약점을 제거했습니다. 이후 npm i 등 cmd 명령어를 순서대로 입력해서 해당 강의에서는 문제 없이 잘 진행이 됩니다. npm install @nestjs/XXX@latest 명령어들이 최신 버전을 설치하는거 같아서 나중에 버전 관련 문제가 생기지 않을까 걱정이 됩니다. 지금이라도 다시 백엔드 서버 세팅을 다시 맞춰서 강의와 맞는 버전으로 진행하는게 좋을까요?
강의 내용 중에 "pip install pykrx" 이 부분에 대한 설명을 해 주신다고 했지만 나중에 VS CODE만 설명하시면서 실제로는 강의에서 빠져 있어서 기존 문의드린 오류가 난 게 아닌가 합니다. 느낌으로는 conda promp 상에서 실행하면 될 것 같은데 안되네요. "pip install pykrx" 를 어디에 설치해야 하나요? 아래 2곳에서는 안됩니다.
The 10x AI-Native Developer: 회사에서 AI로 압도적 성과를 내는 법
2.0.76 (Claude Code) 버전에는 # 메모리 기능이 없습니다..ㅠ (+ 자문자답일거 같은데요.. 혼자 이것저것 하다보니 /memory 기능 이용하면 어쨌든 CLAUD.md에 내용 저장하게끔 하는 기능이 있는데, 결국 # 쓰는거랑 결과는 동일하니 이렇게 처리하면 되겠죠...?)
이 부분을 주석처리해서 빌드하고 실행해보니 확실히 모달 띄우고 닫을 때 시간 체감이 될 정도로 줄어드네요. 강의에 넣어주신 Vercel 최적화를 진행해도 잡히지 않아서 더 근본적인 문제가 있는 것 같아 실험해 봤더니 유의미한 결과가 있던 것 같아서 공유드립니다. 개인적인 생각으로는 수십 개의 데이터를 한꺼번에 가져오는 바람에 생기는 성능 이슈라고 생각하는데, 페이지네이션 api 요청 처리를 배우는 겸으로 /review/book/${bookId} api를 조금 더 고도화하면 좋을 것 같습니다. 긴 강의 준비해주시느라 너무 고생 많으셨고, 덕분에 제 실무 프로젝트에도 아주 유용하게 적용할 수 있을 것 같습니다. 감사합니다!