월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
Modelattribute가 react랑 연계해도 작동하는건가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 안녕하세요 수업 너무 잘 듣고 있습니다.다름이아니고 앞의 검증과 관련된 질문입니다. @modelattribute가 form 에서 잘못 입력했을 경우에 사용자로인해 입력된 그 값을 그대로 유지할수 있도록 사용되게 하고싶을때, react와 연계하여 서버를 띄운다고 했을때 json body로 넘겨주지 않고 이 modelattribute를 사용해도 되나요? 강의에서는 클라이언트도 저희가 만들어서 괜찮지만 프론트측을 리액트로 만든다고 했을때 궁금해서 여쭤봤습니다
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
스프링 부트 3.x버전쓰고 강의대로 했는데 NullPointException 나시는분들을 위해
위에 처럼 NullPointerException 나시고 PostMan에 어떠한 것도 호출되지 않거나 기존에 만들었던 Error 500 html 페이지가 뜨시는 분들 강의자료에 있는 2.x 버전대의 javax.~을 복사붙여넣기 하시면 안됩니다스프링부트 3버전대부터 javax가 아닌 jakatra로 바뀌었기 때문에 RequestDispatcher 참고하셔도 좋고 아래에 있는 코드를 복사해서 쓰세요 public static final String ERROR_EXCEPTION = "jakarta.servlet.error.exception"; public static final String ERROR_EXCEPTION_TYPE = "jakarta.servlet.error.exception_type"; public static final String ERROR_MESSAGE = "jakarta.servlet.error.message"; public static final String ERROR_REQUEST_URI = "jakarta.servlet.error.request_uri"; public static final String ERROR_SERVLET_NAME = "jakarta.servlet.error.servlet_name"; public static final String ERROR_STATUS_CODE = "jakarta.servlet.error.status_code";
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
메세지 소스 설정
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.여기서 메세지 소스를 설정한다는 의미가 무엇인지 자세히 모르겠습니다. 예를 들어 example이라고 등록을 하면 example_en.properties example_ko.properties 이렇게 작동한다는 것인가요?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
타임리프 기본기능 강의중에 궁금한것이 있습니다.
==========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]이런질문을 해도될지 모르겠습니다만.타임리프 기본 강의중에 어떠한 리스트를 테스트 하기 위해서addUsers라는 메소드로 리스트를 만들어서 model에 넣어 사용하는데요.저같은경우라면 보통 더미?를 만들때는private List<User> createUserList() { List<User> list = new ArrayList<>(); list.add(new User("UserA",10)); list.add(new User("UserB",20)); list.add(new User("UserC",30)); return list; }이런식으로 만들어서 데이터를 전달하는데영한님은private void addUsers(Model model) { List<User> list = new ArrayList<>(); list.add(new User("UserA",10)); list.add(new User("UserB",20)); list.add(new User("UserC",30)); model.addAttribute("users", list); }이런식으로 메소드에서 리턴하는것이 아닌 모델을 받아 처리하도록 구현하셨더라구요.어떠한 장점이 있어서 이런식으로 구현하신건가요? 아니면 그냥 스타일의 차이일까요 ?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
이미지 보여주기 @ResponseBody
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.downloadImage 메소드 작성할때 위에 @Responsebody사용한 이유가 이미지를 리턴하기 위해서 사용한게 맞나요 ?그리고 다른 방법은 어떤게 있나요 ?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
IDE에서 파라미터 정보 확인
안녕하세요크게 문제는 안되지만 궁금해서 질문 드립니다! 파라미터 확인해보면 이렇게 잘 나올 때가 대부분 인데 이렇게 시멘틱하지 않게 s1, s2, ... 식으로 표현될 때가 있어서IDE 문제나 버전문제일까요? 설정문제일까요? 혹시 알고 계신지 궁금합니다!!
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
로그인유무에 따른 접근에 관한건 Interceptor보다 Filter가 좋을까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요배운 것에서 조금더 응용해서 구글 로그인을 추가하면서 SecurityFilterChain이라는 것을 써보게 됐는데요..Filter니까.. 그러면 구글같은데선 로그인을 Filter에서 처리하는 것 같은데 보통 일반적으로 그럼 로그인은 Filter에서 하는게 맞을까요?검색해보니까 주로 보안과 관련된 일반적인 작업은 Filter, 비즈니스 로직과 관련된 작업은 Interceptor가 낫다고 하더라구요,, 먼가, 강의에서도 그런식으로 말씀하시는 것 같고..그래서 혼자 홈페이지를 만드는 연습을 해보려는데 로그인은 Filter로만 하는걸로 할까 하는데 괜찮을까요? 세부적인 URL패턴설정 같은건 Interceptor가 더 좋다하니까 먼가 Interceptor가 맞나 싶기도 하고 헷갈립니다 @.@
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
@ModelAttribute 관련 static 처리와 th:field 부분 질문드립니다
[질문 내용]안녕하십니까 강의 정말 잘 듣고 있습니다. 두 가지 질문 드리려고 하는데요!5분 50초 경에 @ModelAttribute("regions")public Map<String, String> regions() {Map<String, String> regions = new LinkedHashMap<>();regions.put("SEOUL", "서울");..return regions;} 부분 설명해주시면서 별도의 메서드마다 별도로 처리하는 것보다는 static으로 처리를 하면 더 좋다는 설명을 해주셨습니다. static으로 처리하는 것의 예시가 궁금합니다. 어떻게 처리를 해야할지 감이 잘 안와서요!! ㅎㅎ ㅠ<!-- multi checkbox --> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> th:field="*{regions}" 와 th:value="${region.key}" 의 값을 비교해서 checked 설정을 해준다는 설명 부분이 이해가 잘안갑니다..ㅠ th:field="*{regions}" 를 적용했을 때 id 값과 name값 value값을 편리하게 설정해준다는 개념만 이해가 되는데 사용자가 항목을 체크하면 th:field="*{reigons}" 에 어떤 값들이 들어가는것인지 , 어떻게 비교를 하는 것인지 잘 모르겠습니다... 감사합니다..!
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
request.getAttribute(ERROR_STATUS_CODE) 관련 질문이 있습니다
위 코드에서 result.put에는 ERROR_STATUS_CODE를 그대로 사용하였는데, return문 바로 윗줄에서는 RequestDispatcher.ERROR_STATUS_CODE를 사용하는 이유가 궁금합니다. 둘 사이에 어떤 차이가 있는건가요?감사합니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
properties파일 경로
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요 수강중 질문이 있어 문의남깁니다!스프링부트가 resolver를 자동등록해주고 messages.properties와 error.properties를 읽어서 데이터를 사용하는데 properties파일의 경로를 변경해서 사용하려면 어떻게 해야될까요?현재는 resources/messages.properties 로 사용하는데 resources/item/itemMessages.properties로 사용하고 싶은데 path를 설정하는 방법이 궁금합니다
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
BasicErrorController와 Interceptor로 오류페이지 처리하기
안녕하세요, 스프링 부트에서 인터셉터로 로그인 체크를 하면서 오류 페이지를 보이도록 하는데인터셉터의 excludePathPatterns와 관련하여 질문글을 올립니다. BasicErrorController가 <예외 처리와 오류 페이지> 강의 전반에 걸쳐 했던 작업들을 모두 자동으로 해주기 때문에, 개발자는 오류 페이지만 resources/templates/error/4xx.html 등의 경로에 생성해주면 된다 이해했습니다.이 과정에서 작성할 부분은오류페이지 html로그인 인터셉터 구현 및 WebConfig에 인터셉터 등록, 설정BasicErrorController의 기본 경로인 "/error" 제외하기라고 생각했는데, 실제로 저 부분만 작성하여 컨트롤러에 등록되지 않은 url로 테스트를 해보니인터셉터로 인해 로그인 페이지로 이동됩니다.제가 작성한 WebConfig의 코드는 아래와 같습니다.@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { log.info("addInterceptors 실행"); registry.addInterceptor(new MyInterceptor()) .order(1) .addPathPatterns("/**") .excludePathPatterns("/", "/user/join", "/user/login", "/user/logout", "/css/**", "/*.ico", "/error"); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new LoginUserArgumentResolver()); } } 인터셉터 관련 부분만 주석처리하고 테스트를 해보면 BasicController가 작동을 잘 하여 오류 페이지가 보이는데, 인터셉터의 경로를 제외하는 부분에서 제가 잘못 작성한 부분이 있을까요?그렇지 않다면 제가 놓친 다른 부분이 있을까요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
상품관리 컨트롤러 /주문관리 컨트롤러 예외 객체
안녕하세요. @ExceptionHandler 강의에서 예를 들어주시던 상품을 처리하는 컨트롤러와 주문을 처리하는 컨트롤러에서 발생하는 예외를 다른 응답방식으로 처리하고 싶다면 @Data@AllArgsConstructorpublic class ProductErrorResult {private String productName;private String code;private String message;} @Data@AllArgsConstructorpublic class OrderErrorResult {private int orderNumber;private String code;private String message; } 예를 들면 위와 같은 방식으로 각각 상품과 주문에러 처리를 다른 DTO객체로 만들어서 api json 응답을 하면 되는것일까요?+ 추가로, 또한 @ExceptionHanlder(annotation = ProoductController.class) @ExceptionHandler(annotaion= OrderProduct.class) 각각의 특정 클래스(상품 ,주문 클래스)를 개별적으로 달아주면 한개의 @RestControllerAdvice 에서 "같은 예외도 다른 방식으로 처리" 가 가능한 것이죠?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
form-submit vs location.href (http request 차이점)
밑에 질문에 대한 답변을 통해 location.href 도 server에 http request message를 보낸다는 것을 알게되었습니다. 그럼 이렇게 form 구문과 type=submit 으로 http request 메시지를 보내는 것과<form action="item.html" th:action th:object="${item}" method="post"> ..... <button class="w-100 btn btn-primary btn-lg" type="submit">상품 등록</button> ..... 그냥 location.href를 통해 http request message를 보내는 것과 무슨 차이인가요?? <button class="w-100 btn btn-secondary btn-lg" th:onclick="|location.href='@{/form/items}'|" type="button">취소</button>만약 둘 다 server 한테 새 VIEW를 받아야하는 것이면 그냥 둘 중 하나로 통일해도 되는거 아닌가요? 복습 중인데 이쪽에서 이해가 계속 막히네요
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
사용자별로 세션이 따로 관리되나요?
사용자마다 서로 다른 세션 저장소가 생성되고 관리되는지 궁금합니다. 만약 공유된다면 session 저장소를 삭제하는 과정에서 다른 사용자의 정보도 같이 삭제되어 문제가 발생할 수도 있을 것 같습니다.더 나아가서 HttpSession은 서블릿이 제공하는 기능이라고 하셨는데, 서블릿이 아닌 HttpServletRequest 객체의 getSession 메소드로 세션에 접근하는 이유가 궁금합니다. 세션 저장소가 사용자별로 다르기 때문에 request 객체로 이를 식별하기 위함일까요?//세션 삭제 로직 HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); }LoginControllerV3에서 로그인 성공 처리과정 중에 세션에 값을 저장하고 쿠키에 세션 id를 등록하는 과정이 언제 이루어지는 것인지 궁금합니다. request.getSession으로 세션 저장소를 가져오고 session.setAttribute에서 세션에 loginMember를 저장함과 동시에 쿠키에 LOGIN_MEMBER의 이름으로 세션 id를 등록하는 걸로 이해했는데 올바르게 이해한건가요? @PostMapping("/login") public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request){ if (bindingResult.hasErrors()) { return "login/loginForm"; } Member loginMember = loginService.login(form.getLoginId(), form.getPassword()); log.info("login? {}", loginMember); if (loginMember == null){ bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다."); return "login/loginFrom"; } // 로그인 성공 처리 // 세션 저장소 호출, 없으면 신규 세션 생성 HttpSession session = request.getSession(); // 세션 저장소에 회원 정보 보관 session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember); return "redirect:/"; }감사합니다!
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
자바 17 프로젝트 시작
[질문 내용]안녕하세요 자바 17 프로젝트 시작 관련해서 질문 드립니다.다른 질문글 답변을 보고 따라했는데도 프로젝트 시작이 안됩니다..이유가 뭘까요..
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
requestDto 데이터 바인딩 질문
프론트에서 request를 보내서 RequestDto에 데이터가 바인딩 될 때, List가 안오면 빈array가 바인딩 되도록 하는 것은RequestDto의 생성자에서 해야하나요? 아니면 공통적으로 처리하게 만들 수 있는 건가요? 혹은 빈array라도 프론트에서 보내야하는 건가요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
오류 처리 컨트롤러 직접 접근
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.sendError 나 Exception 발생 시 내부적으로 호출될 컨트롤러 (/error-page/404, /error-page/500) 을브라우저에서 url 을 직접 입력해서도 호출할 수 있는데이러한 접근은 보안 상에 큰 문제가 없을 것 같은데 굳이 막지 않아도 되는 걸까요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
용어가 모호해서 질문드립니다 (Model 객체, Form 객체, Domain 객체, Command 객체)
강의 중 강사께서 Model 객체, Form 객체, Domain 객체, Command 객체를 혼재해서 사용하시는 것 같은데 실제로 같은 대상을 지칭해서 그런가요?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
errors.properties와 검증 애너테이션을 함께 사용할 때 적용되는 메시지
안녕하세요, 수업을 다 듣고 따로 프로젝트를 생성하여에러 메시지를 errors.properties에서 작성한 후 적용 여부를 확인해봤는데적용이 되지 않아 질문드립니다. 프로젝트 환경Spring Boot 3.2.1 / Java 17 / Jar Packaging / IntelliJ IDEA 입니다. 설정 및 작성 코드 application.propertiesspring.messages.basename=messages,errors errors.properties#추가(스프링이 생성한 기본 오류 메시지 코드 설정하기) typeMismatch.java.lang.Integer = 숫자를 입력해주세요!!!!! typeMismatch = 타입 오류입니다!!!! #Bean Validation 추가 NotNull.validation.minVal = 널 안됨!! Range={0}, {2} ~ {1} 허용 Max={0}, 최대 {1} NotNull={0} Null 안됨!!!! 검증 대상 객체@Data @NoArgsConstructor @AllArgsConstructor public class Validation { // @NotNull(message = "값 필수 입력!") // @NotNull(message = "{NotNull}") @NotNull @Min(1) private Integer minVal; @Max(100) private Integer maxVal; @Range(min = 10, max = 100) private Integer rangeVal; } 컨트롤러@Slf4j @RestController public class ValidationController { @GetMapping("/test") public String setValues(@Validated @ModelAttribute Validation validation, BindingResult bindingResult) { log.info("validation={}", validation); if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); for (FieldError fieldError : fieldErrors) { log.info("errorMessage={}", fieldError.getDefaultMessage()); } } return "OK"; } } 위와 같이 작성을 하였고 에러를 발생시켜 보면errorMessage={}의 로그 부분에서 errors.properties에 설정한 메시지가 아니라스프링에서 기본으로 제공하는 오류 메시지가 출력됩니다. 여러가지 테스트 결과application.properties와 errors.properties 자체를 인식하지 못하는 건가 했지만 파일을 인식하는 것을 확인함애너테이션에 메시지를 직접 적용하는 것은 적용이 됨@NotNull(message = "{NotNull}")과 같이 {} 안에 errors.properties에서의 적용 이름?을 직접 넣으면 메시지가 제대로 출력됨 강의에서의 프로젝트와 다른 점이 버전 뿐인 것 같은데,혹시 자바 혹은 스프링 부트의 버전에 따라 검증 애너테이션의 메시지가 적용되는 로직에 차이가 있나요?그게 아니라면 어떤 이유로 이렇게 되는 건지 꼭 이유를 알고 싶습니다. 제가 작성한 부분 중 틀린 부분이나 추가해야 할 부분이 있다면 알려주세요..!여러군데 검색을 해봤지만 원하는 답을 얻을 수 없어 질문 올립니다!
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
모든 itemTypes를 도는건데 왜 BOOK만 정적값으로 적어놓는 건가요?
<div>상품 종류</div> <div th:each="type : ${itemTypes}" class="form-check form-check-inline"> <input type="radio" th:field="*{itemType}" class="form-check-input"> <label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label"> BOOK </label> </div>여기서 thymeleaf 로 Model 객체 내 에 있는 itemTypes 인 enm 배열을 받아서 사용하는거잖아요? 그러면 정적 값들을 하나도 적어놓을 필요가 없는데 왜 BOOK만 적어놓은건가요?