24%
65,180원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
오 이제부터 강의 계속 올라오는건가요?!!
오 이제부터 강의 계속 올라오는건가요?!!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
검증시 변수값이 아니라 상수값으로 비교하는 이유가 있나요?
문제가 발생한건 아니고 단순 질문입니다! 테스트 짜실 때 보면,// 1번 코드 assertEquals("상수값", findComment.getAuthor()); // 2번 코드 assertEquals(addComment.getAuthor, findComment.getAuthor());1번처럼 상수값과 비교를 많이 하시는데, 저는 2번처럼 저장하려고 했던 객체와 실제로 저장된 후 리턴된 객체간의 비교를 많이 하는 것 같습니다. 2번이 유지보수의 측면으로 봤을 때 더 좋아보이는데 1번 스타일로 테스트 코드를 짜는 이유가 있으실까요?
- 해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
로그아웃 기능
안녕하세요 호돌맨님 강의 너무 잘 듣고 있습니다. 다름이 아니라 로그아웃 기능에 대해서 질문이 있습니다.@PostMapping("/auth/logout") public ResponseEntity<Object> logout(UserSession userSession) { ResponseCookie cookie = ResponseCookie.from("SESSION", "") .path("/") .maxAge(0) .build(); return ResponseEntity.ok() .header(HttpHeaders.SET_COOKIE, cookie.toString()) .build(); }현재 컨트롤러만 만들었고 쿠키 maxAge에 0값을 주는 방법으로 로그아웃 되는 건 확인했습니다.궁금한 건 로그아웃 할 때 user가 가지고 있는 session 리스트와 sessionRepository에서session을 지워주는 것이 맞는지 궁금합니다. 만약 지워주는 방식으로 한다며 자동으로 만료되는 쿠키에 session에 대해선 어떻게 처리하나요?
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
Validation Map으로 구현된걸 List로 바꿔봤는데 이 방식이 맞을까요?
이렇게 바꿔봤는데 Body = {"code":"400","message":"잘못된 요청입니다.","validation":[{"fieldName":"content","errorMessage":"내용을 입력해주세요"},{"fieldName":"title","errorMessage":"제목 을 입력해주세요"}]} 이렇게 배열로 응답이 갈수있게 바꿔봤는데 괜찮을까요?
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
안녕하세요!
혹시 시즌3 자료는 받을수 없을까요?!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
SecurityFilterChain 서블릿 매핑 오류 관련...
@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{return http.authorizeHttpRequests().requestMatchers("/auth/login").permitAll() .anyRequest().authenticated() .and().csrf(AbstractHttpConfigurer::disable) .build(); }기존의 강의에 나온 위 코드를 실행하게 되면, This is because there is more than one mappable servlet in your servlet context: {org.springframework.web.servlet.DispatcherServlet=[/], org.h2.server.web.JakartaWebServlet=[/h2-console/*]}.위와 같은 DispatcherServlet과 h2-console의 서블릿이 하나 이상 매핑되어 나는 오류라고 나옵니다.@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception{ http.authorizeHttpRequests((authz) -> { try { authz .requestMatchers(new MvcRequestMatcher(introspector,"/auth/login")).permitAll() //애는 권한 없이도 허용 .anyRequest().authenticated() //나머지는 인증해 .and() //csrf쪽으로는 builder가 이어지지 않기 때문에 and로 이어준다. .csrf(AbstractHttpConfigurer::disable); } catch (Exception e) { throw new RuntimeException(e); } }); return http.build(); }그래서 검색 결과 위와 같이 작성하게 되면 정상적으로 실행되게 됩니다.- 질문제가 코드를 기존에 SecurityFilterChain 외 잘못 작성한 부분이 존재해서 위와 같이 코드를 작성해야 하는 것인지, 아니면 그 사이에 이렇게 작성되도록 변경된 것인지 앞으로도 지속적으로 검색해보겠지만... 현재까진 답을 찾지 못해 질문드립니다.2. h2-console의 경우 데이터베이스 관련 서블릿이고, DispatcherServlet은 웹 애플리케이션의 컨트롤러 역할을 하는 서블릿인걸로 알고 있는데 용도가 다른 두 서블릿의 매핑 혼동이 일어나는 이유가 궁금합니다...*무지한 한 생명체의 질문은 천천히 쾌차하시고 삶의 여유를 되찾으신 다음 답변해주시면 감사하겠습니다!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
@ConfigurationProperties 사용 시 질문 드립니다.
제가 아직 초보 개발자라 막연히 setter 사용은 지양하는게 좋다고 배워서 실무에서는 다른지 궁금합니다.setter 를 열어두면 빈으로 등록된 AppConfig 의 불변성을 보장할 수 없게 되는게 아닌가 해서 질문드립니다.https://mangkyu.tistory.com/189위 블로그를 보면 @ConfigurationProperties 를 setter 없이 생성자로 할 수도 있는것 같아서요.혹시 제가 너무 setter 사용을 지양하라는 말에 매몰돼있는건 아닐까 고민도 되네요.
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
안녕하세요 호돌맨님 예외처리2 에서 질문이 있습니다.
좋은 강의 정말 감사드립니다.호돌맨님 강의덕분에 기존에 공부했던 지식들 정리도 하고 더 좋은 설계가 어떤건지 잘 배우고 있습니다.제가 예외처리2 강의를 보고 컨트롤러 테스트를 하다가 게시글 작성 실패케이스에서 오류가 생겨서 질문드립니다. PostControllerPostCreatePostControllerTest글 작성 요청 시 제목, 내용 모두 null 인 케이스 테스트입니다.이 테스트에서 실패합니다.로그는 아래와 같습니다.응답 바디에도 아무것도 오지 않습니다.로그를 쫓아서 ErrorResponse 에 브레이크 포인트를 찍어봤습니다. ErrorResponse여기서 validation 이 null로 잡힙니다.PostControllerAdvice이쪽 ExceptionHandler 작성할 시점에 생성자에 validation 을 매개변수로 받지 않았을땐 오류가 발생하지 않았는데 validation 을 매개변수로 받고 나서 오류가 생기는거면 @Builder 가 ErrorResponse 의 validation 초기화를 무시하고 null 값으로 생기는 현상 같습니다.그래서 따로 빌더 안붙인 validation 을 받지 않는 생성자를 만드니 잘 돌아갑니다.그런데 강의 마지막에 전체 테스트 한번 돌리고 마무리 하신것 같은데 호돌맨님은 어떻게 테스트 실패가 안뜬건지 궁금합니다. 그리고 혹시 더 좋은 방법이 있는지 방향을 알려주시면 감사하겠습니다.
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
E..dito...r에 대한 질문...
난독증이 있는건지 내용은 그대론데 읽을 때마다 내용이 달라지는 것 같아 질문을 남깁니다...다른 분들이 작성하고, 호돌맨님께서 남기신 답글들을 보고 나서 제가 이해한 것이 맞는지 확인 부탁드립니다... 1. 자판기 비유에 대한 내용1.1. request(edit), domain(editor)를 작성하셨는데, 말씀하시는 부분이 (결국 같은 내용이겠지만...) request(edit)에는 edit.title, edit.content(100원, 500원)(동전)뿐만 아니라 추후에 예를 들어 edit.name, edit.gender(1000원, 10000원)(지폐)가 넘어 올 수도 있는 상황이 발생할 수도 있는데, 지폐(name, gender)는 받고 싶지 않은 상황에서 domain(editor)(금액 투입구)를 사용하지 않으면, 지폐가 들어오는 것을 막을 수 없고, 추후에 불필요한 지폐를 걸러내는 작업이 발생하기 때문에 애초에 입구 자체를 동전만 넣을 수 있는 domain(editor) 금액 투입구를 만들게 되면, 들어온 모든 동전은 사용에 필요한 값이기 때문에 불필요하게 걸러내는 작업이 없어진다고 생각하는 것이 맞을까요...? (같은 말인 것 같은데... 예를 더 어렵게 만든 것 같아 죄송합니다...) 호돌맨님이 if를 통해 기존 값을 사용하는 방식2.1 이 말은 즉, 위 예를 연속해서 사용하자면 [사람 1]이 edit.title(100원)을 넣은 상태에서 [사람 2]가 edit.content(500원)짜리를 넣어도 [사람 2] 때문에 [사람 1]이 넣은 edit.title(100원)이 사라지면 안되기 때문에 사용한다는 말씀이 맞으실까요? (물론 위의 예는 [사람 2]가 edit.title(100원)을 넣게되면 금액이 추가되는 것이 아니라 동전이 변경되야 한다는 오류가 있긴 하지만... 그냥 사용하겠습니다...) 뭔가 작성하면서 또 이해가 된 것 같긴하지만... 틀린 부분이 있다면 지적 부탁드립니다... 또 예를 추가하고 글을 복잡하게 만들어 죄송합니다...
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
WebSecurityCustomizer 와 SecurityFilterChain 차이점에 대해 여쭙고싶어요
@Configuration @EnableWebSecurity(debug = true) // 운용환경에서는 꼭 꺼야한다. public class SecurityConfig { @Bean // Spring Security 무시시키기 public WebSecurityCustomizer webSecurityCustomizer() { return new WebSecurityCustomizer() { @Override public void customize(WebSecurity web) { // /error -> spring에서 기본제공하는 것 web.ignoring().requestMatchers("/favicon.ico", "/error") // .requestMatchers(new AntPathRequestMatcher("/h2-console/**")); // 멍청한 우리들을 위해 스프링이 제공해주신 위으 코드를 대신하는 메서드 .requestMatchers(toH2Console()); } }; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // and() 메서드가 deprecated되어 람다식으로 사용하라고 한다. return http.authorizeHttpRequests(authorizeHttpRequests -> { authorizeHttpRequests .requestMatchers("/auth/login").permitAll() .anyRequest().authenticated(); }).csrf(AbstractHttpConfigurer::disable).build(); } }안녕하세요 호돌맨님 위의 WebSecurityCustomizer에서 하는 일을 밑의 SecurityFilterChain에서도 할 수 있을것 같은데요 둘을 어떻게 사용방법을 구분해야할지 여쭙고 싶어요 30년차사수(ChatGPT) 에 물어보니 차이점:WebSecurityCustomizer는 주로 보안 구성을 조정하고 보안 설정을 사용자 정의하는 데 사용됩니다. 이를 통해 더 세부적인 보안 요구 사항을 처리할 수 있습니다.SecurityFilterChain은 주로 실제 보안 필터 체인을 구성하는 데 사용됩니다. 여러 보안 필터가 어떤 순서로 실행될지를 결정하며, 보안 관련한 요청 처리를 담당합니다.둘 다 Spring Security의 핵심 요소이며 보안 구성과 필터 체인의 다른 측면을 다룹니다. 일반적으로 SecurityFilterChain을 사용하여 필터 체인을 정의하고, 필요에 따라 WebSecurityCustomizer를 사용하여 더 많은 세부 설정을 적용할 수 있습니다.라는데.. 처음 Security를 접하다보니 감이 안잡히네용..
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
[해결완료] 로그인 인증 테스트코드 작성 질문입니다
안녕하세요 호돌맨 선생님!세션토큰 발급기능 추가를 초반에 보다가 로그인 관련 테스트를 직접 작성해보라고 하셔서 해봤는데 궁금한 점이 있어서 질문드립니다!작성한코드@Test @DisplayName("인증 테스트") void test11() throws Exception { // given Member member = Member.builder() .email("abc@naver.com") .password("1234") .build(); // UserRepository를 MemeberRepository로 이름 변경 했습니다. memberRepository.save(member); Login login = Login.builder() .email("abc@naver.com") .password("1234") .build(); String json = objectMapper.writeValueAsString(login); // expected mockMvc.perform(post("/auth/login") .contentType(APPLICATION_JSON) .content(json) ) .andExpect(status().isOk()) .andDo(print()); 결과query did not return a unique result: 2; nested exception is javax.persistence.NonUniqueResultException: query did not return a unique result: 2 원인JPA 에러라는 것을 검색을 통해서 알았습니다해결 방법 블로그 주소 : https://wakestand.tistory.com/943UserRepository에 작성한 findByEmailAndPassWord 메서드가 Optional로 되어 있는데 이 부분을 List로 변경해야할 것 같아서 다음과 같이 변경했습니다 변경된 코드UserRepositorypublic interface MemberRepository extends CrudRepository<Member, Long> { List<Member> findByEmailAndPassword(String email, String password); }AuthService@Service @RequiredArgsConstructor public class AuthService { private final MemberRepository memberRepository; public List<Member> signin(Login login) { List<Member> memberList = Optional.ofNullable(memberRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())) .orElseThrow(() -> new InvalidSign()); return memberList; } } 위 처럼 Optional<Member가 아닌 List<Member>로 변경해서 테스트 로직을 성공하긴했습니다... 질문UserRepository의 Optional<Member>를 변경하지 않고 테스트 코드를 작성하는 방법이 있을까요??Optional에서 List로 변경했을 때 문제점은 없을까요?
- 해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
호돌센세 안녕하세요 auth.http에서 로그인시 자꾸 500 에러가 뜹니다..
https://github.com/incheol789/hodolog.git깃허브에 파일 올려두었습니다..날이 많이 덥습니다.. 더위 조심하세요!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
Count 쿼리 발생에 대해 궁금합니다.
안녕하세요 호돌맨님 ! 질문이 있습니다 !!Pageable 을 사용해서 페이징 구현 시 Full Scan 을 하기 위해 Count 쿼리가 발생하는걸 확인했는데, Pageable 에서는 페이징 처리를 위해 총 데이터의 개수를 파악해야 하기 때문이니까 Count 쿼리가 필요한거고 Querydsl 은 직접 limit 값, offset 값을 지정하기 때문에 Full Scan 할 필요가 없으니 Count 쿼리가 필요없는게 맞을까요 ?
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
Controller Test 시 @WebMvcTest 사용 관련 질문입니다.
안녕하세요 호돌맨님 :) 좋은 강의 늘 감사드립니다.Controller Test 할 때 질문이 있습니다. 강의에서 호돌맨님께서는 @SpringBootTest 사용하셨는데 저는 한 번 @WebMvcTest를 사용해보고 있습니다.그러다보니 문제가 하나 발생을 하더라구요. 우선 PostController 쪽 코드를 보여드리겠습니다.@GetMapping("/posts") public ApiResponse<List<PostResponse>> getAll(@ModelAttribute PostSearch postSearch) { List<PostResponse> posts = postService.getAllPost(postSearch); return ApiResponse.ok(posts); }보시면 게시글을 전체 조회하는 이 메서드의 경우에는 인증이 따로 필요없이 바로 조회가 되게 했는데요. Insomnia 라는 프로그램을 통해서 테스트했을 때 따로 인증하지 않아도 전체 조회 요청이 성공하는 것을 확인했습니다.그런데 테스트코드를 작성할 때 인증 처리를 해주지 않으면 계속해서 401 에러가 발생을 하더라구요.@DisplayName("게시글을 전체 조회한다.") @CustomMockUser //todo 실제로는 인증이 필요없는데도 테스트 통과를 위해서 인증 처리를 해줘야 하는 것인가? @Test void getAllPosts() throws Exception { // given List<Post> posts = IntStream .range(1, 5) .mapToObj(i -> Post.of(FREE, i + "번 제목입니다.", i + "번 내용입니다.")) .toList(); List<PostResponse> response = changePostListToPostResponseList(posts); // when when(postService.getAllPost(any())).thenReturn(response); //then mockMvc.perform( MockMvcRequestBuilders.get("/api/posts") ) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.jsonPath("$.code").value(200)) .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("OK")) .andExpect(MockMvcResultMatchers.jsonPath("$.status").value("OK")) .andExpect(MockMvcResultMatchers.jsonPath("$.data").isArray()) .andExpect(MockMvcResultMatchers.status().isOk()); }@CustomMockUser 어노테이션을 붙여줘야 테스트 통과가 되는 상황입니다. 실제 원하는 기능은 인증없이 전체 조회 되게 하는 것이 목표인데 테스트 통과를 위해서 @CustomMockUser 어노테이션을 붙여주는 것이 올바른 테스트인지 궁금합니다! 혹시 이게 @WebMvcTest와 관련없는 다른 문제라면 알려주시면 한 번 제가 더 찾아보겠습니다..!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
테스트 시행 시 롤백
게시글 조회5-페이징처리(QueryDSL) 강의 내용 이후 전체 테스트를 시행하면 PostControllerTest에서 test5, test6에서 id값을 검증할때에 이전의 테스트에서 PostRepository에 저장이 되어 test5에서는 id값이 30이어야하는데 33이고, test6에서는 30이어야하는데 63으로 이전 테스트 수행 결과가 롤백되지 않아요.BeforeEach랑 Transactional 둘 다 사용해보았는데 테스트가 독립적으로 수행되지 않습니다.찾아보니 sequence는 롤백되지 않는 것이 DB의 기본 규칙이라는데 호돌맨님은 강의에서 전체 테스트를 수행하여도 모든 테스트케이스가 통과되어서 코드에서 어떤 부분이 다른지 궁금합니다.package com.blog.controller; import com.blog.domain.Post; import com.blog.repository.PostRepository; import com.blog.request.PostCreate; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc @Transactional class PostControllerTest { // TODO ObjectMapper 공부하기 @Autowired private ObjectMapper objectMapper; @Autowired private MockMvc mockMvc; @Autowired private PostRepository postRepository; @Test @DisplayName("/posts 요청 시 출력한다.") void test() throws Exception { // given PostCreate request = PostCreate.builder() .title("제목입니다.") .content("내용입니다.") .build(); String json = objectMapper.writeValueAsString(request); // expected mockMvc.perform(post("/posts") .contentType(APPLICATION_JSON) .content(json)) .andExpect(status().isOk()) .andDo(print()); } @Test @DisplayName("/posts 요청 시 title 값은 필수다.") void test2() throws Exception { // given PostCreate request = PostCreate.builder() .content("내용입니다.") .build(); String json = objectMapper.writeValueAsString(request); // expected mockMvc.perform(post("/posts") .contentType(APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("400")) .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) .andExpect(jsonPath("$.validation.title").value("타이틀을 입력해주세요.")) .andDo(print()); } @Test @DisplayName("/posts 요청 시 DB에 값이 저장된다.") void test3() throws Exception { // given PostCreate request = PostCreate.builder() .title("제목입니다.") .content("내용입니다.") .build(); String json = objectMapper.writeValueAsString(request); // when mockMvc.perform(post("/posts") .contentType(APPLICATION_JSON) .content(json)) .andExpect(status().isOk()) .andDo(print()); // then assertEquals(1L, postRepository.count()); Post post = postRepository.findAll().get(0); assertEquals("제목입니다.", post.getTitle()); assertEquals("내용입니다.", post.getContent()); } @Test @DisplayName("글 1개 조회") void test4() throws Exception { // given Post post = Post.builder() .title("123456789012345") .content("bar") .build(); postRepository.save(post); // expected mockMvc.perform(get("/posts/{postId}", post.getId()) .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(post.getId())) .andExpect(jsonPath("$.title").value("1234567890")) .andExpect(jsonPath("$.content").value("bar")) .andDo(print()); } @Test @DisplayName("글 여러개 조회") void test5() throws Exception { // given List<Post> requestPosts = IntStream.range(1, 31) .mapToObj(i -> Post.builder() .title("호돌맨 제목 " + i) .content("반포자이 " + i) .build()) .collect(Collectors.toList()); postRepository.saveAll(requestPosts); // expected mockMvc.perform(get("/posts?page=1&size=10") .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()", is(10))) // .andExpect(jsonPath("$[0].id").value(30)) // sequence는 롤백되지 않음(DB 기본규칙) - mysql 계열이라면 auto_increment로 생성한 값은 commit, rollback 에 상관없이 한번 생성한 값을 그대로 유지합니다. .andExpect(jsonPath("$[0].title").value("호돌맨 제목 30")) .andExpect(jsonPath("$[0].content").value("반포자이 30")) .andDo(print()); } @Test @DisplayName("페이지를 0으로 요청하면 첫 페이지를 가져온다") void test6() throws Exception { // given List<Post> requestPosts = IntStream.range(1, 31) .mapToObj(i -> Post.builder() .title("호돌맨 제목 " + i) .content("반포자이 " + i) .build()) .collect(Collectors.toList()); postRepository.saveAll(requestPosts); // expected mockMvc.perform(get("/posts?page=0&size=10") .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()", is(10))) // .andExpect(jsonPath("$[0].id").value(30)) .andExpect(jsonPath("$[0].title").value("호돌맨 제목 30")) .andExpect(jsonPath("$[0].content").value("반포자이 30")) .andDo(print()); } }
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
AuthControllerTest에서 @BeforeEach
main resources/data.sql로 설정한 파일이 테스트시적용이 되지만 @BeforeEach 메소드 내부의 UserRepository.deleteAll()동작으로 인하여 테스트시 User테이블이 비어있는 것 같습니다.알아낸게 기분좋아서 공유드립니다.호돌님 정말 좋은 강의 만들어주셔서 많이 배우고있습니다.감사합니다!!
- 해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
PostCreate 기본 생성자 문제 질문
질문PostController 에서 "/posts" 요청 시 PostCreate Dto Binding 관련 질문Controller @RequestBody의 Dto는 기본생성자와 Getter or Setter 중 하나가 필요한 것으로 알고 있습니다.[참고 링크][Spring] @RequestBody에 기본생성자만 필요하고 Setter는 필요없는 이유 - 1 (tistory.com)[Spring] @RequestBody에 기본생성자만 필요하고 Setter는 필요없는 이유 - 2 (tistory.com)하지만, 강사님의 코드를 보면,PostCreate (Dto)에 기본생성자가 없음에도 테스트가 정상적으로 통과하는데 어떻게 그것이 가능한가요?제가 따로 코드를 작성하여 시도한 경우, 기본 생성자가 없어서 실패하였습니다. (아래 코드 작성) 완전히 같은 질문https://www.inflearn.com/questions/752002/comment/236088https://www.inflearn.com/questions/796162호돌맨님 답변 → 생성자가 존재하는 경우 생성자를 통해 값이 들어간다.답변에 대한 질문 → 저는 생성자가 존재하더라도 기본생성자가 없으면, 오류가 발생합니다.. 왜 그런걸까요? 강사님 코드기본 생성자가 없음에도 성공@Setter @Getter @ToString public class PostCreate { @NotBlank(message = "타이틀을 입력하세요.") private String title; @NotBlank(message = "콘텐츠를 입력해주세요.") private String content; @Builder public PostCreate(String title, String content) { this.title = title; this.content = content; } } 질문자 코드 :: 실패 케이스강사님 코드와 동일하다고 생각합니다 @Getter @Setter @ToString public class CreatePostRequest { @NotBlank(message = "타이틀을 입력하세요") private String title; @NotBlank(message = "글 내용을 입력하세요") private String content; @Builder private CreatePostRequest(String title, String content) { this.title = title; this.content = content; } } 오류 메세지org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.example.blog.dto.request.CreatePostRequest]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.example.blog.dto.request.CreatePostRequest (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2]※ 컨트롤러에 진입도 못하고 오류 발생합니다.질문자 코드 :: 성공 케이스@NoArgsConstructor 하나 추가 @Getter @Setter @ToString @NoArgsConstructor public class CreatePostRequest { @NotBlank(message = "타이틀을 입력하세요") private String title; @NotBlank(message = "글 내용을 입력하세요") private String content; @Builder private CreatePostRequest(String title, String content) { this.title = title; this.content = content; } }
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
안녕하세요 쿠키 관련 질문이 있습니다
안녕하세요 강의 정말 잘보고있습니다!!쿠키의 수명이 30일인데 만약 토큰의 세션값(UUID)이 탈취된다면 해당방식에선 어떻게 대응할수있을까요?httpOnly나 Secure옵션 등으로인해 현실적으로 탈취는 쉽지않을것이다.. 로만 생각하기엔 뭔가 찝찝한부분이 있는것같은데 제가 놓치고있는부분이 있을까요??또한 호돌님이 생각하시는 해당강의에서 다뤘던 쿠키에 세션토큰을 담아서 인증하는 방식의 단점이 궁금합니다!!
- 미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
세션과 토큰을 이용한 로그인 유지 방식의 차이점
안녕하세요! 강의를 보다가 의문점이 생겨 질문드립니다.크게 아래와 같이 두 가지 질문이 생겼습니다.로그인 유지를 위해 remember-me 토큰을 발급하고 해당 토큰의 유효기간을 (예를 들어) 30일로 설정하여 유저의 세션이 만료되어도 로그인이 풀리지 않게 한다면 단순히 최초에 저장되는 세션의 유효기간을 30일로 늘리는 것과 비교해 보안 측면에서 어떠한 장점을 갖는지 의문이 들었습니다.결론적으로 만약 리프레시 토큰을 사용한다고 하면 리프레시 토큰이 만료되기 전에 이를 갱신할 책임은 클라이언트에게 있는 건가요?? DB를 사용하지 않는 remember-me 방식이라고하면 토큰에서만 expired 관련 정보를 알 수 있을 것이고 그렇다면 클라이언트에서 이를 디코딩하여 남은 유효기간을 확인 후 직접 다시 요청을 하는 식의 처리를 해서 Cookie를 갈아주어야 하는 것인가하는 생각이 들었습니다.먼저 2번의 경우 강의에서의 세션=액세스 토큰, remember-me 토큰=리프레시 토큰이라고 비슷하게 생각할 수 있을 것 같아서 카카오 api 문서를 참고해봤는데,카카오에서는 리프레시 토큰의 유효기간이 1달 이내일 경우 액새스 토큰 갱신 요청을 보낼 때 리프레시 토큰도 같이 갱신하여 보내준다고 하더라구요. (https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#refresh-token)2번의 경우 이렇게 이해하면 되는건지와, 1번에 대해서는 어떻게 생각하시는지 궁금합니다!
- 해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
9:27 에 나오는 부분 찾아봤습니다.
public static MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables) { return MockMvcRequestBuilders.get(urlTemplate, urlVariables) .requestAttr(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate); }위의 코드는 RestDocumentationRequestBuilders의 get()입니다.Spring REST Docs2 - 요청, 응답필드의 9:27에서 하신 말씀 듣고 상속 관계이지 않을까하는 생각이 들었고 궁금해서 들어가보니 상속이 아닌RestDocumentationRequestBuilders의 get()에서 내부적으로 MockMvcRequestBuilders의 get()를 호출해주더라구요.MockMvcRequestBuilders가 추상클래스지만 get()이 static으로 선언되어 있어 상속을 해도 오버라이드를 할 수 없기에 저런 식으로 만들었지 않았을까?라고 추측을 해봤습니다.그러면서 추가적으로 위의 클래스들이 추상클래스로 만들어져 있고 메소드가 전부 static으로 선언되어 있는 것에 대해 이유가 궁금했습니다.추상클래스는 추상 메소드를 선언하고 상속을 하면서 오버라이드를 통한 다형성을 위해 사용한다고 알고 있었는데 여기서는 다른 목적과 방식으로 사용하고 있는 것처럼 보였기 때문입니다.그래서 검색을 해봤지만 키워드를 잘못 선택했는지명확하게 답을 찾지는 못했고, 추상 클래스와스태틱 메소드에 대해 각각 찾아보면서"객체 생성 제한과 메모리 이득 때문인가?"라는 생각이 들더라구요.하지만 추상클래스도 익명객체를 사용하면 객체 생성이 가능해지는 걸로 아는데 그래서인지RestDocumentationRequestBuilders는 생성자도 private으로 선언해 익명 객체로도 생성이 안되게 막아 놨지만 MockMvcRequestBuilders같은 경우는 생성자를 따로 막아 놓지 않아서 익명 객체로 생성이 가능하더라구요. 이렇게 차이를 두는 이유는 뭔가요??그리고 위의 클래스들처럼 선언한 이유도 궁금합니다.