묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
타임리프에서 th:errorclass가 정확히 어떤 것인지 궁금합니다!
안녕하세요! 항상 좋은 답변해주셔서 감사합니다. 이번에는 타임리프에서 th:errorclass를 사용할 때 궁금증이 생겨서 코드로 여쭤보고 싶어 글을 작성하게 되었습니다. 정확하게는 th:errorclass에서 errorclass가 true일 때, th:field="*{price}"를 통해서 나와야 할 th:value = "${item.price}"가 왜 안 나오는지를 이해하지 못해서 글을 적게 되었습니다. <input type="text" id="price" th:field="*{price}" th:errorclass="field-error" class="form-control" placeholder="가격을 입력하세요"> 위 코드를 보면 errorclass='field-error'가 있고, 이것이 여러가지의 형태를 축약해서 보여주는 것으로 알고 있습니다. <input type="text" id="price" th:field="*{price}" th:classappend="${#fields.hasErrors('price')} ? 'field-error' : _" class="form-control" placeholder="가격을 입력하세요"> 타임리프 독스를 활용하면 위의 코드가 축약되는 것이 errorclass로 이해를 하고 있습니다. 즉, errorclass는 현재 선택표현식으로 나오는 값이 에러가 있으면, 클래스에 field-error를 더해서 사용하고, 에러가 없으면 form-control만 사용하는 것으로 이해를 하고 있습니다. bindingResult.addError(new FieldError("Item","itemName","상품 이름은 필수입니다.")); 그런데 RejectedValue를 사용하지 않고, 위 코드를 사용하게 될 경우 Validation을 통과하지 못한 값들은 다시 HTML Form으로 나오지는 않습니다. 그런데 확인해보니 @ModelAttribute로 요청 파라미터가 바인딩 될 때는, 로그 상에서 잘못된 값이 들어오더라도 Item 객체에는 정상적으로 바인딩 되는 것이 확인되었습니다. 이 상황들을 요약해보면 다음과 같습니다. 1. @ModelAttribute로 객체 Binding이 될 때는 타입 에러만 아니면, Validation을 통과하지 못하는 모든 값들도 자동적으로 객체에 Binding이 된다. 2. 따라서 다시 addForm으로 넘어갈 때, Model에 들어있는 Item에는 비정상적으로 입력된 값도 들어가있다. 3. 뷰 템플릿에서 Model에서 item을 찾아서 값을 꺼내려고 할 때, 값이 없기 때문에 안 꺼내지는 것은 아닌 것으로 확인된다. 위의 세 가지 상황을 요약해보면... <input type="text" id="price" th:field="*{price}" th:errorclass="field-error" class="form-control" placeholder="가격을 입력하세요"> 위 코드에서 price로 된 error가 있다면, th:field에 의해서 자동으로 생성되는 th:value=${price}만 실행되지 않는다로 이해를 해야할 것 같습니다. 왜냐하면 error가 있을 때, 레드박스는 발동하기 때문입니다. 아무리 찾아봐도... 없어서... 위처럼 이해를 해도 되는 것인지 궁금합니다! 항상 좋은 답변 감사드립니다! 좋은 하루 되세요!
-
미해결Vue.js 중급 강좌 - 웹앱 제작으로 배워보는 Vue.js, ES6, Vuex
권한 수락이 안된 것 같아요...
수락이 된게 맞을까요?? github joshua1988 로 들어가서 repositories 에서 vue-intermediate 검색을 하고 아무리 찾아봐도 해당 결과가 안 나오네요 ㅠㅠ ..
-
미해결코틀린 3강으로 끝내기 feat. 안드로이드 개발
ignoreNulls 함수
ignoreNulls함수에 파라미터 변수 타입이 String?인데 그 밑에는 str!!로 하셨습니다. ?는 null값일 수도 있다고 하셨는데 밑에 !!로 null이 아니다를 뜻하는데 왜 굳이 ?를 썼는지 궁금합니다.
-
미해결문과생도, 비전공자도, 누구나 배울 수 있는 파이썬(Python)!
클래스명.__init__()사용시 에러
강의에서 알려주신 것처럼 클래스명.__init__()를 실행 시 아래와 같은 에러가 뜨는데 잘몰라서 구글링을 해도 명확히 이해가 되지 않는데 왜 그런건가요?
-
미해결작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지
사진이 업로드되지 않는 에러
1. profile 수정해도 화면에 표시되지 않거나 2. "413 Request Entity Too Large" 에러가 발생합니다. 설정오류일까요? 깃주소는 아래와 같습니다. https://github.com/JJingu/jjinkong.git
-
미해결3. 웹개발 코스 [스프링 프레임워크+전자정부 표준프레임워크]
service를 만들엇고 serviceimpl에서 저 단어가 왜나왔나 지금 의문이 해소가안되네요 답변좀요
빨간 표시한 EgovAbstractServiceImpl은 어디서 나온것인가 도저히 이해할수가없어요 이거 어디에 연결이되서 어떻게 저단어가 나오게된거죠? 비전공자가 알기쉽게 설명 부탁드립니다.
-
미해결Node.js에 TypeScript 적용하기(feat. NodeBird)
타입추론이 제대로 안됩니다 ㅠㅠ
routes의 middleware.ts에 isAuthenticated() 부분이 타입추론이 안됩니다. passport에 index.ts를 켜놓은 상태에서는 추론이 됩니다. passport에 index.ts에서도 types/index.d.ts 를 켜놓은 상태에서는 user.id 에 타입이 추론되는데 꺼져있으면 또 에러가 생깁니다. 왜그럴까요?
-
미해결팀 개발을 위한 Git, GitHub 입문
좋은 강의 잘 들었습니다.. ppt자료 부탁합니다..
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 입문자에게 유익한 강의네요..강의 잘 들었습니다... ppt자료 부탁합니다.. sisky77@gmail.com
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
질문 있습니다!!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. @GetMapping("/{postId}/edit")public String editForm(@PathVariable Long postId, Model model) { PostDetailDto post = postService.findByPostId(postId); model.addAttribute("post", post); return "post/post_edit_form";}@PostMapping("/{postId}/edit")public String editForm(@PathVariable Long postId, @Validated @ModelAttribute("post") PostUpdateRequestDto dto, BindingResult bindingResult) { //글로벌오류 if ( !StringUtils.hasText(dto.getTitle()) && !StringUtils.hasText(dto.getContent())) { bindingResult.reject("globalError"); } //검증실패시 다시 입력 폼으로 if (bindingResult.hasErrors()) { log.info("errors ={}", bindingResult); return "post/post_edit_form"; } postService.updatePost(dto, postId); return "redirect:/post/{postId}";}@Getterpublic class PostDetailDto { private Long postId; private String title; private String content; private String author; private Date regDate; public PostDetailDto(Post entity) { this.postId = entity.getPostId(); this.title = entity.getTitle(); this.content = entity.getContent(); this.author = entity.getAuthor(); this.regDate = entity.getRegDate(); }}@Getter@Setterpublic class PostUpdateRequestDto {@NotBlank private String title; @NotBlank private String content;}이런식으로 editForm을 보여줄 때 모델에 바인딩 되어서 넘어가는 dto가 다를때는 어떻게 해야 할까요? @GetMapping으로 조회 할 땐 db에 있는 값이 다 담겨져서 조회가 가능 하지만@PostMapping으로 수정 할때 haserror가 걸리면 수정폼으로 리턴 될 때 수정 폼의 필드들에 @Validated @ModelAttribute("post") PostUpdateRequestDto dto -> 이 값이 넘어가서 editForm에 있는 다른 필드들(author,content등..)에 매칭이 안돼서 오류가 납니다리다이렉트로 editForm에 넘기는 방법도 해봤는데 결국 findById로 조회해서 모델에 바인딩시켜주는거라 전에 있던 value값들이 적혀서 나오네요( 강의에서는 빈값으로 나옵니다 )dto를 합치는 방법밖에 없을까요?
-
미해결[파이토치] 실전 인공지능으로 이어지는 딥러닝 - 기초부터 논문 구현까지
[코드 질문] 코드 관련 질문드립니다!
안녕하세요. 강사님 우선, 연말 잘 보내세요 : ) 강사님 덕분에 파이토치를 열심히 공부하고 있습니다! 현재, LSTM가지고 여러가지 시도를 해보면서 공부중에 있습니다. 강의에서 다루시지는 않았지만, CNN + LSTM + LSTM 위의 형식으로 레이어를 구성해서 활용해보고 싶습니다. LSTM 2개를 연속해서 사용하기 위해서는 어떻게 해야할까요? 열심히 구글링 해봤지만, 명확하게 알기 힘들어서 질문드립니다. 현재 강의에서 알려주신 LSTM에 CNN과 드랍아웃을 적용한 상태입니다. 여기에서 LSTM을 추가로 Stack하려면 어떻게 해야하는 알려주실 수 있을까요? 바쁘신 와중에 감사드립니다 : )
-
미해결설계독학맛비's 실전 Verilog HDL Season 1 (Clock부터 Internal Memory까지)
설치과정 질문
안녕하세요 맛비님 이번에 강의를 듣게된 학생입니다. 설치 강의 영상 22분 58초 나오는데로 입력을 하였는데 You have to accept the EULA to proceed with this installation. To accept the EULA, specify the option --agree XilinxEULA,3rdPartyEULA,WebTalkTerms usage: xsetup [-a <arg>] [-b <arg>] [-c <arg>] [-e <arg>] [-h] [-l <arg>] [-p <arg>] [-x] Xilinx Installer - Command line argument list. -a,--agree <arg> Agree to the required terms and conditions. [XilinxEULA,3rdPartyEULA,WebTalkTerms] -b,--batch <arg> Runs installer in batch mode and executes the specified action. Valid actions are [AuthTokenGen, ConfigGen, Install, Uninstall, Add, Update]. AuthTokenGen is used to generate an authentication token that will be used by the batch mode webinstaller to download install content. ConfigGen is used to generate a config file as described below. Install is use for a fresh installation. Uninstall is for uninstalling an existing installation. Add is for adding tools or devices to an existing installation. Update is for installing an update release from Xilinx. -c,--config <arg> File defining install configuration. It is recommended to use a configuration file for batch install. To generate a configuration file, run xsetup -b ConfigGen. This file will contain the default install selections, which you can then change as needed by setting a value to 1(select) or 0(de-select) within the file. It is recommended that you generate this reference for each new quarterly release, so that new devices, tools, options or other changes will be accounted for in your configuration file. -e,--edition <arg> Name of the edition that should be installed. This option is not needed if using -c with a config file since the edition is included in the config file. -h,--help Display this help text. -l,--location <arg> The destination location of the installation. This option is not needed if using -c with a config file since the location is included in the config file. -p,--product <arg> Name of the product that should be installed. This option is not needed if using -c with a config file since the product is included in the config file. -x,--xdebug Run installer in debug mode Examples: Generate authentication token: xsetup -b AuthTokenGen Generate a config file: xsetup -b ConfigGen (generate and modify as needed). Install using a config file: xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms -b Install -c install_config.txt. If you do not wish to use a config file, you must provide the -l and -e. The -e choices for a given release can be found by generating a config file and copying the edition name from the resulting config file. When you do not use a config file, the default install options will be used for your installation. Example installing without a config file: xsetup --agree 3rdPartyEULA,WebTalkTerms,XilinxEULA --batch Install --edition "SDx Development Environments" --location "C:\Xilinx". The batch mode also supports uninstallation and upgrades (adding additional tools and devices). For example, if you install the Xilinx software to <user home>/Xilinx, go to <user home>/Xilinx/.xinstall/<product>_<version> To uninstall: xsetup -b Uninstall. To add devices or tools: xsetup -b Add -a XilinxEULA,3rdPartyEULA,WebTalkTerms -c <configfile>. 설치가 진행되지 않고 다음과 같은 문구가 떠서 질문 드립니다. 어디서 문제가 발생한건지 궁금합니다.
-
해결됨홍정모의 따라하며 배우는 C++
const에 대한 질문
const를 사용하면서 이해가 잘 안되는 부분이 있어서 질문합니다 int getValue() const { return a; } //a는 멤버변수 함수를 이렇게 만들었을때 해당 함수안의 멤버변수들은 값을 못바꾸니 함수가 끝나기 전까진 상수가 되는건가요? int& getValue() const { return a; } 이렇게 했을때 'return': cannot convert from 'const int' to 'int&' 라고 오류가 떳는데 const int라고 되어있길래 궁금해서 질문했습니다
-
해결됨스스로 구축하는 AWS 클라우드 인프라 - 기본편
인스턴트 태그 이름설정
강의 6:00 에 name을 lab-web-srv-pri1-2c 이라고 하셨는데 lab-web-srv-pri1-2a가 맞지 않나요?
-
미해결[React 1부] 만들고 비교하며 학습하는 React
mvc 패턴 비동기 처리 질문입니다
mvc 패턴은 비동기 처리를 어떻게 하나요? ex1) // model async setData() { const response = await fetch(...); const data = await response.json(); return data; } // controller constructor() { this.getData(); } getData() { this.data = this.model.setData(); } 이렇게 해서 view에 전달하면 되나요? ex2) // model async setData() { const response = await fetch(...); const data = await response.json(); this.foo(data); } this.foo(data) { // data에 대한 잔처리 } // controller ?? 이렇게 한다면 controller에서는 어떻게 데이터를 받아야 하나요? 감사합니다!
-
미해결3. 웹개발 코스 [스프링 프레임워크+전자정부 표준프레임워크]
map,hashmap,parametermap 알기쉽게 설명좀요
map,hashmap,parametermap 알기쉽게 설명좀요 제가 비전공자인데요 정보처리기사취득하고 겨우겨우 끄적이는데 아 남에게도 설명할정도로 정확한 로직을 알고싶은게 저의 목표입니다 저나 비전공자나 전공자도 알기쉽게설명부탁드립니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
무한정 back으로부터 post 데이터를 불러와요!
안녕하세요 zerocho 선생님... 다른게 아니라 이 부분에서 아주 크나큰 문제에 맞닥뜨려 작업을 못하고 있습니다. pages/index.js에서 useEffect를 사용해서 첫 페이지에 오면 로그인 유무를 판단하고 또 기존에 있던 게시글을 불러와야 하는것을 잘 아는데 문제는 로그인할 경우에는 딱 한번만 LOAD_MY_INFO_REQUEST를 잘 수행하는데 LOAD_POST_REQUEST를하는순간 무한 응답을 합니다. post man에서 받아온 데이터를 다음과 같습니다. 사실 저는 springboot를 back으로 사용하고 있는데 이유는 JPA를 좀 사용해보고 싶어서 였습니다. next.js를 아예 안쓰는것이 나앗던 것 같지만 처음에 강의를 접하고 할때는 아무것도 몰라서... 무진 후회중.. 그냥따라할걸... 하여간... 기존의 데이터도 이런 식으로 받아오는데 문제는 무한 응답을 요청하니까 도대체 어디서 잘못된건지 모르겠다는 것입니다. ㅠㅠ 제발좀 도와주십시오.;.. pages/index.js import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import AppLayout from "../components/AppLayout"; import PostCard from "../components/middleComponent/Post/PostCard"; import PostForm from "../components/middleComponent/Post/PostForm"; import { LOAD_POST_REQUEST } from "../reducers/post"; import { LOAD_MY_INFO_REQUEST } from "../reducers/user"; const Home = () => { const dispatch = useDispatch(); const { me } = useSelector((state) => state.user); const { mainPosts, hasMorePost, loadPostLoading } = useSelector((state) => state.post); useEffect(() => { console.log("useEffect in index.js") dispatch({ type: LOAD_MY_INFO_REQUEST }); // dispatch({ // type: LOAD_POST_REQUEST, // }); }, [hasMorePost, loadPostLoading]); useEffect(() => { function onScroll() { if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300){ if (hasMorePost && !loadPostLoading) { dispatch({ type: LOAD_POST_REQUEST, }); } } } window.addEventListener('scroll', onScroll); return () => { window.removeEventListener('scroll', onScroll); } }, []); console.log(mainPosts); return ( <AppLayout> {me && <PostForm />} {mainPosts.map((post) => <PostCard key={post.id} post={post}/>)} </AppLayout> ); } export default Home; reducers/post.js import shortId from 'shortid'; import produces, { produce } from 'immer'; import faker from 'faker'; import { ConsoleSqlOutlined } from '@ant-design/icons'; export const initialState = { mainPosts: [], imagePaths: [], hasMorePost: true, loadPostLoading: false, loadPostDone: false, loadPostError: null, addPostLoading: false, addPostDone: false, addPostError: null, addCommentLoading: false, addCommentDone: false, addCommentError: null, removePostLoading: false, removePostDone: false, removePostError: null, } export const generateDummyPost = (number) => Array(number).fill().map(() => ({ id: shortId.generate(), User: { id: shortId.generate(), nickname: faker.name.findName(), }, content:faker.lorem.paragraph(), Images: [{ src: faker.image.imageUrl(), }], Comments: [{ User: { id: shortId.generate(), nickname: faker.name.findName() }, content: faker.lorem.sentence(), }], })); export const LOAD_POST_REQUEST = 'LOAD_POST_REQUEST'; export const LOAD_POST_SUCCESS = 'LOAD_POST_SUCCESS'; export const LOAD_POST_FAILURE = 'LOAD_POST_FAILURE'; export const ADD_POST_REQUEST = 'ADD_POST_REQUEST'; export const ADD_POST_SUCCESS = 'ADD_POST_SUCCESS'; export const ADD_POST_FAILURE = 'ADD_POST_FAILURE'; export const ADD_COMMENT_REQUEST = 'ADD_COMMENT_REQUEST'; export const ADD_COMMENT_SUCCESS = 'ADD_COMMENT_SUCCESS'; export const ADD_COMMENT_FAILURE = 'ADD_COMMENT_FAILURE'; export const REMOVE_POST_REQUEST = 'REMOVE_POST_REQUEST'; export const REMOVE_POST_SUCCESS = 'REMOVE_POST_SUCCESS'; export const REMOVE_POST_FAILURE = 'REMOVE_POST_FAILURE'; export const ADD_POST_TO_ME = 'ADD_POST_TO_ME'; export const REMOVE_POST_OF_ME = 'REMOVE_POST_OF_ME'; export const addPost = (data) => ({ type: ADD_POST_REQUEST, data }) export const addComment = (data) => ({ type: ADD_COMMENT_REQUEST, data }) // const dummyPost = (data) => ({ // id: data.id, // content: data.content, // User: { // id: 1, // nickname: 'thelovedaejeon', // }, // Images: [], // Comments: [], // }); // const dummyComment = (data) => ({ // id: shortId.generate(), // content: data, // User: { // id: 1, // nickname: 'thelovedaejeon', // }, // }) //이전 상태를 action을 통해 다음 상태로 만들어 내는 함수 (불변성을 지키면서) const reducer = (state = initialState, action) => { return produce (state, (draft) => { switch (action.type){ case LOAD_POST_REQUEST: draft.loadPostLoading = true; draft.loadPostDone= false; draft.loadPostError= null; break; case LOAD_POST_SUCCESS: draft.loadPostLoading = false; draft.loadPostDone= true; draft.mainPosts = action.data.concat(draft.mainPosts); draft.hasMorePost = false; break; case LOAD_POST_FAILURE: draft.loadPostLoading = false; draft.loadPostError = action.error; break; case ADD_POST_REQUEST: draft.addPostLoading = true; draft.addPostDone= false; draft.addPostError= null; break; case ADD_POST_SUCCESS: draft.addPostLoading = false; draft.addPostDone= true; draft.mainPosts.unshift(dummyPost(action.data)); break; case ADD_POST_FAILURE: draft.addPostLoading = false; draft.addPostError = action.error; break; case REMOVE_POST_REQUEST: draft.removePostLoading = true; draft.removePostDone = false; draft.removePostError = null; break; case REMOVE_POST_SUCCESS: draft.removePostLoading = false; draft.removePostDone = true; draft.mainPosts = draft.mainPosts.filter((v) => v.id !== action.data); break; case REMOVE_POST_FAILURE: draft.removePostLoading = false; draft.removePostError = action.error; break; case ADD_COMMENT_REQUEST: draft.addCommentLoading = true; draft.addCommentDone = false; draft.addCommentError = null; break; case ADD_COMMENT_SUCCESS:{ const post = draft.mainPosts.find((v) => v.id === action.data.postId); post.Comments.unshift(dummyComment(action.data.content)); draft.addCommentLoading = false; draft.addCommentDone = true; break; // const postIndex = state.mainPosts.findIndex((v) => v.id === action.data.postId); // const post = { ...state.mainPosts[postIndex] }; // post.Comments = [dummyComment(action.data.content), ...post.Comments]; // const mainPosts = [...state.mainPosts]; // mainPosts[postIndex] = post; // return { // ...state, // mainPosts, // addCommentLoading: false, // addCommentDone: true, // }; } case ADD_COMMENT_FAILURE: draft.addCommentLoading = false; draft.addCommentError = action.error; break; default: break; } }); }; export default reducer; sagas/post.js import { delay, fork, all, takeLatest, put, call} from "redux-saga/effects"; import shortId from "shortid"; import axios from 'axios'; // import Axios from 'axios'; // import qs from 'query-string'; import Cookies from 'universal-cookie'; import { ADD_COMMENT_FAILURE, ADD_COMMENT_REQUEST, ADD_COMMENT_SUCCESS, ADD_POST_FAILURE, ADD_POST_REQUEST, ADD_POST_SUCCESS, ADD_POST_TO_ME, generateDummyPost, LOAD_POST_FAILURE, LOAD_POST_REQUEST, LOAD_POST_SUCCESS, REMOVE_POST_FAILURE, REMOVE_POST_REQUEST, REMOVE_POST_SUCCESS } from "../reducers/post"; import { REMOVE_POST_OF_ME } from "../reducers/user"; const cookies = new Cookies(); function addPostAPI(data) { const accessToken = cookies.get("accessToken"); const userEmail = cookies.get("userEmail"); const newObj = { description : data, email : userEmail } return axios.post('/auth/post', newObj,{ headers:{ 'Authorization': `Bearer ${accessToken}`, "Content-Type": "application/json" } }); } function* addPost(action) { try { const result = yield call(addPostAPI, action.data); yield put({ type: ADD_POST_SUCCESS, data: { id : result.data.postId, content: action.data } }) yield put({ type: ADD_POST_TO_ME, data: result.data.postId, }) } catch (error) { console.log(error); yield put({ type: ADD_POST_FAILURE, data: error.data }) } } function loadPostAPI(data) { return axios.get('/api/posts'); } function* loadPost(action) { try { const result = yield call(loadPostAPI); console.log(result); console.log(result.data); yield put({ type: LOAD_POST_SUCCESS, data: result.data.result, }); } catch (error) { console.log(error); yield put({ type: LOAD_POST_FAILURE, data: error.data }) } } function removePostAPI(data) { return axios.post('/api/post', data); } function* removePost(action) { try { delay(1000); // const result = yield call(addPostAPI, action.data); const id = shortId.generate(); yield put({ type: REMOVE_POST_SUCCESS, data: action.data }); yield put({ type: REMOVE_POST_OF_ME, data: action.data }) } catch (error) { yield put({ type: REMOVE_POST_FAILURE, data: error.data }) } } function addCommentAPI(data) { return axios.post('/api/post/${data.postId}/comment', data); } function* addComment(action) { try { delay(1000); // const result = yield call(addPostAPI, action.data); yield put({ type: ADD_COMMENT_SUCCESS, data: action.data }) } catch (error) { yield put({ type: ADD_COMMENT_FAILURE, data: error.data }) } } function* watchAddPost(){ yield takeLatest(ADD_POST_REQUEST, addPost); // 첫번째것만 하고 싶으면 takeLeading } function* watchLoadPost(){ yield takeLatest(LOAD_POST_REQUEST, loadPost); // 첫번째것만 하고 싶으면 takeLeading } function* watchRemovePost(){ yield takeLatest(REMOVE_POST_REQUEST, removePost); // 첫번째것만 하고 싶으면 takeLeading } function* watchAddComment(){ yield takeLatest(ADD_COMMENT_REQUEST, addComment); // 첫번째것만 하고 싶으면 takeLeading } export default function* postSaga(){ yield all([ fork(watchLoadPost), fork(watchAddPost), fork(watchRemovePost), fork(watchAddComment), ]) };
-
미해결Klaytn 클레이튼 블록체인 어플리케이션 만들기 - 이론과 실습
checkValidKeystore 함수 수정
저같은 경우는 keystore파일이 version4네요. crypto 대신 keyring 이 존재합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
Router node v.6 바뀐 부분
이렇게 적으면 v6에서 작동합니다. 앞에 분들이 여럿 글을 적어 주셨지만 정리된 게 없는 것 같아서 이렇게 올립니다. 공식문서에 나와있지만 영어가 어려우신 분들이나 처음 공부하시는 분들은 이거 참고 하시면 될 겁니다. 그리고 Link부분은 아직 안 나왔는데 적혀있어서, 오류떠서 주석 처리 했습니다. ```js import { BrowserRouter, Route, Routes, //Link } from "react-router-dom"; import LandingPage from './components/views/LandingPage/LandingPage' import LoginPage from './components/views/LoginPage/LoginPage' import RegisterPage from './components/views/RegisterPage/RegisterPage' function App() { return ( <BrowserRouter> <Routes> <Route exact path="/" element = {<LandingPage/>}/> <Route exact path="/login" element = {<LoginPage/>}/> <Route exact path="/register" element = {<RegisterPage/>}/> </Routes> </BrowserRouter> ); }
-
미해결따라하며 배우는 NestJS
useGards데코레이터 이후 Unauthorized입니다..
로그인으로 발급받은 토큰을 Bearer Token으로 두고 포스트 리퀘스트를 보내면 권한이 막히네요.. JWT.io사이트에서 로그인후 발급받은 토큰을 검증해봐도 정상적이라 나오고 설정시 이용하는 키도 잘 적어줫는데.. 무슨일일까요
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
validator질문 있습니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 저는 강의 내용과 다르게 엔티티와 DTO를 구분해놨습니다. 컨트롤러가 받는 값 즉, modelattribute와 validator 는 엔티티의 특정 필드만 뽑아서 만든 saveDto로 받는데요 validator를 만들때 support에서는 saveDto 클래스로 설정하고 validate에서 받는 target의 다운캐스팅 자료형도 saveDto로 받았습니다 문제는 컨트롤러에서 initBinder를 할 때 save하는 메서드에만 @Validated를 추가하니 , 다른 dto를쓰는 detail페이지나 이런 것들을 호출할때 에러가 나는데 , 제가 알기로는 initBinder를 쓴 컨트롤러에 전부다 적용 되는건 알고 있는데 특정 메서드에만 적용 할 수 없을까요? @Validated를 쓴 메서드에만 적용하고 싶습니다