묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
강의 자료 오타일까요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용] 이 사진은 김영한 선생님이 강의 영상에서 보여 주신 부분이고, 같은 부분이 6. 스프링 MVC - 기본 기능.pdf(v20231202)의 51 페이지에 있습니다. (아래 사진) RequestResponseBodyMethodProcessor랑 HttpEntityMethodProcessor는 강의 내용에서도 그렇고 제가 코드로 확인해 봤을 때도 클래스였는데, 수정된 강의 자료엔 RequestResponseBodyMethodProcessor(), HttpEntityMethodProcessor() 이런 식으로 메서드처럼 표시되어 있습니다. 저는 이것들이 갑자기 메서드처럼 수정된 이유가 궁금했었는데 혹시 ArgumentResolver 글씨를 지우면서 남겨진 오타일까요? 방금 코드를 보면서 알았는데 ResponseBodyMethodProcessor뿐만 아니라 HttpEntityMethodProcessor도 ArgumentResolver인 동시에 ReturnValueHandler인 것 같더라고요. 혹시 ArgumentResolver 하나에만 해당하는 게 아니기 때문에 지우신 거라면 ArgumentResolver, ReturnValueHandler 둘 다에 해당한다는 내용이 추가되거나, 아니면 괄호가 아예 삭제되는 게 어떨까 싶어서 제보드립니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
hello 페이지로 안들어가집니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]여기에 질문 내용을 남겨주세요.>>> 어노테이션이 저렇게 뜨는데 설정을 바꾸는 방법을 못찾겠어요. >>> 해당 컨트롤러로 못들어갑니다 ㅜㅜ 에러페이지가 나와요
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
@SpringBootTest 에러
[질문 템플릿]1. 강의 내용과 관련된 질문인가요?예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요?예3. 질문 잘하기 메뉴얼을 읽어보셨나요?예[질문 내용]메시지/국제화 파트의 @SpringBootTest를 하는 과정에서 다음과 같은 오류가 납니다.그냥 Junit 단위 테스트는 잘되지만 스프링 부트 테스트에서만 해당 오류가 발생합니다.다른 수강생의 비슷한 질문도 확인하여 해당 질문의 답변에 따라 조치도 취해보았고, 스택오버플로우를 찾아보며 mockito-inline 관련 설정도 해보았음에도 해결되지 않아 질문 올립니다!#콘솔 오류 메시지 # 테스트코드#프로젝트 설정
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
테스트코드에서 스프링빈 자동 등록시 트랜잭션
안녕하세요!제가 기억이 안 나는지 갑자기 궁금해진 부분이 있습니다. aop class=class hello.springtx.apply.TxBasicTest$BasicService$$SpringCGLIB$$0강의대로 하니 정상적으로 Proxy 적용 확인할 수 있었습니다 그런데 갑자기 왜 테스트에서 수동으로 스프링 빈 등록을 했었지...? 라는 생각이 들어서 @SpringBootTest(classes = TxBasicTest.BasicService.class) public class TxBasicTest {@TestConfiguration을 주석처리 후 자동으로 빈을 생성할 클래스(BasicService)를 지정했습니다: aop class=class hello.springtx.apply.TxBasicTest$BasicService Expecting value to be true but was false Expected :true Actual :false다시 실행해보니 프록시가 적용이 안되어있습니다 왜 프록시가 스프링 컨테이너에 등록되지 않은건지 궁금합니다!@SpringBootTest로 해도 테스트코드에서 @Component 적용이 안되는건지 궁금합니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
윈도우 cmd 창에서 gradlew.bat 빌드 success 이후 lib 디렉토리가 생성 안되요
C:\Users\hong_\Desktop\hello-spring1>gradlew.bat> Task :helpWelcome to Gradle 8.5.To run a build, run gradlew <task> ...To see a list of available tasks, run gradlew tasksTo see more detail about a task, run gradlew help --task <task>To see a list of command-line options, run gradlew --helpFor more detail on using Gradle, see https://docs.gradle.org/8.5/userguide/command_line_interface.htmlFor troubleshooting, visit https://help.gradle.orgBUILD SUCCESSFUL in 760ms1 actionable task: 1 executedC:\Users\hong_\Desktop\hello-spring1> cd build C:\Users\hong_\Desktop\hello-spring1\build 디렉터리2024-02-13 오전 10:57 <DIR> .2024-02-13 오전 10:57 <DIR> ..2024-02-13 오전 10:57 <DIR> classes2024-02-13 오전 10:57 <DIR> generated2024-02-13 오전 10:57 <DIR> resources2024-02-13 오전 10:57 <DIR> tmp 0개 파일 0 바이트 6개 디렉터리 366,841,688,064 바이트 남음
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
thymeleaf.org html 영상의 코드와 pdf 2장의 View 코드와 다르네요..
PDF 파일에는 View라는 코드는 아래 코드 밖에 없습니다<html xmlns:th="http://www.thymeleaf.org"><body><p th:text="'hello ' + ${name}">hello! empty</p></body></html> 혹시 10줄 인 영상이랑 같은 코드좀 공유해 주실 수 있으신가요?
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
폼 요청에도 @ModelAttribute 사용하는 이유는 뭔가요?
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]@GetMapping("/login") public String loginForm(@ModelAttribute("loginForm") LoginForm form) { return "login/loginForm"; }로그인 예제에서 로그인 폼 요청을 할때도, @ModelAttribute 로 값을 받는데, 어떤 기능을 하는지 궁금합니다.폼 요청시에는 파라미터 값이 없어서 필요없을것 같아지워보니 오류가 발생합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
이미 존재하는 회원이라고 오류가 뜹니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.전 강의에서 통합테스트할 때는 잘 돌아갔는데 jdbc 템플릿으로 코드를 수정하니 이런 오류가 뜹니다. 코드에는 빨간불이 안 떠요. 문제가 뭘까요?껐다 다시 키고 실행하니 이렇게 뜹니다. integrationtest클래스랑 회원가입, 중복회원예외에 다 빨강느낌표 표시가 뜨고 저런 오류가 떠요.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
th:field, th:value 질문 있습니다
위에서 th:field와 th:value 값이 같다면, 셀렉트 박스의 경우, selected 속성이 활성화된다고 이해했습니다. 애플리케이션 실행 후, 만약 '빠른 배송'이라는 것을 선택하면, thh:field의 값으로 'FAST'가 넘어오게 되고,th:each로 순회되면서 th:value의 값으로 'FAST'을 만났을 때, selected 속성이 활성화되는 것이 맞을까요? 맞다면, 아래와 같은 궁금증이 있습니다.위 과정에서 '빠른 배송' 글자를 클릭했을 때, 어떠한 코드로 인해서 'FAST'가 넘어오게 되는지th:field와 th:value의 값이 String의 equals()와 같은 원리로 동작해서 단순히 똑같은 문자임을 확인하는 것인지th:field와 th:value 값이 각각 어떻게 입력이 되어서 비교가 되는지 (item.deliverCode는 객체이고, deliverCode.code는 String 타입인데 어떻게 비교가 되는지..)장문의 질문 읽어주셔서 감사합니다 (_ _)
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
서블릿 참조 공유 변수에 대한 해결책이 궁금합니다.
스프링 핵심 원리 - 기본편 강의를 듣고 정리한 내용을 다시 보자면, 싱글톤을 기본으로 사용하는 스프링 컨테이너에서는 공유 변수를 방지하기 위해 order() 메서드 안에 지역변수로 값을 설정해야 한다고 나와있습니다. public void order(String name, int price) { System.out.println("name = " + name + " price = " + price); return price; }그런데 JPA 활용편에서는 임베디드 타입일 경우에는 new 생성자로 이를 해결하였고, 정적 팩토리 메서드 방식에서는 createOrder() 안에 new로 인스턴스를 따로 만들어서 객체 값을 관리하는 것으로 배웠습니다. 그렇다면 싱글톤으로 관리되는 서블릿에서도 지역변수 또는 new 생성자를 통한 불변 객체로 참조 변수가 공유되는 것을 막을 수 있나요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
localhost:8080/hello 에러 발생
안녕하세요. localhost:8080/hello 을 실행하면 whitelabelerror 500이 발생 합니다. 경로도 영어로 바꿨고, 코드도 확인했고, 실행 중인지도 확인 했는데 안 됩니다.해결 방법이 궁금합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
MemoryMemberRepositoryTest 실행시 오류
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]package msj9965.project1.repository; import msj9965.project1.domain.Member; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import java.util.List; import static org.assertj.core.api.Assertions.*; class MemoryMemberRepositoryTest { MemoryMemberRepository repository = new MemoryMemberRepository(); @AfterEach public void afterEach(){ repository.clearStore(); } @Test public void save(){ //given Member member = new Member(); member.setName("spring"); //when repository.save(member); //then Member result = repository.findById(member.getId()).get(); assertThat(result).isEqualTo(member); } @Test public void findByName(){ //given Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); //when Member result = repository.findByName("spring1").get(); //then assertThat(result).isEqualTo(member1); } @Test public void findAll(){ //given Member member1 = new Member(); member1.setName("Spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("Spring2"); repository.save(member2); //when List<Member> result = repository.findAll(); //then assertThat(result.size()).isEqualTo(2); } } 위와 같이 MemoryMemberRepositoryTest을 작성했는데 테스트 코드 실행 시 아래와 같은 오류가 뜹니다.Execution failed for task ':test'.> Process 'Gradle Test Executor 14' finished with non-zero exit value 1* 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.> Get more help at https://help.gradle.org.Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.BUILD FAILED in 1s4 actionable tasks: 2 executed, 2 up-to-date
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
테스트를 실행해도 db에 반영이 안되는 것 같습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.처음에 db delete 안 해주고 실행했을 때도 체크 표시가 떴고 delete 해주고 실행, db에서 회원 목록 조회하니 목록에 아무도 없습니다. test가 db에 연결이 안된 걸까요?
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
테스트코드에서 transactionManager() 사용이유
안녕하세요@Bean PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dataSource()); }테스트코드에서 이 로직을 제거해도 작동이 잘 되는데요MemberServiceV3_3 클래스 에서@Transactional 을 사용해서트랜잭션 설정하는 로직이 필요없을것 같았는데위 코드를 사용하신 이유가있으실까요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
h2 데이터베이스 관련
안녕하세요 h2 데이터베이스에 대한 질문이 있습니다. h2 데이터베이스는 "연결" 누르고 sql 실행할 수 있는 창에 들어왔다면 이게 데이터베이스 서버를 띄운건가요?그럼 이 데이터베이스 창을 닫으면 자동으로 데이터베이스 서버를 다운시킨건가요? 그러니까 종료시킨건가요?그럼 spring 실행을 시킬때 항상 이 h2 데이터베이스에 연결해서 접속한다음에 실행해야하는건가요?그리고 현재는 저 한명만이 h2로 테스트하는거니까 그냥 계속 Embedded mode로 접속해도 되는거죠?감사합니다.
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
강의 수강 관련 고민질문 드립니다.
김영한님께서 추천하신 강의 순서는 이미 확인하였습니다. 해당 순서대로 mvc1편 듣고 있습니다.(이해가 완전히 잘 되었던 유일한 http 강의를 제외하고는) 모든 강의가 50%정도의 이해, 50% 정도는 그냥 따라치기에 급급한 느낌이 듭니다. 강의가 온전히 이해되지 않으니, 강의를 듣고 따라치는 과정에서 '나는 절대 저 코드를 혼자서는 못 만들 것 같다'라는 생각이 자연스럽게 듭니다.저는 현재 강의 내용이 이해가 잘 안 되더라도 흐름만 파악하며 일단 끝까지는 들어보자라는 생각으로 강의를 수강하고 있는데요, 이해가 잘 안 되면 오래걸리고 되돌아가면서라도 실시간으로 코드까지 이해를 완전 다 하면서 듣는 방식을 추천하시나요?비슷한 얘기일 수 있지만, 제가 이해가 덜 된 상태로 완강한 강의들을 다시 복습하는게 좋을까요? 결국 나중에는 복습을 하긴 하겠지만, 일단 끝까지 계속 진도를 나가며 모든 로드맵 완강 후 그제서야 다시 복습을 하는게 맞을까요? 아니면 현재 시점까지는 이제 스탑하고 처음 스프링 입문부터 복습을 먼저 한 후에 이어서 진도를 나가는 것이 맞을까요? 추가로, 아직 제가 듣는 강의에서는 내가 저 기술을 유용히 쓸 수 있겠다 라는 생각이 잘 안 들어서 더 힘든 것 같은데, 조금 더 실질적으로 잘 쓰이는 영역의 강의를 먼저 골라들어보고 싶습니다.. '스프링 입문 → 스프링 핵심원리-기본편 → HTTP 기본 지식 → 김영한 스프링 MVC 1편' 까지 수강중인데 추후 바로 '자바 ORM 표준 JPA프로그래밍-기본편 → 실전 스프링 부트와 JPA 활용1 → 실전 스프링 부트와 JPA 활용2' 이렇게 먼저 들어도 될까요? +) 강의를 모두 완강하신 누구든 답변해주시면 감사하겠습니다:)
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
예외 처리 질문드립니다.
[질문 내용]안녕하세요 해당 강의에서 LoginCheckFilter 구현 중에 try - catch 코드에서 질문이 있어서 글을 남깁니다. catch (Exception e) { throw e; // 예외 로깅 가능하지만 , 톰캣까지 예외를 보내주어야 함.}부분이 이해가 가질 않습니다. 톰캣까지 예외를 보내줘야하는 이유를 모르겠네요. 그리고 try 구문 내에서 return으로 다음을 진행하지 않고 끝을 내는 부분도 잘 와닿지 않습니다.제가 예외 처리 부분 개념이 약한 거 같은데, 위에 질문 드린 내용들을 뭐라고 검색하고 공부하면 좋을까요?
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
th:field 에 id부여 방식에 대해서 궁금합니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]먼저 올해도 spring강의 수강생들과 강사님 모두 새해 복 많이 받으시길 기원합니다제가 질문드리고싶은 사항은 th:field=*{regions} 를 통해서 id,name값을 설정하는 부분입니다 addForm에서는 item.regions에 아무런 값이 없는데도 불구하고 id를 th: each 문에 맞춰서 regions1,2,3 를 타임리프가 알아서 단순히 텍스트로 생성해주는 건가요?? addform에서는 분명 데이터가 없을텐데 저렇게 id가 생성되는 이유가 궁금해서 질문 드립니다
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
[체크박스-멀티] 안녕하세요. #ids의 작동 방식에 대한 질문입니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요, 우선 좋은 강의에 감사드립니다.다름이 아니라, 강의를 듣는 도중 멀티 체크박스를 정의하는 과정에서 #ids.prev('regions')부분에서 이해가 되지 않았습니다. th:each를 사용하는 경우 id에 1, 2, 3과 같은 숫자를 붙여 regions1, regions2.. 와 같이 만드는데, 왜 #ids.prev에선 'regions'를 입력으로 넣는지가 이해가 되지 않았습니다.(뿐만 아니라 전체 흐름을 조금 더 명확하게 이해하고 싶었습니다.)구글링을 해봤는데, 해당 강의에 대한 블로그 정리는 많지만 제가 원하는 내용은 찾지를 못했습니다..ㅜㅜ그래서, 이번 기회에 소스코드를 찾아보며 이해를 해보려고 했는데, 아래 작성된 과정이 맞는지, 제가 잘 이해한게 맞는지가 궁금하여 질문 드리게 되었습니다. 너무나도 긴 질문이라 미리 죄송하다는 말씀 드립니다..다음 코드는 SpringInputCheckboxFieldTagProcessor 클래스의 doProcess()와, AbstractSpringFIeldTagProcess 클래스의 computeId() 메서드 입니다.protected void doProcess(ITemplateContext context, IProcessableElementTag tag, AttributeName attributeName, String attributeValue, IThymeleafBindStatus bindStatus, IElementTagStructureHandler structureHandler) { String name = bindStatus.getExpression(); name = name == null ? "" : name; String id = this.computeId(context, tag, name, true); // 이하 생략.. } protected final String computeId(ITemplateContext context, IProcessableElementTag tag, String name, boolean sequence) { // 이전 부분 생략.. if (sequence) { Integer count = context.getIdentifierSequences().getAndIncrementIDSeq(id); return id + count.toString(); } } computeId()를 보면, sequence인 경우(→ 이 경우는 th:each가 들어간 경우라고 추측합니다.) Id에 count를 붙여서 반환하도록 되어있습니다.2.IdentifierSequences 클래스public final class IdentifierSequences { private final Map<String, Integer> idCounts = new HashMap(1, 1.0F); public IdentifierSequences() { } public Integer getAndIncrementIDSeq(String id) { Validate.notNull(id, "ID cannot be null"); Integer count = (Integer)this.idCounts.get(id); if (count == null) { count = 1; } this.idCounts.put(id, count + 1); return count; } public Integer getPreviousIDSeq(String id) { Validate.notNull(id, "ID cannot be null"); Integer count = (Integer)this.idCounts.get(id); if (count == null) { throw new TemplateProcessingException("Cannot obtain previous ID count for ID \\"" + id + "\\""); } else { return count - 1; } } } IdentifierSequences 클래스를 보면, idCounts 라는 Map에 id와 count 정보를 저장하고, 1에서의 computeId()는 getAndIncrementIDSeq() 를 통해 count 정보를 얻어냅니다.이 세부 과정을 생각해보면,처음에 th:field=”*{regions}”를 통해 regions라는 id가 들어가면 IdentifierSequences 클래스의 Map<String, Integer> idCounts 에는 regions라는 id가 없어 getAndIncrementIDSeq() 의 count값은 1이 됩니다.this.idCount.put(id, count + 1); 을 통해 idCounts에는 {”regions” : 2}가 저장되며, getAndIncrementIDSeq()가 반환하는 count값은 1이 됩니다.즉, 처음에 regions라는 id가 들어가면, 이는 <input> 태그에는 regions1이라는 id로 지정되지만 IdentifierSequence의 idCount 맵에는 count가 2로 되어있는 상태입니다.IDs 클래스public class Ids { private final ITemplateContext context; public String prev(Object id) { Validate.notNull(id, "ID cannot be null"); String str = id.toString(); return str + this.context.getIdentifierSequences().getPreviousIDSeq(str); } public Ids(ITemplateContext context) { Validate.notNull(context, "Context cannot be null"); this.context = context; } } 그러면 #ids.prev(’regions’) 를 통해 label이 regions1로 등록되는 과정은 다음과 같이 이해할 수 있을 것 같습니다.prev 메서드는 id를 입력받아, IdentifierSequence 의 getPreviousIDSeq()을 호출하여 얻은 숫자를 뒤에 붙여 label의 id를 지정합니다.이전 문단의 IdentifierSequence의 getPreviousIDSeq() 코드를 보면, idCount에서 얻은 count에 1을 빼서 반환합니다.idCount에는 count가 2로 지정되어 있기에, 최종적으로 #ids.prev(’regions’)의 결과는 regions1이 됩니다.활용 : #ids.next의 사용<label th:for="${#ids.next('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> label과 input 태그의 위치를 바꾸고 #ids.next를 사용하면, 이전과 같이 label의 for와 input의 id를 일치시킬 수 있습니다. 결과는 다음과 같습니다.<!-- multi checkbox --> <div> <div>등록 지역</div> <div class="form-check form-check-inline"> <label for="regions1" class="form-check-label">서울</label> <input type="checkbox" value="SEOUL" class="form-check-input" id="regions1" name="regions"><input type="hidden" name="_regions" value="on"/> </div> <div class="form-check form-check-inline"> <label for="regions2" class="form-check-label">부산</label> <input type="checkbox" value="BUSAN" class="form-check-input" id="regions2" name="regions"><input type="hidden" name="_regions" value="on"/> </div> <div class="form-check form-check-inline"> <label for="regions3" class="form-check-label">제주</label> <input type="checkbox" value="JEJU" class="form-check-input" id="regions3" name="regions"><input type="hidden" name="_regions" value="on"/> </div> </div> 세부 과정을 보면 다음과 같습니다.public String next(Object id) { Validate.notNull(id, "ID cannot be null"); String str = id.toString(); return str + this.context.getIdentifierSequences().getNextIDSeq(str); } next()는 IdentifierSequences의 getNextIDSeq() 를 통해 count 정보를 얻습니다.public Integer getNextIDSeq(String id) { Validate.notNull(id, "ID cannot be null"); Integer count = (Integer)this.idCounts.get(id); if (count == null) { count = 1; } return count; } getNextIDSeq() 를 보면, idCounts에 id가 없는 경우 1을 반환합니다. 즉, 처음에 #ids.next(’regions’)가 입력되면, getNextIDSeq()는 1을 반환하기에 첫 번째 label은 for=’regions1’ 이 됩니다.다음 과정은 2번 문단에 적은 세부 과정과 동일한데, 이전의 #ids.prev에서와 달리 #ids.next는 count에 1을 뺀 값이 아닌 count 그대로를 반환하므로, #ids.prev를 사용할 때와 같이 for와 id가 일치된다고 생각할 수 있습니다.읽어주셔서 감사드립니다. 새해 복 많이 받으세요!(질문 작성일이 설 당일이라.. 겸사겸사 인사드립니다!)
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
Test코드 실행 시 findItems에서 오류 발생합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]7:56에서 하신 테스트를 실행했을 때 강의에서는 정상적으로 동작했지만 저는 오류 발생하며 테스트가 정상적으로 되지 않습니다.오류 로그테스트 코드에서 item3이 무슨 이유인지 모르지만 같이 넘어가서 문제가 되는 것으로 보입니다.왜 이럴까요?