월 19,800원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨토비의 스프링 부트 - 이해와 원리
섹션 3 모든 강의가 재생이 안됩니다
다른 섹션은 재생이 되는데 무한로딩이 뜨면서 재생이 안되네요..ㅜㅜ새로고침, 강력새로고침 모두 해결이 안됩니다어떻게 해야하나요?
- 미해결토비의 스프링 부트 - 이해와 원리
어노테이션매핑정보 - 404 오류 문의드립니다
안녕하세요. 어노테이션 매핑정보 사용 강의 보고 궁금한점이 생겨 문의 남겼습니다.지금까지 강의에 나온것과 똑같이 코드를 작성했습니다. 그런데 실행하면 예상했던 값이 나오지 않고 404 오류가 떠요.실행창에는 아래와 같은 메세지가 나옵니다.16:09:26.879 [http-nio-8080-exec-1] WARN org.springframework.web.servlet.PageNotFound -- No mapping for GET /hello16:09:26.886 [http-nio-8080-exec-1] WARN org.springframework.web.servlet.PageNotFound -- No endpoint GET /hello. 그래서 HelloController 클래스위에 @RequestMapping을 지우고 대신 @Controller을 추가해봤더니 그제서야 강의와 같은 결과가 나옵니다.제 스프링 버전은 3.x, jdk17인데 이것과 관련이 있을까요? 같은 코드인데 왜 저는 404가 나오는지 궁금합니다...
- 미해결토비의 스프링 부트 - 이해와 원리
@JdbcTest 관련 질문
안녕하세요. 섹션 10. 스프링 부트 자세히 살펴보기에서스프링 부트의 자동 구성과 테스트로 전환하는 부분 보다가 궁금증이 생겨서 질문남깁니다. @HellobootTest를 @JdbcTest 또는 @SpringBootTest로 전환하는 부분에서 @JdbcTest같은 경우는 내장된 테스트용 db로 교체를 한다. 라고 설명을 해주셨습니다. 그리고 이전 강의에서 테스트를 위해 인메모리 db인 h2를 사용하도록 application.properties에 설정을 하고 테스트를 진행했었습니다. 여기서 질문은 @JdbcTest를 사용하면 교체된다고 하는 db가 기존에 사용했던 h2 DB가 아닌 또 다른 DB로 전환된다는 말씀인건지가 헷갈려서 질문드립니다. 구체적으로 JdbcTemplateTest class가 jdbcTemplate을 테스트하기 위해 hello table을 db에 생성하고 insert하는 작업을 할 때, @HellobootTest 일 때는 h2 db를 사용하고 @JdbcTest로 교체했을 때는 다른 embedded db를 사용하는건가요? 감사합니다!
- 해결됨토비의 스프링 부트 - 이해와 원리
스프링 부트 2.x 버전 지원 중단
안녕하세요! 최근에 강의를 수강하게 된 학생입니다.다름이 아니라 강의에서 말씀해주신 SpringBoot 2.7.6 버전을 설치하려고 하는데 start.spring.io에는 3.x버전들 밖에 보이지 않더라고요. 그래서 spring-cli를 사용해서 설치하려고 했으나 Initializr service call failed using 'https://start.spring.io' - service returned Bad Request: 'Invalid Spring Boot version '2.7.6', Spring Boot compatibility range is >=3.1.0'라는 문구와 함께 설치가 되지 않아 공식 깃허브를 찾아보았더니 2.x 버전에 대해서는 지원이 중단되었다고 적혀있었습니다.https://github.com/spring-io/start.spring.io/issues/1357Commercial support에 대해서는 25년까지 가능하다고 되어있는데, Commercial support(유료 지원?)이라는 것이 정확하게 어떤 것인지 이해가 잘 되지 않습니다. 그렇기에 Commercial support와 SpringBoot 3.1.6 버전을 설치하는 것 둘 중에 어떤 것이 더 나을지 질문드립니다ㅠㅠ 감사합니다!
- 미해결토비의 스프링 부트 - 이해와 원리
Environment Abstraction 의 우선순위
섹션8의 Environment 추상화와 프로퍼티 제목의 강의의 막바지 부분에서 Environment Abstraction 의 우선순위에 대한 내용이 나옵니다. 강의 내용을 요약해보자면 ServletConfig Parameter < ServletContext Parameters < JNDI < System Properties < System Environment Variables < @PropertySource < application.properties, xml, yml 대로 오른쪽으로 갈 수록 우선순위가 높다라고 이해를 했습니다. 우선 저는 System Properties가 jvm 옵션을 말하는건가? 라는 생각을 가지고 들었고 그렇게 생각하고 위의 내용을 보니 jvm option의 우선순위가 os의 환경 변수보다 높아야 되는거 아닌가? 라는 궁금증이 생겼습니다. 제목 그대로 우선순위에 대한 내용에 오류는 없는것인지 궁금합니다.++ 질문 수정"자동 구성에 Environment 프로퍼티 적용" 강의를 들어보니 우선순위를 제가 반대로 이해한것 같습니다. 여기서 추가적으로 궁금증이 생겼습니다.저는 application level의 설정이 더 우선해야 되는 것 아닌가? 라는 생각에application property > jvm property > os level property 라고 생각을 했습니다. 하지만 스프링에서는jvm property > os level property > application property의 우선순위를 가지게 한 것 같은데 그 이유가 무엇일까요?이것에 대한 생각이 어떠신지 궁금합니다.그리고 우선순위의 변경을 원한다면 바꿀 수 있도록 스프링이 제공하는지도 궁금합니다! 감사합니다.=======================제가 강의 내용을 끝까지 안듣고 궁금한것을 적었는데..질문을 남기고 나머지 강의를 들어보니 궁금했던 내용이 해소가 됐네요. 자문 자답하자면, application의 설정을 default로 하되, 어떤 환경에서 어떤 사용자가 사용하냐에 따라 설정이 달라질 수 있어야 하기 때문에 jvm, os level의 property보다 우선순위가 낮아야 할 것입니다. 이왕 글을 남긴거 삭제하기 뭐해서 남겨두겠습니다.
- 미해결토비의 스프링 부트 - 이해와 원리
proxyBeanMethods=false 와 관련해서 질문이 있습니다.
proxyBeanMethods=false 을 사용하면 Bean 오브젝트가 싱글톤 빈처럼 같은 오브젝트가 리턴되는 것이 아니라 매번 새로운 오브젝트가 생성된다고 하셨는데 이렇게 굳이 새로운 오브젝트를 매번 생성하는 이유가 있을까요?새로운 오브젝트를 생성하는 비용보다 프록시 생성을 해서 싱글톤 방식으로 같은 오브젝트를 리턴하는 비용이 더 크기 때문일까요?왜 그렇게 설정을 하는 것인지 궁금합니다.
- 해결됨토비의 스프링 부트 - 이해와 원리
@Configuration 과 @ComponentScan
@Configuration @ComponentScan public class HelloApplication { public static void main(String[] args) { AnnotationConfigServletWebApplicationContext applicationContext = new AnnotationConfigServletWebApplicationContext(){ @Override protected void onRefresh() { super.onRefresh(); ServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory(); WebServer webServer = webServerFactory.getWebServer( servletContext -> { servletContext.addServlet("dispatcherServlet", new DispatcherServlet(this) ).addMapping("/*"); } ); webServer.start(); } }; // applicationContext.register(HelloController.class); // applicationContext.register(SimpleHelloService.class); applicationContext.register(HelloApplication.class); applicationContext.refresh(); } }강사님 안녕하세요, 강의를 복습하다보니 @ComponentScan을 사용할 때 @Configuration이 필요한지 의문이 들더라구요 처음에 @Configuration javaDoc를 보면 @ConponentScan 부분에 @Configuration 클래스는 구성 요소 스캐닝(component scanning)을 통해 부트스트랩될 뿐만 아니라, @ComponentScan 주석을 사용하여 스스로 구성 요소 스캐닝을 설정할 수도 있습니다.라고 작성이 되었더라구요 @ComponentScan public class HelloApplication {}이 상태로 register에 등록을 해도 컴포넌트 스캔이 동작합니다. Creating shared instance of singleton bean 'helloApplication' Creating shared instance of singleton bean 'helloController' Creating shared instance of singleton bean 'simpleHelloService'@Configuration이 없어도 직접 register에 등록하면 애노테이션을 읽어서 컴포넌트 스캔이 동작합니다. 그러면 register에 @Configuration을 붙이지 않고 직접 등록한다면 @ComponentScan만 있어도 되는데 붙이는 이유가 궁금합니다.
- 미해결토비의 스프링 부트 - 이해와 원리
스프링 로그인 제어 문의드립니다
안녕하세요 토비님제가 테더링이 제한되서 부득이 하게첨부이미지로 질문드립니다수고하세요,,
- 해결됨토비의 스프링 부트 - 이해와 원리
DataSourceConfig에서 @EnableTransactionManagement를 사용하면 DataSourceTest가 안 되는것에 대한 질문이 있습니다.
안녕하세요 토비님. 강의 정말 잘 듣고있습니다! JdbcTemplate과 트랜잭션 매니저 구성 강의를 듣다가 @EnableTransactionManagement으로 트랜잭션(tx) 관리 기능을 열어주고 기존 DataSourceTest.java 예제를 실행하니 java.lang.IllegalStateException: Failed to unwrap proxied object 에러가 계속 발생합니다.DataSourceConfig.java에서 @EnableTransactionManagement 애노테이션을 제외를 하면 DataSourceTest.java 테스트가 정상적으로 잘 돌아가더라고요...음 java와 spring 버전, 라이브러리는 모두 동일하게 설정을 했습니다. 제 소스 코드는 하단에 있습니다! 버전 문제로 해당 예제가 안 돌아가는 것인지? 왜 안 되는지 궁금합니다.. 바쁘실텐데 이유나 원인을 아시면 알려주시면 감사하겠습니다. 에러코드java.lang.IllegalStateException: Failed to unwrap proxied object at org.springframework.test.util.AopTestUtils.getUltimateTargetObject(AopTestUtils.java:105) at org.springframework.boot.test.mock.mockito.SpringBootMockResolver.resolve(SpringBootMockResolver.java:35) at org.mockito.internal.util.MockUtil.resolve(MockUtil.java:118) at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:108) at org.mockito.internal.util.DefaultMockingDetails.isMock(DefaultMockingDetails.java:32) at org.springframework.boot.test.mock.mockito.MockReset.get(MockReset.java:106) at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:82) at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:70) at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.beforeTestMethod(ResetMocksTestExecutionListener.java:57) at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:293) build.gradleplugins { id 'java' id 'org.springframework.boot' version '2.7.6' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'tobyspring' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '11' } repositories { mavenCentral() maven { url 'https://repo.clojars.org' name 'Clojars' } } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework:spring-jdbc' implementation 'hikari-cp:hikari-cp:3.0.1' runtimeOnly('com.h2database:h2:2.1.214') // spring-boot-starter-undertow // implementation 'org.springframework.boot:spring-boot-starter-jetty' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() } DataSourceTest package tobyspring.helloboot; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; @HellobootTest public class DataSourceTest { @Autowired DataSource dataSource; @Test public void connect() throws SQLException { Connection connection = dataSource.getConnection(); connection.close(); } } HelloBootTestpackage tobyspring.helloboot; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = HellobootApplication.class) @TestPropertySource("classpath:/application.properties") @Transactional public @interface HellobootTest { } DataSourceConfig.javapackage tobyspring.config.autoconfig.datasource; import com.zaxxer.hikari.HikariDataSource; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import tobyspring.config.ConditionalMyOnClass; import tobyspring.config.MyAutoConfiguration; import tobyspring.config.autoconfig.EnableMyConfigurationProperties; import javax.sql.DataSource; import java.sql.Driver; @MyAutoConfiguration @ConditionalMyOnClass("org.springframework.jdbc.core.JdbcOperations") @EnableMyConfigurationProperties(MyDataSourceProperties.class) @EnableTransactionManagement public class DataSourceConfig { @Bean @ConditionalMyOnClass("com.zaxxer.hikari.HikariDataSource") @ConditionalOnMissingBean DataSource hikariDataSource(MyDataSourceProperties properties) { HikariDataSource dataSource = new HikariDataSource(); dataSource.setDriverClassName(properties.getDriverClassName()); dataSource.setJdbcUrl(properties.getUrl()); dataSource.setUsername(properties.getUsername()); dataSource.setPassword(properties.getPassword()); return dataSource; } @Bean @ConditionalOnMissingBean DataSource dataSource(MyDataSourceProperties properties) throws ClassNotFoundException { SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); dataSource.setDriverClass((Class<? extends Driver>) Class.forName(properties.getDriverClassName())); dataSource.setUrl(properties.getUrl()); dataSource.setUsername(properties.getUsername()); dataSource.setPassword(properties.getPassword()); return dataSource; } @Bean @ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnMissingBean JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean @ConditionalOnSingleCandidate(DataSource.class) @ConditionalOnMissingBean JdbcTransactionManager jdbcTransactionManager(DataSource dataSource) { return new JdbcTransactionManager(dataSource); } }
- 미해결토비의 스프링 부트 - 이해와 원리
스프링부트 내장톰캣이 아닌 별도 웹서버 설치 가능 여부 문의
스프링부트 내장톰캣이 아닌 별도 웹서버 설치 가능 여부 문의 토비님 안녕하세요~여전히 공공기관 프로젝트 참여중입니다관리하시는 총괄 PL 께서 혹시 스프링부트 사용하면서 내장톰캣이아닌 다른 웹서버를 설치 해서 사용 가능한지를물어보시더라구요내장톰캣이 아닌 웹로직이던, 다른제품을 두고웹로그분석기나 다른 솔루션을 같이 웹서버에언져서 사용하고 싶은가 보더라구요 1.이게 가능한지 문의 드립니다. 만약 가능하다면 제가 구글링이나, 스프링문서에서 어느 부분을 찾아 보면 될까요? 2.실전에서 내장톰캣이 아닌 별도 웹서버 설치해서 연동하는 이유는 어떤것 들이 있는지도 궁금하네요급한부분 아니니 한가 하실때 알려주시면 감사하겠습니다. 수고하세요김동희 드림
- 미해결토비의 스프링 부트 - 이해와 원리
imports확장자 인식이 안됩니다. ㅜㅜ
이거 저만 그럴까요..? ㅜㅜ 하위 디렉토리도 맞습니다.
- 해결됨토비의 스프링 부트 - 이해와 원리
url만 희한하게 null이 나옵니다..
테스트 실패해서 디버깅 돌리는데,이상하게 다른 거 다 잘 들어오는 거 같은데 url만 null이 찍히네요.. 원인이 무엇인지 모르겠습니다.. DataSourceTest의 connect() 메소드입니다.
- 해결됨토비의 스프링 부트 - 이해와 원리
학습 테스트 중 스프링 컨테이너 관련 질문이 있습니다.
우선 강의 정말 잘 보고 있습니다. 토비님.일단 굉장히 초보적인 질문을 드리는 것 같아서 죄송스럽지만 자꾸 뭔가 하나 모자란 느낌이 자꾸 들어서 질문드립니다.계속 강의를 보면서 서블릿 컨테이너를 띄우고 스프링 컨테이너도 띄우고 이 과정을 리팩토링해서 스프링 컨테이너만 띄운 뒤 서블릿 컨테이너와 디스패쳐 서블릿의 팩토리 메소드를 빈으로 바꾸는 과정까지 학습했습니다. 그런데 이번 강의에서 나오는 학습 테스트를 보면 별다른 빈을 등록하지 않으시고 스프링 컨테이너만 띄우셔서 커스텀 빈을 테스트하시는 것 같아 보였습니다. 여기서 궁금한 점이 스프링 컨테이너에 빈이 등록되고 라이프사이클이 끝나는 과정까지 서블릿 컨테이너를 아예 의존하지 않는게 맞나요? 사실 웹 프로덕트 코드를 구현하는 과정에선 반드시 서블릿 컨테이너가 있어야 파싱이 되기 때문에 실무에선 무쓸모일 고민 같지만 스프링 컨테이너가 얼마나 독립적으로 실행될 수 있는지 알면 좋을 것 같아서요...
- 미해결토비의 스프링 부트 - 이해와 원리
MydataSourceProperties를 작성하고 DataSourceConfig를 작성하는 도중 에러가 발생했습니다.
자동 배선을 할 수 없습니다. 'MyDataSourceProperties' 유형의 빈을 찾을 수 없습니다. 라는 에러가 나오는데 해결을 못 하고 있습니다. @MyConfigurationProperties(prefix = "data") public class MyDataSourceProperties { private String driverClassName; private String url; private String username; private String password; public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }tobyspring.config.autoconfig.TomcatWebServerConfig tobyspring.config.autoconfig.JettyWebServerConfig tobyspring.config.autoconfig.DispatcherSetvletConfig tobyspring.config.autoconfig.PropertyPlaceholderConfig tobyspring.config.autoconfig.PropertiesPostProcessorConfig tobyspring.config.autoconfig.DataSourceConfigdependencies { implementation('org.springframework.boot:spring-boot-starter-web') implementation('org.springframework:spring-jdbc') testImplementation 'org.springframework.boot:spring-boot-starter-test' }어디가 문제인지 안보이네요...
- 미해결토비의 스프링 부트 - 이해와 원리
스프링 spring get/post 보안 관련 문의 드립니다
스프링 spring 보안 관련 문의 드립니다 토비님 안녕하세요 ~여전히 공공기관 프로젝트에 참여 중 인데요스프링 보안 관련 해서 문의 드립니다현재 기 구축되어 있는 프로젝트 소스에서 고도화 및 신규 프로그램 개발 중입니다그러던 중 공공기관 관리자 담당자가보안 관련 지적을 하셨습니다 -.공무원 담당자 지적사항 내용 https://www.url.com?paramA=파라미터a¶mB=파라미터b => 현재 일반 조회는 스프링 겟 매핑 방식 으로 하고 있습니다사이트를 사용하는 일반 유저가브라우저 url 주소창에 파라미터만 수정해가면서 조회 하면조회 결과가 달라져 나오는데 이거 보안상 문제 있는거 아니냐고 따져 지적을 합니다 기 구축되어 있는 소스에는 request 할때따로 인코딩/디코딩이 되어 있지 않는데토비님이 경험해오신 스프링 get/post 보안관련 지적 사항이 나오지 않을려면저희 프로젝트에서 어떻게 전체 소스(js, java ) 에 어떤 보안 관련 기능을 추가 할 수 있을까요? 참고로 구글도 검색어에 '토비' 라고 치고개발자 도구 열어서 payload 보면 한글 그대로 넘어가던데이게 공무원 담당자가 보안 관련 지적 하는게 맞는 건지도저는 모르겠습니다한가하실 때 시간 나시면 조언 부탁 드립니다감사합니다 수고하세요~ 김동희 드림 #토비#토비의스프링#spring#스프링#보안#get#post#parameter#파라미터#문제
- 해결됨토비의 스프링 부트 - 이해와 원리
인텔리제이 뎁스 구분 선
저 별건 아니지만,,뎁스 구분 선이 뜨게 하는 설정 방법 알려주십사 질문 드립니다
- 미해결토비의 스프링 부트 - 이해와 원리
intellij community edition terminal http request
intellij community edition을 사용해 실습하고 있습니다. 섹션 2. Hello API 테스트와 같이 터미널에http -v ":8080/hello?name=Spring" 요청시 다음과 같은 에러가 뜨며 요청이 제대로 이루어지지 않습니다.혹시 ultimate 버전에서만 지원하는 기능이어서 그런건지 질문 드립니다. http : The term 'http' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.At line:1 char:1+ http -v ":8080/hello?name=Spring"+ ~~~~+ CategoryInfo : ObjectNotFound: (http:String) [], CommandNotFoundException+ FullyQualifiedErrorId : CommandNotFoundException
- 미해결토비의 스프링 부트 - 이해와 원리
스프링 검색 유입 경로 pc or 모바일 구분 방법 문의 드립니다
안녕하세요~ 토비님 참여중인 프로젝트가 현재 포탈 사이트 성격입니다 해당프로젝트에서 커뮤니티 기능이 있는데커뮤니티 기능 중에 접속 유입 경로를 따져통계 조회를 해야 하는 기능이 있습니다 개발하는 커뮤니티에 pc 로 접속 할 수 있고 모바일로 접속 할 수 있습니다 PC or 모바일 중어느 기기를 통해서 해당 포탈 커뮤니티에 접속해서 검색했는지따질려면 스프링의 어느 기술 라이브러리를이용해서 따지면 되는지 문의 드립니다감사합니다 수고하세요. 김동희 드림 #sping#스프링#pc#모바일#접속 #구분
- 미해결토비의 스프링 부트 - 이해와 원리
ProxyBeanMethods = false에 대해 궁금합니다.
MyAutoConfiguration에서 ProxyMethods를 false를 줬으니 Tomcat과 DisPatcherServlet이 호출될떄마다 새로 생성되는건가요??
- 미해결토비의 스프링 부트 - 이해와 원리
스프링 사용 관련 궁금한 사항이 생겨 질문드립니다
스프링 사용 관련 궁금한 사항이 생겨 질문드립니다 토비님 안녕하세요~ 오늘 아침에 웹프로그램 개발하다 갑자기 궁금한 사항이 생겼습니다 1. MVC 컨트롤러 를 이용 할 때 보안상 문제로 get을 사용하지 않고 post 만 작성 하는게 맞는것인지 웹프로그램을 개발 할 때 브라우저 url 에는 파라미터가 전혀 안보이는것이 보안상 최선인지 궁금합니다 토비님도, 스프링 mvc 를 이용해서 개발 하실때 모두 post 방식으로 request 를 하시는지 궁금합니다 (간혹 금융권 사이트에서는 url 부분에 파라미터가 안보였던거 같아서요.. ) 2. 네이버/카카오/유튜브 open API 등을 누가나 사용 할 수 있는데요 나쁜 사용자가 악의적인 의도를 갖고 마구 request 호출 을 할 경우 서버 트랙픽을 방어 하려고 하면 스프링의 어느 기술을 이용해서 막을 수 있을 까요? 3. 스프링 프레임웍 안에서 뷰(프론트) 부분에 JSP / 타임리프 / php / react / vue 동시에 여러가지를 함께 쓸 수가 있나요? 감사합니다. 수고하세요