안녕하세요. 상속과 별로 연관된 질문은 아닌 듯 하지만 강의에서 나온 부분에 궁금증이 생겨 질문 남깁니다. val swimAbility: Int get() = 3 이라는 예제 코드를 작성하셨는데요. 코틀린은 어차피 필드를 선언하면 게터, 세터를 만들어주고 필드 선언 시 디폴트 값도 지정해줄 수 있는데 그렇다면 위와 같은 형태의 커스텀 게터는 굳이 구현할 필요 없는 것 아닌가? 하는 생각이 듭니다. 그냥 초기값 3을 갖는 필드를 선언하기만 하면 게터까지 알아서 만들어질 테니까요. 그냥 인터페이스의 게터 상속 의도를 표현하기 위해 별 의미나 실 용례는 없는 코드를 작성하신 거라고 봐도 될지? 아니면 저런 방식의 커스텀 게터에 제가 이해하지 못하는 어떤 의미가 있는 것일지가 궁금합니다. 감사합니다. ㅇ
안녕하세요. 해당 PRD 생성 강의를 듣고 나서 세부적으로 깊은 질문이 몇 가지 생겨서 질문드리고자 합니다. 서브에이전트 문서를 여러 개 강사님께 받아서 진행했습니다. 다만 이전에도 질문 드린 적 있지만 세부적으로 프론트엔드, 백엔드, AI 등의 개인 프로젝트가 아닌 팀프로젝트 단위에서의 서브 에이전트 구성이나 이런 부분은 수강생이 스스로 학습해나가야 하는 부분도 있지만 어떤 식으로 만들어야 되고 참고하면 좋다라고는 말씀하셨지만 실질적으로 개인/팀 단위일 때의 에이전트 및 PRD가 어떤 식으로 차이가 나는 지 알고 싶습니다. (강사님께서 올려주신 소스 코드에 있는 것이 기본적인 틀이 될 수 있다는 점은 알겠지만 응용 단계에서 헷갈리는 부분이 발생한 부분입니다!) PRD에 API, DB 구조 등이 들어가있어 약간의 틀로 보이는데 실제 대형 프로젝트 등을 진행했을 때에는 API, ERD 구조 및 각종 사용자/관리자 명세서 등을 일일이 구분해서 만들었던 경험이 있었습니다. 이러한 것을 세분화해서 각각 자세하게 만들지 않고 PRD 하나로 뭉쳤을 때의 장점 및 단점, 향후 저를 포함한 수강생들이 어떤 방향성을 가지고 활용을 하면 좋을 지 아직까지는 감이 잘 오지 않습니다 ㅠㅠ
79. 서브에이전트 활용: 프로젝트 초기화 안녕하세요~ 이 단원이 좀 복잡해서 다시 보는중인데요, 프로젝트를 초기화(스타터킷에서부터)하는데, PRD를 참고해서 초기화 하는 방식으로 진행을 하시는데요, 이렇게 하면 프로젝트가 완전 초기화가 아닌(그냥 next.js 와 기본 라이브러리만 깔린 상태가 아닌), 초기화를 하면서 PRD에 나와 있는 PRD의 프로젝트를 일부 만드는 것 아닌가요?(실제로 UI,일부 버튼들을 만들더군요). 그냥 (완전)초기화하고 PRD로부터 ROADMAP.map을 만들어서 처음부터 하나씩 만들어 나가는게 더 깔끔한 방식이 아닌가 해서요. 왜냐하면 prd를 기준으로 초기화를 하면 일정부분 화면UI도 나오고 일부 버튼도 동작하는데, 결국에는 ROADMAP.md에 나와 있는 작업 순서대로 다시 작업을 하게 되면 2중으로 작업을 하는게 아닌가 해서요 (심지어 복잡한 프로젝트, 큰 프로젝트의 경우 초기화하면서 PRD 기준으로 만든 뼈대? UI하고 나중에 로드맵 만들고 본격적으로 프로젝트를 만드는중에 코드가 꼬이는(?) 현상 같은게 나오지 않을까 해서요)
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
@PutMapping("/user") public void updateUser(@RequestBody UserUpdateRequest request){ String readSql = "select * from user where id=?"; String sql = "update user set name=? where id=?"; jdbcTemplate.update(sql, request.getName(), request.getId()); } 웹페이지에서 update를 발생시켜서 put 요청이 올라 왔을때 UserUpdateRequest dto에 id와 name이 들어 간다는건 웹에서 요청이 올라왔을때 json에 이미 해당 name에 대한 id 정보가 있다는 거죠? id는 db에서 자동적으로 생성해 준다고 했었는데, 이 id를 웹에서는 어떻게 알고 있나요?
안녕하세요! 회사에서 프론트엔드업무도 맡게되어 강사님 강의로 잘 배우고 있습니다! 😍 😍 Context=props driling을 방지하려고 데이터를 꺼내쓰는 저장소를 만든다고 이해했습니다. 만약 Context.Provider로 "최상위 컴포넌트"를 감싸주면 그게 "전역" 저장소 역할을 하는거 아닌가요?!.. Redux나 zustand? 같이 전역저장소 역할을 하는 툴들이 있다고 하던데 조사해보니 value={{todos,b,c]} 일때 redux는 구독이라는 개념으로 todos의 "길이변화"를 감지해서 "특정 컴포넌트만 리렌더링" 시킬수있다..? 이런 정밀한 작업의 차이밖에 없는걸로 이해돼서요! 좀더나은 Provider로 이해됐습니다. 로그인 정보라던가 현재 선택한 메뉴정보, 장바구니정보 이런데이터들을 담기위해 앱최상단에 Provider로 감싸는건 안좋은 방법일까요? 굳이 Redux나 zustand같은 툴들을 사용하는 이유나 적절한 사용법이 궁금합니다!
안녕하세요. 프로젝트 2 섹션에 돌입하게 되어 프로젝트 소개 및 오리엔테이션을 수강을 시작한 뒤 의문점이 생겨 몇 가지 질문을 드리고자 합니다! 현재 Notion을 활용해서 견적서를 내는 프로젝트를 짐코딩님께서 강의를 쭉 촬영해서 올라와 있는 상태로 알고 있습니다. 하지만 아래 미션들을 보면 수강생들이 직접 아이디어를 내서 새로운 프로젝트를 생성하는 것을 미션으로 제출하고 있는 것으로 미리 확인을 했습니다. 그렇기 때문에 아무래도 pro 버전이라 실습을 하고 제 프로젝트도 따로 만들다보면 많은 토큰을 사용해서 Current Session 토큰이 부족해지거나 주간 토큰량을 초과하게 될까봐 걱정이 되는 상황이고, 또한 견적서는 학생인 저의 경우에는 실습까지 해두면 좋겠지만 토큰량이 걱정입니다. 이런 상황 속에서 아이디어를 미리 정하고 강사님의 강의를 들으면서 저의 프롬프트로 진행하는 것이 좋을 지 혹은 강사님의 커리큘럼대로 쭉 따라간 다음에 미션을 마지막에 진행해도 되는 지 여쭤보고 싶습니다. 현재는 섹션마다 강의를 듣고 미션을 바로바로 진행했는데(강의 실습 진행과 미션 진행을 동시에 => 그 이유는 스타터킷이라는 동일한 조건이기 때문에 실습 자료에 저의 생각을 넣어도 어차피 결과물은 다르게 나오기 때문에 괜찮다고 생각했습니다.) 생각보다 토큰이 빠르게 차서 중간에 작업을 중단해야 되는 경우가 발생했었기 때문에 질문을 드립니다. 위의 이유와 같이 스타터킷의 경우에는 저도 활용 가능하기 때문에 괜찮다고 생각했지만 견적서의 경우에는 당장 학생의 신분에서는 이 강의를 듣고 활용하기에는 어려움이 있지 않을까? 하는 의문이 생겼기 때문입니다!
1. 현재 학습 진도 몇 챕터/몇 강을 수강 중이신가요? 4-8강 2. 어려움을 겪는 부분 어느 부분에서 막히셨나요? chapter4/_2_event_with_participant 폴더의 EventJoinService 객체의 메서드 코드에 대한 질문입니다. 코드의 어떤 로직이 이해가 안 되시나요? @Transactional public void joinEvent(Long eventId, Long memberId) { Event event = eventRepository.findById(eventId) .orElseThrow(() -> new EntityNotFoundException("이벤트를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); // save()를 호출하지 않아도 Dirty Checking에 의해 Update 쿼리가 나가지 않나요? event.increaseParticipants(); eventRepository.save(event); EventParticipant participant = EventParticipant.builder() .event(event) .member(member) .build(); participantRepository.save(participant); } } 코드 블럭의 주석 란에 질문을 적어놓았습니다. 저 상황에서 save() 를 호출하는 이유가 궁금합니다. JPA 엔티티의 상태 변경분에 대한 쿼리는 트랜잭션 커밋 후, 자동으로 나가는 것으로 알고 있습니다. 혹시, 제가 잘못 알고 있는건지 궁금합니다.
이번 미션을 진행하면서 궁금한 점이 있어 질문드립니다. 이전 강의에서 프로젝트를 처음 시작시 보통 초기화(/init)하여 claude.md파일을 생성한다고 했는데 이번 미션에는 초기화없이 Plan Mode로 계획을 수립/구현하는데 그럼 구현 후 초기화하면 되는 걸까요? 초기화 하는 시점이 궁금합니다. 그리고 만약 구현 후 초기화하면 코드베이스를 분석하여 claude.md 파일을 생성하면 그 이후에 수정사항은 Plan Mode가 아닌 claude.md 파일에서 지침을 수정하면 이전 컨텍스트를 기억해서 수정하는게 아니라 claude.md 파일을 분석해서 수정하니까 token 소모가 덜 들것 같은데 claude.md 파일을 수정해서 구현을 요청해도 되는 걸까요?
안녕하세요 토비님!! 강의를 완강하고 제 프로젝트를 리팩토링하면서 피드백받고싶은점이 생겨 질문글을 올립니다. Repository Port를 기술에 종속시키지 않기 위해 Adapter에서 JPA, MyBatis, QueryDSL을 조합하는 구조를 선택했는데, 이 설계 방향이 적절한지 조언을 구하고 싶습니다. 현재 구조 core/ └── domain/ └── application/ └── required/ ← Port 인터페이스 └── ~Repository adapter/ └── persistence/ ├── ~RepositoryAdapter ← Port 구현체 ├── ~JpaRepository ← Spring Data JPA └── ~MybatisMapper ← Mybatis 매퍼 인터페이스 의존 관계 [Service] → [Repository] ←impl― [RepositoryAdapter] → [JpaRepository] → [MybatisMapper] → [JPAQueryFactory] (core) (core) (adapter) (adapter) 예시 @Repository @RequiredArgsConstructor public class ItemRepositoryAdapter implements ItemRepository { private final ItemJpaRepository itemJpaRepository; private final ItemMybatisMapper itemMybatisMapper; @Override public List<Item> findBySearchRequest(ItemSearchRequest request) { return itemMybatisMapper.findBySearchRequest(request) .stream() .map(Item::from) .toList(); } @Override public List<Item> saveAll(List<Item> items) { return itemJpaRepository.saveAll(items); } } @Repository @RequiredArgsConstructor public class AuctionRepositoryAdapter implements AuctionRepository { private final JPAQueryFactory jpaQueryFactory; private final AuctionJpaRepository auctionJpaRepository; @Override public void deleteAllByRegionAndRealmId(RegionType region, Long realmId) { QAuction qAuction = QAuction.auction; BooleanBuilder filter = new BooleanBuilder(); filter.and(qAuction.region.eq(region)); if (realmId == null) { filter.and(qAuction.realmId.isNull()); } else { filter.and(qAuction.realmId.eq(realmId)); } jpaQueryFactory.delete(qAuction) .where(filter) .execute(); } @Override public int saveAll(List<Auction> auctions) { if (auctions.isEmpty()) return 0; return auctionJpaRepository.saveAll(auctions).size(); } } 이 구조를 선택한 이유 동적 쿼리, 벌크 연산 등 JPA만으로 해결하기 어려운 케이스가 있어 MyBatis와 QueryDSL을 병행 사용하고 있습니다. 일반적인 방식인 Port 인터페이스가 Spring Data JPA Repository를 상속하는 구조를 채택하지 않은 이유: MyBatis나 QueryDSL 기반 구현체를 만들 수 없음 CustomRepository 인터페이스를 별도로 만들어야 하는 복잡도 증가 현재 방식의 장점: Port 인터페이스가 순수 Java 인터페이스로 유지됨 RepositoryAdapter에서 상황에 맞는 기술을 자유롭게 조합 가능 추가 인터페이스 없이 단순한 구조 유지 저는 현재 구조가 의존 관계도 외부에서 내부로 향하고 테스트도 쉬워서 괜찮다고 생각하는데 토비님의 생각도 듣고싶습니다!! 좋은 강의 감사합니다!!
안녕하세요, PRD.md -> ROADMAP.md -> Shrimp 로 작업 쪼개기 후 MVP 만든 후에, 기능을 새로 추가할때마다 똑같은 프로세스 ( PRD.md -> ROADMAP.md -> Shrimp ) 를 반복해야 하나요? 아니면 그냥 클로드에 바로 해당 기능을 추가해달라고 하는게 좋을까요?
마지막 부분인 9.5 프로필 인가부분까지 수업을 들으면서 코드를 작성했는데, ProfileDetailPage가 제대로 렌더링 되지 않아서 질문드립니다. 코드가 혹시 잘못되었을까해서 깃허브 보고 다시 확인했는데, 코드는 강의 내용이랑 맞는 것 같습니다. 뭐가 문제인지 잘모르겠어요