묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨Practical Testing: 실용적인 테스트 가이드
양방향 매핑
안녕하세요~ 양방향 매핑을 사용하면 엔티티 간의 결합도를 높이기 때문에 가급적 단방향으로 만들면 좋다는 의견도 많은 것 같더라구요.심지어는 양방향 매핑을 만들어야 한다면 엔티티가 아니라 id 값을 넣어서 참조를 하는게 더 좋다는 의견도 있구요. 강의에서는 양방향 매핑을 사용하셨는데 실무에서도 자주 양방향 매핑으로 설계하시나요?사용하신다면 이러한 단점이 있지만 편의성이 더 크기 때문인가요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
연관관계 메서드의 위치는 핵심적으로 컨트롤 하는 쪽이 무슨 말일까요?
24분 30초부터 연관관계 메서드에 관련해서 설명해주시는데연관관계 메서드의 위치는 핵심적으로 컨트롤 하는 쪽에 있는 것이 좋다 이게 무슨 말인지 잘 이해가 되지 않습니다 ㅠㅠ
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
updateItem질문입니다.
@PostMapping("/items/{id}/edit") public String updateItem(@PathVariable Long id, @ModelAttribute Item item) { Item findItem = itemService.findById(item.getId()); //더티 체킹 findItem.setId(item.getId()); findItem.setName(item.getName()); findItem.setPrice(item.getPrice()); findItem.setStockQuantity(item.getStockQuantity()); findItem.setAuthor(item.getAuthor()); findItem.setIsbn(item.getIsbn()); return "redirect:/items"; } 강의를 보지 않고 스스로 코드를 짜보고 있는데 이렇게 하니까 수정내역이 반영 되지 않더라구요 스스로 생각해봤을 때는 다음 2가지 이유 중 하나일 것 같은데 이유가 이유가 무엇인가요 ㅠㅠ? findItem은 영속성 컨텍스트가 관리하지 않는 객체가 된 것이다. 따라서 더티체킹이 되지 않는다. 영속성 컨텍스트가 관리하는 엔티티는 맞지만 Controller에는 트랜잭션이 없어서 반영이 안되는 것이다.
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
bootstrap.min.css 파일이 어떤 역할을 하는 건가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. html 디렉터리에 있는 html파일들이 bootstrap.min.css 파일과 연결된다고 했는데 이렇게 하면 어떠한 효과가 있는건가요?
-
해결됨Practical Testing: 실용적인 테스트 가이드
패키지 구조에 대한 질문
안녕하세요 강의에서는 패키지 구조를 api 아래에 api - service - productapi - controller - product 이렇게 구현하셨는데이렇게 구현하면 도메인이 많아지면 가독성이 떨어질 것 같아서 각 도메인마다 service, controller를 가지게 하는 구조는 어떻게 생각하시나요? api - product - service, controller가독성보다 더 중요한 장점이 있을까요?실무에서는 어떻게 하시는지 궁금합니다. 감사합니다~!
-
해결됨Practical Testing: 실용적인 테스트 가이드
단위테스트의 개념에 대해서 질문 드립니다!
안녕하세요! 테스트 강의가 드문데 정말 친절하게 잘 알려주셔서 감사하게 듣고 있습니다 :)아직 강의를 다 들은 것은 아니지만 강의 내용 중 궁금한 것이 있어 질문 드립니다.제가 테스트를 제대로 공부해본 적이 없어 혼자서 독학을 하며 공부했던 단위테스트는 주로 Mock과 항상 연관지어 설명이 되어 있었습니다. 통합테스트(@SpringBootTest)는 스프링 컨테이너를 띄우고 bean으로 등록된 모든 빈을 가지고 테스트를 하는 것인데 반해, 단위테스트는 해당 계층(Layer)을 테스트할 때 꼭 필요한 bean만 가지고 와서 최소 단위(메서드나 클래스)로 테스트를 진행한다고 저는 알고 있었습니다.그래서 예를 들어 Service 계층 테스트를 진행할 때면 Repository에 관련된 bean들은 Mockito 등을 사용해서 Mock을 만들고 InjectMocks를 해준다는 식으로 저는 공부를 하고 테스트 코드를 작성한 경험이 있습니다.그런데 오늘 강의에서 강사님이 설명해주시는 내용을 듣다보니 @SpringBootTest 와 같은 어노테이션과 상관없이 단위테스트를 진행하시는 것 같다는 인상을 받았습니다. Order에 대한 테스트를 진행하실 때도 단위테스트라는 언급을 하셨고, OrderSerivice에 대한 테스트를 진행하실 때도 @SpringBootTest를 사용하고 있지만 단위테스트를 하신다고 표현을 하시더라구요.혹시 통합테스트와 단위테스트를 구분하는 강사님만의 방법이 있는 것인지 궁금합니다! 장문 글 읽어주셔서 감사합니다!
-
미해결실전! 스프링 데이터 JPA
@Param의 존재 이유>?
@EntityGraph(attributePaths = "team") List<Member> findEntityGraphByUsername(@Param("username")String username);이번 강의를 복습하다 보니까 강사님께서 @Param을 사용하셨더라구요.(강의 20:59)findByAge(), findOptionalByUsername()과 같은 메소드는 @Param 애노테이션 없이도 잘 동작 했는데 따로 특별한 이유가 있는 것일까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
제공되는 html 파일을 사용해도 될까요?
QueryDSL까지 강의를 다 듣고 난 이후에 게시판이나 쇼핑몰 같은 포트폴리오를 만들기전에 자그맣게 배운걸 써보고 싶은데 html,css,js를 모르다보니 view쪽을 처리할 수가 없더라구요.그래서 혹시 활용1편에 제공되는 HelloShop view단 파일을 사용해도 될지 궁금합니다. 깃허브에 올리려고 하고 백엔드단 코드는 전부 스스로 짤 생각입니다.!
-
미해결실전! 스프링 데이터 JPA
지연로딩과 fetchJoin 성능 차이
즉시로딩을 사용하면 Member 객체를 불러 올 때 1+N문제가 발생하고 Lazy로딩을 사용하면 Team 객체를 사용할 때 쿼리문이 나가서 즉시로딩이든 지연로딩이든 결국 1+N 문제가 생기는 게 맞나요 ? 이 1+N 문제의 해결방법으로 fetchJoin이 나온 것 같은데 지연 로딩, 즉시 로딩보다 무조건 fetchJoin이 이점이 있는 것 아닌가요? 왜 디폴트값으로 지연로딩으로 설정하고 fetchJoin을 선택해서 사용하는지 궁금합니다. 기본적으로 fetchJoin을 사용하고 연관관계에 있는 객체를 사용하지 않을 것 같은 경우에만 지연로딩을 선택적으로 사용하는게 더 편하지 않나요? 사용하지 않는 객체를 가져오는 fetchJoin의 쿼리문 몇 줄이 성능에 그렇게 큰 영향을 미치나요?
-
미해결실전! 스프링 데이터 JPA
2분 정도에 이 코드는 안되는 이유가 있나요?
Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); teamRepository.save(teamA); teamRepository.save(teamB); memberRepository.save(new Member("member1", 10, teamA)); memberRepository.save(new Member("member2", 10, teamB)); 강의에서 이렇게 한번에 하려다가 Member를 생성해주고 따로 save를 해주던데 한번에 하면 안되는 이유가 있을까요 ?
-
미해결실전! 스프링 데이터 JPA
Page 자료구조에 관해 질문입니다.
PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Direction.DESC, "username")); int age = 10; //when Page<Member> page = memberRepository.findByAge(age, pageRequest);PageRequest.of 코드에서 첫 번째 파라미터가 무엇을 의미하는지 헷갈립니다.PageRequest.of 의 2번째 파라미터는 한 페이지의 element 개수이고(limit), 3번째 파라미터는 정렬 조건이 맞나요?List<Member> content = page.getContent(); assertThat(content.size()).isEqualTo(3); assertThat(page.getTotalElements()).isEqualTo(5); assertThat(page.getNumber()).isEqualTo(0); assertThat(page.getTotalPages()).isEqualTo(2); assertThat(page.isFirst()).isTrue(); assertThat(page.hasNext()).isTrue(); page.getContent()는 현재 페이지의 데이터를 가져오는 메소드인가요?page.getNumber()는 현재 페이지를 가져오는 메소드인가요?Page는 책처럼 0,1,2,3 ... 이렇게 페이지가 있는 거고Content는 그 Page안에 있는 데이터를 의미하는 건가요? List<List<data>> 와 같은 구조로 되어 있는 것일까요? Page와 Content의 자료 구조가 어떻게 되어있는지가 궁금합니다.
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
제가 생각하고 있는 동작과정 피드백을 부탁드립니다.
안녕하세요. 선생님 6장 마무리 하는 시점에서 강의와 스스로 DispatcherServlet 소스 코드를 분석하고 그중 핵심적인 것만 크게 정리해봤습니다. 그래서 분석한 내용이 올바른 내용인지, 확실히 하고 싶어서 질문을 드려봅니다!틀린 부분이 있다면 지적해주시면 정말 감사하겠습니다! 0. 스프링 부트 구동 시점에 스프링 컨테이너와 서블릿 컨테이너는 각각이 필요한 기본 빈들을 생성하고, 필요한 초기화 작업과 DI 작업을 수행 1. 클라이언트로부터 URL 호출 시, 서블릿 컨테이너가 request를 파싱하고, HttpServletRequest와 Response 객체를 생성 후, 파싱된 메세지를 HttpServletRequest에 전달함. 이후, 쓰레드가 DispatcherServlet 객체의 service()를 호출(service()는 실제로 부모 클래스에서 오버라이딩 되어 있고 그 내부에서 중요한 메서드인 doDispatch()가 호출됨) 2. 이후 DispatcherServlet은 미리 초기화 해둔 handlerMappings의 handlerMapping 구현 클래스를 순서대로 하나씩 꺼내와서 검사하는데, 1순위인 RequestMappingHandlerMapping 클래스의 조회 전략은 @Controller 클래스 중, 메서드 레벨에 @RequestMapping이 붙어 있고, request의 URL 정보를 토대로 일치하는지 검사. 있다면 해당 핸들러를 반환(컨트롤러) 하지만, 없다면 서블릿 예외를 던지고 애초에 @Controller 자체가 없다면 2순위로 검사 위임하지 않음 3. 해당 핸들러를 getHandlerAdapter()를 통해서 해당 핸들러를 지원하는 어댑터가 있다면 해당 어댑터를 반환하여 HandlerAdapter ha에 할당하고, 지원하는 어댑터가 없는 경우 서블릿 예외를 던짐 4. handlerAdapter의 handler()를 수행하는데 실제 컨트롤러 메서드를 호출하기 전에, 해당 메서드가 필요로 하는 매개변수 정보를 (@RequestBody인지, HttpEntity인지) ArgumentResolver에 제공하고, 각각에 특화된 Http메세지 컨버터를 사용해서 필요한 객체를 생성 5. handlerAdapter가 컨트롤러를 호출해서 로직 수행 6. 컨트롤러가 결과값을 반환 6-1. 메서드 레벨에 @ResponseBody가 붙어있다면 RetrunValueHandler가 HttpMessengerConverter를 이용해서 반환값을 응답 메세지 바디부에 실어서 ViewResolver등을 거치지 않고 즉시 요청 송신자에 반환 6-2. 위의 경우가 아니면, ReturnValueHandler는 반환 값의 타입에 따라 적절한 HttpMessengerConverter를 통해 응답 메세지를 생성 후, ViewResolver가 동작하는데 이는 View 객체를 생성하고 DispatcherServlet가 이를 이용하여 render()하고 최종적으로 클라이언트에게 반환. 감사합니다.
-
미해결실전! 스프링 데이터 JPA
뭘 사용할지 선택에 있어서 질문입니다.
EntityManger를 주입받는 방법으로private final EntityManager em;이렇게 선언하고 @RequiredArgsConstructor로 받을 수도 있고, 이번 강의에서처럼 @PersistenceContext로 받을 수도 있는데 각각의 차이점이 무엇인가요 ? public long count() { return em.createQuery("select count(m) from Member m", Long.class) .getSingleResult(); }또 여기서 메소드 선언문에는 long 타입을 반환타입으로 설정했는데 createQuery의 2번째 파라미터로는 Long값을 주는데 어떤 이유인지 궁금합니다.
-
미해결실전! 스프링 데이터 JPA
@GeneratedValue에 관한 질문입니다.
member = Member(id=3, username=member1, age=10)-> member.getTeam() = Team(id=1, name=teamA)member = Member(id=4, username=member2, age=20)-> member.getTeam() = Team(id=1, name=teamA)member = Member(id=5, username=member3, age=30)-> member.getTeam() = Team(id=2, name=teamB)member = Member(id=6, username=member4, age=40)-> member.getTeam() = Team(id=2, name=teamB) Team을 먼저 persist 했기때문에 team의 id가 1,2가 됐고, 그 뒤에 순차적으로 member의 id가 3,4,5,6이 된 건가요 ? Team은 Team대로, Member는 Member대로 각 엔티티마다 id를 사용하는게 낫지 않나요? 실무에서는 어떤지 궁금하고, 만약 실무에서는 각 엔티티마다 id값을 공유한다면 강의에서는 모든 엔티티가 같은 id값을 공유하는지 궁금합니다.
-
미해결더 자바, 코드를 조작하는 다양한 방법
어노테이션 프로세서 활용 예와 관련해 질문 있습니다.
'마무리' 한 강 남았네요.덕분에 많이 배우고 많이 성장한 것 같습니다.그런데, 어노테이션 프로세서 활용과 관련해서,, QueryDSL 사용 시 생성되는 엔티티의 Q파일도 어노테이션 프로세서를 활용한 기술인지 궁금합니다.짐작으로는 맡긴 한데, 관련 언급이 없었어서요.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
11분 쯤에 프록시 관련하여 질문입니다.
지연 로딩을 사용하면 그 객체를 사용할 때 프록시 객체에서 영속성 컨텍스트에 연결을 요청해서 진짜 객체를 가져오는 거로 알고 있는데요이번에는 단순히 Order만 Return 했기 때문에 Order객체 안에 있는 프록시 객체(Member, Delivery, OrderItems)는 사용할 일이 없는 것 아닌가요 ?왜 프록시 객체를 사용하려다 문제가 발생했는지 알 수 있을까요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
8:41 질문
@PutMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMemberV2( @PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) { memberService.update(id, request.getName()); return new UpdateMemberResponse(id, request.getName()); } 파라미터로 들어온 값으로 UpdateMemberResponse를 만들어주지 않고 memberService.findOne을 통해 하는 이유가 있을까요?
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
변경감지를 통한 데이터 변경에 대해서
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요. 김영한님 JPA강의를 모두 듣고 개인프로젝트를 하던 중에 궁금한 점이 생겨서 질문 올리게 되었습니다.김영한님께서 데이터의 업데이트는 변경감지를 통해서 하는 것이 좋다고 말씀하셨던 게 기억이 나는데요. 물론 변경감지만을 이용하라는 말씀은 아니시겠지만 변경감지를 통한 업데이트를 어디까지 사용해야 하는 가에 대해서 좀 의문이 생겼습니다.예를 들어 이런 경우입니다.회원이 게시판을 조회하면 조회수를 조회수를 증가시키는 로직인데요. (조회수 증가와 게시판 조회를 서로 다른 트랜잭션으로 했음)이럴 때에 변경감지를 통해서 조회수를 증가시킬 경우에 변경감지를 통해 변경된 값이 그대로 update되는 형태를 취하는 것인데, 이럴 경우 요청이 한 번에 많이 들오면 update순서가 보장되지 않아 정확한 조회수 증가가 이뤄지지 않을 것 같았습니다. 하지만 그렇다고 LOCK을 걸자니 조회수 하나 때문에 게시판 조회까지 LOCK이 걸려 조회 속도를 낮추는 것도 문제인 듯 하였습니다. 생각해 보면 이러한 조회수 증가는 쿼리를 UPDATE .. SET column = column +1 이런 식으로 만들고 처리하면 현재 컬럼의 값을 기준으로 1씩 증가하기 때문에 LOCK을 걸 필요도 없고 순서에 상관없이 일관된 값이 보장될 것 같은데 변경감지를 통해 값을 업데이트 하는 방식을 사용하면 현재 조회된 Entity의 조회수 값에 1을 추가하고 그 값으로 직접 UPDATE되는 형태라서 문제가 된 것이 아닐까 싶었습니다.이런 경우 UPDATE쿼리를 따로 날려 주는 방식이 더 효율적인 방식이 맞을까요? 실무에서는 어떤 방식을 취하고 있는 지 궁금합니다..!
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@ModelAttribute 질문
@PostMapping("/members/new") public String create(@Valid @ModelAttribute MemberForm form, BindingResult result) { if (result.hasErrors()) { return "members/createMemberForm"; } Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode()); Member member = new Member(); member.setName(form.getName()); member.setAddress(address); memberService.join(member); return "redirect:/"; }@GetMapping("/members/new") public String createForm(Model model) { return "members/createMemberForm"; }이런식으로 @ModelAttribute를 사용하여 코드를 짜보려고 하니 에러가 나왔고, 아마 html에서 memberForm 객체가 없어서 이용하지 못했고, 결국 매핑에 문제가 생겨 출력(?)을 하지 못해서 그런 것 같은데 예전 스프링 MVC강의에서는 @ModelAttriute를 이용해 코드를 잘 작성했던 거 같은데 왜 이번 강의에서는 사용하지 않았는지 궁금합니다. @PostMapping("/members/new") public String create(@Valid MemberForm form, BindingResult result) { MemberForm이 어떻게 파라미터로 받을 수 있는지 궁금합니다. (이미 Model에 객체가 있으면 파라미터로 받듯이 받을 수 있는 건지?) 위의 코드를 이용해서 웹페이지를 만드려면 createMemberForm.html 에서<form role="form" action="/members/new" th:object="${memberForm}" method="post">이부분 대신 html 파라미터를 넘겨주는 식으로 고쳐야하는 것 일까요? html을 잘 몰라 질문드립니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
OrderService에서는 find 메서드를 만들지 않은 이유가 따로 있나요 ?
ItemService에서는 ItemRepository의 기능을 위임받아 저장 및 검색 기능을 구현했는데OrderService에서는 검색기능을 구현하지 않았더라구요. ItemService에서 위임 받는 것 처럼 하면 간단할 것 같은데 굳이 만들지 않고 OrderRepository의 findOne기능을 사용하는 이유가 따로 있는 것일까요?