묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
enum에 메세지 때려박기....
안녕하세요. 강좌 잘 보고 있습니다. 덕분에 요새 지식을 쌓는 재미를 알아가고 있습니다.메시지와 국제화 강의를 보다가 타임리프로는 #{} 으로 하면 바로 읽어오는 것을 확인하고, 그럼 자바 코드안에서도 가져올 수 있지 않을까 싶어서, test 코드에서 알려주셨던 방법으로 가져와 봤습니다.option.regions.seoul = 서울 option.regions.busan = 부산 option.regions.jeju = 제주@Slf4j @Controller @RequestMapping("/form/items") @RequiredArgsConstructor public class FormItemController { private final ItemRepository itemRepository; private final MessageSource ms; @ModelAttribute("regions") public Map<String, String> regions( Locale locale ) { Map<String, String> regions = new LinkedHashMap<>(); regions.put("SEOUL", ms.getMessage("option.regions.seoul", null, locale)); regions.put("BUSAN", ms.getMessage("option.regions.busan", null, locale)); regions.put("JEJU", ms.getMessage("option.regions.jeju", null, locale)); return regions; } }이 때에는 정상적으로 가져와지는 것을 확인했습니다.그런데 문제는, ENUM 이었습니다.option.itemType.book = 도서 option.itemType.food = 음식 option.itemType.etc = 기타public enum ItemType { BOOK("도서"), FOOD("음식"), ETC("기타"); private final String description; ItemType(String description) { this.description = description; } public String getDescription() { return description; } }저의 목적은 이렇습니다.Enum의 강점을 유지하면서도, 필드의 description을 국제화 시키고 싶다.하지만 여기서 문제가 발생했습니다. DI를 받기 위해 먼저 Enum을 Bean으로 등록시키기 위해 @Component 키워드를 넣어 시도해보니 컴파일 에러가 터졌습니다. 찾아보니, @Component를 이용해 Bean으로 등록하기 위해선, Enum을 상속받은 Proxy가 만들어져야 하는데, Enum은 상속할 수 없었던게 문제였습니다.그렇다면, MessageSource를 전역으로 설정하거나, 다른 방법으로 이 문제를 해결해야 한다는 건데, 이 부분에 대한 해결책이 마땅히 보이지 않아 질문 남겨봅니다..
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
인터셉터 addInterceptors 가 어디서 호출이 되는건가요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)네2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]여기에 질문 내용을 남겨주세요.package hello.login; import hello.login.web.argumentresolver.LoginMemberArgumentResolver; import hello.login.web.filter.LogFilter; import hello.login.web.filter.LoginCheckFilter; import hello.login.web.interceptor.LogInterceptor; import hello.login.web.interceptor.LoginCheckInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.Filter; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new LoginMemberArgumentResolver()); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .order(1) .addPathPatterns("/**") .excludePathPatterns("/css/**", "/*.ico", "/error"); registry.addInterceptor(new LoginCheckInterceptor()) .order(2) .addPathPatterns("/**") .excludePathPatterns("/", "/members/add", "/login", "/logout", "/css/**", "/*.ico", "/error"); } // @Bean public FilterRegistrationBean logFilter() { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new LogFilter()); filterRegistrationBean.setOrder(1); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } // @Bean public FilterRegistrationBean loginCheckFilter() { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new LoginCheckFilter()); filterRegistrationBean.setOrder(2); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } } Configuration 이 Component이고 ComponentScan 대상이어서 빈으로 등록 된다고 이해하고있었는데@Configuration 이 달려있고 WebMvcConfigurer 상속 받는 상태에서 addInterceptors 메소드를 오버라이드 해주기만 하면 서버구동시 컴파일 과정에서 스캔을하다 @Override addInterceptors 메소드가 있으면 내부적으로 조건에 맞을시 매 uri 호출마다 addInterceptors 를 자동으로 호출하는건가요? 따로 맵핑되어서 uri 같은걸로 호출되는것도 아닌것같은데 어디서 호출이 되는건가요? .addPathPatterns("/**") .excludePathPatterns("/css/**", "/*.ico", "/error");이부분은 이해가 가는데 여태 맵핑된 uri 로 찾아다니는거만 생각하다보니까 이해가 잘안되네요
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
한글 함수 깨짐 현상
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 있는데 해당 글 참고해서 설정 변경했는데 실행 자체가 안됩니다.3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예https://www.inflearn.com/questions/664806/intelli-j-%ED%95%9C%EA%B8%80-%EA%B9%A8%EC%A7%90위의 글 참고해서 설정 변경해 보았지만 첨부한 사진과 같이 실행이 되지 않습니다.스프링 부트 3.0 버전이상이라 jdk 17 버전 사용하고 있는 상황입니다. Execution failed for task ':test'.> There were failing tests. See the report at: file:///D:/인프런/hello-spring/build/reports/tests/test/index.html* Try:> Run with --stacktrace option to get the stack trace.> Run with --info or --debug option to get more log output.> Run with --scan to get full insights.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
템플릿 조각 경로
템플릿 조각의 경로를 지정하는 코드에 의문이 생겨서 질문드립니다.아래 2개의 코드는 실제로 돌려보니 같은 동작을 하는데, <div th:replace="~{template/fragment/footer :: copy}"></div> <div th:replace="~{/template/fragment/footer :: copy}"></div>타임리프엔진이 특정 템플릿 조각을 가져올 때, 템플릿 조각이 어디있는지 찾는 경로는 상대경로나 절대경로 같은 개념이 없는 건가요?
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
session을 model에 등록하지 않아도 되는 이유
타임리프에서 제공하는 기본 객체들을 사용하는 강의에서스프링 부트 3.0 이후로는 ${#request} 등을 지원하지 않기 때문에, model에 직접 addAttribute 해야한다고 하셨는데요.request, response, servletContext는 add 하는데,session은 add하지 않아도 되는 이유가 무엇인가요?
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
타임 리프 Expression Basic Objects 질문
안녕하세요. 강의를 듣던중 궁금한점이 생겨 질문 드립니다.강의에서 basic-objects 템플릿의 결과로위와 같이 나왔었는데,스프링 부트 3.0 이후의 코드로 수정하여 실행하였을 때는,위와 같이 나왔습니다.session 에 해당하는 객체가 달라졌는데, 바뀐 이유가 있나요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
static폴더에 index.html이 실행이 안돼요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.실행엔 문제가 없는데...
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
기댓값 - 406 Not Acceptable 오류
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요.API 예외 처리 - 시작 강의 8:30 경에서 Postman으로 요청을 보낼때, Accept Header를 application/json 으로 설정하고 보내셨는데, HTML 로 응답이 오면 406 Not Acceptable 오류가 발생해야 할 것으로 기대했는데, 서버 내부에서 처리한 예외 오류가 HTML Page로 그대로 반환된 이유가 궁금하여 질문드리게 되었습니다.감사합니다.
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
view resolve할 때 생성된 View에 대한 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]질문 요약:controller에서 viewName을 리턴하고 나서 상황에 대한 궁금증인데요. resolve 후 리턴된 View가 빈인지 빈이면 scope가 어떤지 아니면 단순 개체인지가 궁금합니다. 다음은 제가 문제를 생각하게 된 상황인데요:JSP를 resolve할때 사용하는 InternalResourceViewResolver의 부모인 UrlBasedViewResolver가 있고 resolve한 후 리턴된 View는 스프링 빈이 맞는 것 같은데(UrlBasedViewResolver.applyLifecycleMethods()에서 빈 lifecycle method를 실행하는 것으로 미루어 추측. 실제 applicationContext에 빈 등록하는 코드는 찾지 못했습니다.)그러면 /WEB-INF/file1.jsp /WEB-INF/file2.jsp 두개의 파일이 있고 각각 "file1", "file2"를 리턴하는 controller가 있어서 한 번씩 요청 됐을 때 반환되는 View는 빈인지 빈이면 scope이 어떻게 되는지 궁금합니다.구체적으로:View가 다른이름 싱글턴 빈으로 두개가 생기고 계속 재활용 되는건가요 (가령 file1, file2라는 이름으로 각각 빈이 생기고 BeanNameViewResolver를 써서 재활용 한다든지)아니면 request scoped 빈으로 그때마다 만들어지는건가요아니면 InternalResourceView를 클래스로 갖는 싱글턴 빈 한개만 생기고 resolve 요청 올때마다 setUrl()로 url을 달리해서 넘기는 걸까요(이건 동시성 문제 같은게 있을 것 같습니다)그것도 아니면 반환된 View는 빈이 아닌 단순 개체일까요(빈을 찾아보니 viewResolver나 viewNameTranslator는 있어도 view라고 끝나는 빈이 안 나오긴 했습니다. 스프링 Api doc을 봐도 UrlBasedViewResolver에 보면 createView(), instantiateView(), applyLifecycleMethods() 설명에도 view instance를 반환한다고 만 되어있고 View가 빈이란 언급은 없긴하네요)
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
findByName만 오류가 뜨는데 이유를 모르겠습니다..
==============================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]다른거는 다 잘되는데 findByName만 오류가 뜨는데 이유를 모르겠습니다..
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
'new-form' 404 에러 관련 질문
코드 복사 붙이기도 해보고 재작성도 여러번 했는데서블릿 MVC 회원목록만 계속 오류가 납니다..어떤 점이 문제인지 모르겠습니다..
-
미해결스프링 프레임워크는 내 손에 [스프2탄]
안녕하세요 강의를 듣던중에 카카오 지도 api에서 계속 오류가 발생하여 질문을 드립니다
자바스크립트키는 일치하는거같은데 계속 오류2개가 발생하네요 제아이피주소하고 입력한 아이피주소네요
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
configureHandlerExceptionResolvers을쓰면 안되는이유
왜 스프링이 제공하는 ExceptionResolver가 없어지면안되는건가요?없어지면어떻게되는거죠?
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
th:onclick 질문
th:onclick="|location.href='@{/basic/items/{itemId}(itemId=${item.id})}'|" 을 간결하게 하고 싶어서 th:onclick="|location.href='@{/basic/items/${item.id}}'|"이렇게 해봤는데 400에러가 뜨더라구요 onclick은 간결 표현식이 안되나요?
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
43강에서 id가 갑자기 사라졌는데요
분명히 성별의 id가 18분 전까지는 있었는데 갑자기 사라져서요 id를 제거해준 이유가 무엇인가요?
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
서로 다른 프로젝트의 welcome page
안녕하세요 mvc 2편 코드를 따라하며 프로젝트를 실행시키고 확인하다가,mvc 1편에 특정 부분을 확인하고자 1편에서 썼던 프로젝트를 실행시켰습니다 분명 2편 프로젝트를 실행중지하고, 1편 프로젝트를 실행했는데localhost:8080 을 통해 나온 welcome page가 2편 프로젝트의 index.html 입니다왜 1편 프로젝트의 index.html이 welcome page로 뜨지 않는 것일까요? 감사합니다!
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
build 생성 오류 문의드립니다.
안녕하세요 아래 링크의 문의글과 같은 상황이라 문의드립니다.build 생성 오류 질문드립니다...(윈도우)https://www.inflearn.com/questions/268449/build-%EC%83%9D%EC%84%B1-%EC%98%A4%EB%A5%98-%EC%A7%88%EB%AC%B8%EB%93%9C%EB%A6%BD%EB%8B%88%EB%8B%A4-%EC%9C%88%EB%8F%84%EC%9A%B0 인텔리제이에서는 정상적으로 컴파일 되는 상태입니다.인텔리제이를 종료 한 상태에서 CMD를 통해 gradle을 build하면 아래와 같은 오류 메세지가 나오는 상태입니다.댓글에 안내해주신 대로 프로젝트를 새로 생성 후 바로 CMD에서 컴파일을 했는데도 오류 메세지가 동일해서 문의드립니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
스프링부트 정적파일 관리는 그래들에만 해당되는것이 맞나요?
==============================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]스프링 부트에서 정적 파일 관리를 제공하는 것이 그래들, 메이븐 모두에게 해당되는 개념인지 아니면 그래들에만 해당되는 얘기인지 궁금합니다.메이븐 방식일 경우 webapp 하위에 resources와 WEB-INF로 나뉘는데 정적파일이 resources에 저장되는걸로 알고있습니다.스프링프레임워크에서는 뷰리졸버의 prefix가 기본적으로 /WEB-INF/views/ 이렇게 세팅해두고 하는것으로 알고있거든요...
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
DI 이해도 확인
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 아니오3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]제가 DI를 제대로 이해한 것인지 확인 부탁드려도 될까요?MemberService클래스와 MemberServiceTest클래스의 멤버변수인 MemoryMemberRepository 객체가 다른 객체일 가능성이 있습니다. 각각의 두 클래스에서 굳이 동일한(총 2개) MemoryMemberRepository객체를 만들 필요는 없습니다. 왜냐하면 두 객체가 다른 객체일 가능성도 있고 목적상 다른 객체이어야 할 이유가 전혀 없기 때문입니다. 이러한 문제를 개선하기 위해 DI가 필요합니다. DI를 하는 방법은 다음과 같습니다. MemberService클래스에서 멤버변수에MemoryMemberRepository 객체를 생성하지 않고 참조변수만을 선언합니다. 생성자를 만들어 MemoryMemberRepository 객체를 주입받고 그 객체를 멤버변수 MemoryMemberRepository로서 사용하도록 합니다. MemberServiceTest클래스에서 MemberService 생성자를 사용하여 MemberService 객체를 생성하는데 이 때, 생성자의 인자에 MemoryMemberRepository 객체를 생성해 주입합니다. MemberService클래스에서 생성자를 만들었고 생성자의 인자로 MemoryMemberRepository 객체를 주입받고 그 객체를 멤버변수로 사용하기로 했다는 것을 잊지말아야 합니다. 이것이 핵심입니다. 물론 14분대 강의영상에서는 MemberServiceTest클래스에서 MemberService의 각 메서드들이 테스트되기 전 매번 MemberService 객체가 만들어져야 하므로 beforeEach() 메서드 안에서 구현이 되었을 뿐, DI의 원리는 지금까지 설명한 바와 동일합니다.
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
12분대 memberRepository 참조변수 이름 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]MemberService에서 아직 어떤 DB를 사용할지 모르니 참조타입을 MemberRepository로 하고생성자를 MemoryMemberRepository를 한 것은 이해가 갔습니다. 다형성을 위해서 그러신 것이죠.private final MemberRepository memberRepository = new MemoryMemberRepository(); 근데 강의영상 12:00부터의도치 않은 Member객체를 가르킬 수 있으니 MemberServiceTest에서 멤버변수 AfterEach()를 새로 만들어 리포지토리를 지우기 위해 MemoryMemberRepository의 clearStore()를 가져와야 했습니다.그래서 MemberServiceTest 16라인에MemoryMemberRepository memberRepository = new MemoryMemberRepository();이렇게 작성하셨습니다. 근데 제가 생각했을 때 참조타입도 MemoryMemberRepository 이고 생성자도 MemoryMemberRepository인데 어째서 참조변수의 이름은 memberRepository 인건지 궁금합니다. 귀한 시간 내주셔서 제 질문 읽어주셔서 감사합니다.