한 달 전 · 하이린 님의 새로운 답변
프론트엔드 이직 준비로 어떤 것들을 하는게 좋을까요?
안녕하세요. 경력 2년차 프론트엔드 개발자입니다. 이전에 두 개의 회사에서 프론트엔드 개발자로 일했는데 불행하게도 두 회사 모두 임금체불로 인해 퇴사를 하게 되었습니다. 그래서 이번에는 50인 이상의 규모를 가진 회사로 이직하는 것을 목표로 이직을 준비하고 있습니다. Next.js, React, Typescript @tanstack/react-query, Context API, Recoil Vanilla-extract, emotion, styled-components, tailwind-css, Sass 위와 같은 스킬들을 공부 및 경험해보았고, Vanilla-extract, tailwind-css를 제외한 스킬들은 실제 업무에서도 활용하였습니다. 현재 저는 [1. 코딩테스트, 2. 기술블로그, 3. 개인프로젝트] 를 매일 반복하며 이직을 준비하고 있습니다. 이대로 계속 이직을 준비하면 될지, 아니면 다른 무언가를 더 준비해야할 지, 앞으로의 이직 준비 방향에 대해 알려주시면 감사하겠습니다. 추가로 혹시 이력서 피드백 해주실 수 있는 분 계시면 말씀 부탁드립니다... 서류에서 계속 떨어지다보니 개발자 입장에서 피드백을 꼭 받아보고 싶습니다...!
개발자
#프론트엔드
#이직
#경력이직
#이력서
#피드백
답변 1
댓글 0
조회 77
2달 전 · 서노 님의 새로운 댓글
Next 14 전역 상태 관리 질문
커뮤니티 개발할 때 리스트같은 경우는 보통 useContext 로 전역 관리 하나요? 그래서 뒤로가기나 그럴 때 기존 상태 보여주도록 하나요?..
개발자
#next.js14
답변 1
댓글 1
보충이 필요해요 2
조회 50
2달 전 · 김재민 님의 새로운 답변
React 상태관리질문
학원에서 프로젝트를 진행중인데 기능이많아 상태관리가 많아요. React useContext와 Redux중 어떤상태관리를 사용하는게 유리할까요?? 그리고 현업에서는 어떤방법을 택하는지 궁금합니다
개발자
#react
답변 4
댓글 0
추천해요 2
조회 2,223
6달 전 · 노원재 님의 답변 업데이트
ReactNative ios build 에러 3일째 해결을 못했습니다.
시뮬레이션을 실행하려고 해도 스크립트 문제, iPhone 버전 범위 문제, 시뮬레이터 문제가 계속 발생합니다. 어떤 도움이라도 감사합니다. ReactNative를 처음 접했습니다. 저희 팀에서 저를 도울 수 있는 사람이 없습니다. #프로젝트 환경 mac M2 ruby -v ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin23] node -v v20.10.0 pod --version 1.15.2 package.json { "name": "labts", "version": "0.0.1", "private": true, "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", "lint": "eslint .", "start": "react-native start", "test": "jest" }, "dependencies": { "@react-native-community/async-storage": "^1.12.1", "@react-native-community/cli": "13.6.9", "@react-navigation/bottom-tabs": "^6.6.0", "@react-navigation/native": "^6.1.17", "@react-navigation/native-stack": "^6.10.0", "@tanstack/react-query": "^5.51.5", "@types/react-native-vector-icons": "^6.4.18", "axios": "^1.7.2", "date-fns": "^3.6.0", "immer": "^10.1.1", "react": "18.2.0", "react-native": "0.74.3", "react-native-calendars": "^1.1305.0", "react-native-date-picker": "^5.0.4", "react-native-dotenv": "^3.4.11", "react-native-get-random-values": "^1.11.0", "react-native-image-crop-picker": "^0.41.2", "react-native-image-zoom-viewer": "^3.0.1", "react-native-paper": "^5.12.3", "react-native-permissions": "^4.1.5", "react-native-safe-area-context": "^4.10.8", "react-native-screens": "^3.32.0", "react-native-splash-screen": "^3.3.0", "react-native-tab-view": "^3.5.2", "react-native-vector-icons": "^10.1.0", "react-native-vision-camera": "^4.5.1", "uuid": "^10.0.0", "yarn": "^1.22.22" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@react-native/babel-preset": "0.74.85", "@react-native/eslint-config": "0.74.85", "@react-native/metro-config": "0.74.85", "@react-native/typescript-config": "0.74.85", "@types/react": "^18.2.6", "@types/react-native-dotenv": "^0.2.2", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", "babel-plugin-module-resolver": "^5.0.2", "eslint": "^8.19.0", "jest": "^29.6.3", "prettier": "2.8.8", "react-test-renderer": "18.2.0", "typescript": "5.0.4" }, "engines": { "node": ">=18" } } PodFile require Pod::Executable.execute_command('node', ['-p', 'require.resolve( "react-native/scripts/react_native_pods.rb", {paths: [process.argv[1]]}, )', __dir__]).strip platform :ios, '12.0' use_frameworks! #use_modular_headers! prepare_react_native_project! linkage = ENV['USE_FRAMEWORKS'] if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_sym end target 'nexlabts' do config = use_native_modules! use_react_native!( :path => config[:reactNativePath], # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) target 'nexlabtsTests' do inherit! :complete # Pods for testing end post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false, # :ccache_enabled => true ) end end 제가 아래 에러 3가지에 대해 제가 해본 방법들입니다. 1. node 재설치 node_module 폴더 삭제, package-rock.json 삭제 후 재설치 npm install --legacy-peer-deps yarn install 2. Xcode가 node 읽을 수 있도록 설정 sudo ln -s "$(which node)" /usr/local/bin/node 3. Podfile 내 platform 설정 수정 platform :ios, '12.0' or platform :ios, '14.0' 4. Pods 재설치 rm -rf ~/Library/Developer/Xcode/DerivedData or rm -rf ~/Library/Developer/Xcode/DerivedData/* rm -rf Pods rm Podfile.lock pod install --repo-update Xcode \> Product \> Clean Build Folder. cd ./ios pod cache clean -all pod install --repo-update cd ../ npx react-native run-ios --no-packager --simulator="iPhone 15" or npx react-native run-ios --simulator="iPhone 15" or yarn start > i(run ios) Err 1. cocoaPods 설치할 때 [!] CocoaPods could not find compatible versions for pod "React-RuntimeHermes": In Podfile: React-RuntimeHermes (from ../node_modules/react-native/ReactCommon/react/runtime) Specs satisfying the React-RuntimeHermes (from ../node_modules/react-native/ReactCommon/react/runtime) dependency were found, but they required a higher minimum deployment target. Err2. iOS 실행할때 run-ios --no-packager --simulator="iPhone 15" Build description signature: fc1341421f84b87c5245d346c2c17b66 Build description path: /Users/nowonjae/Library/Developer/Xcode/DerivedData/nexlabts-argvodqcybjfcybstpulfpghnzvm/Build/Intermediates.noindex/XCBuildData/fc1341421f84b87c5245d346c2c17b66.xcbuilddata /Users/nowonjae/Desktop/project/NeXLabRN/ios/nexlabts.xcodeproj:1:1: error: Unable to open base configuration reference file '/Users/nowonjae/Desktop/project/NeXLabRN/ios/Pods/Target Support Files/Pods-nexlabts/Pods-nexlabts.release.xcconfig'. (in target 'nexlabts' from project 'nexlabts') warning: Unable to read contents of XCFileList '/Target Support Files/Pods-nexlabts/Pods-nexlabts-resources-Release-output-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') warning: Unable to read contents of XCFileList '/Target Support Files/Pods-nexlabts/Pods-nexlabts-frameworks-Release-output-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') error: Unable to load contents of file list: '/Target Support Files/Pods-nexlabts/Pods-nexlabts-frameworks-Release-input-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') error: Unable to load contents of file list: '/Target Support Files/Pods-nexlabts/Pods-nexlabts-frameworks-Release-output-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') warning: Run script build phase 'Bundle React Native code and images' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'nexlabts' from project 'nexlabts') warning: Run script build phase '[CP] Embed Pods Frameworks' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'nexlabts' from project 'nexlabts') error: Unable to load contents of file list: '/Target Support Files/Pods-nexlabts/Pods-nexlabts-resources-Release-input-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') error: Unable to load contents of file list: '/Target Support Files/Pods-nexlabts/Pods-nexlabts-resources-Release-output-files.xcfilelist' (in target 'nexlabts' from project 'nexlabts') warning: Run script build phase '[CP] Copy Pods Resources' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'nexlabts' from project 'nexlabts') --- xcodebuild: WARNING: Using the first of multiple matching destinations: { platform:iOS Simulator, id:B5AA2E84-4F83-4749-A986-A1FCE5E398A3, OS:17.5, name:iPhone 15 } { platform:iOS Simulator, id:B5AA2E84-4F83-4749-A986-A1FCE5E398A3, OS:17.5, name:iPhone 15 } ** BUILD FAILED ** ] Err3. Xcode 로 Build 할때 (Any iOS Simulator Device (arm64, x86_64)) Command PhaseScriptExecution failed with a nonzero exit code
개발자
#reactnative
#xcode
#reactnative-run-ios
답변 1
댓글 0
조회 435
6달 전 · ㅇㅅㅇ 님의 질문 업데이트
React Next infinite scroll
A 라는 infinite scroll페이지에서 500개 데이터를 보여주고 scroll은 70프로 내려왔다고 가정했을 때 다른 페이지 갔다가 돌아왔을 때 500개 데이터랑 scroll 위치 그대로 유지하는 좋은 방법 뭐 있을까요? localstorage나 context 이용했을때는 dom을 다시 랜더링하고 state 값을 다시 주입 했을 때 부드럽지 않은 느낌입니다. redux를 이용해서 전역으로 상태값을 저장해 놓고 컴포넌트에서 사용하면 될까요?
개발자
#react
#next.js
#redux
답변 0
댓글 0
조회 30
10달 전 · 정창록 님의 질문
Next.js 에서 fluent-ffmpeg 사용 시 에러 해결 가능할까요?
Next.js 에서 puppeteer를 사용해서 특정 url에 접속하여 애니메이션을 png로 100장 정도 캡처하여 생성하고, fluent-ffmpeg를 사용해서 해당 png 이미지들을 mp4 영상으로 만들려고 하는데요. yarn add puppeteer fluent-ffmpeg @ffmpeg-installer/ffmpeg yarn add --dev @types/fluent-ffmpeg 위와 같이 라이브러리들을 설치했구요. 아래 page.tsx 파일에서 코드를 구현했는데요. dev로 실행해서 해당 페이지에 접속을 하면 아래와 같은 에러가 발생하는데요. 해결이 가능할까요?? 다른 라이브러리를 써야할지 구현한 코드가 문제가 있는지 모르겠네요. 도움 부탁드립니다!! # 에러 코드 # 1 of 1 error Next.js (14.2.3) Server Error Error: Cannot find module '/Users/.../animation-capture/node_modules/@ffmpeg-installer/darwin-arm64/package.json' This error happened while generating the page. Any console logs will be displayed in the terminal window. Call Stack webpackEmptyContext file:///Users/.../animation-capture/.next/server/app/capture/page.js (22:10) eval node_modules/@ffmpeg-installer/ffmpeg/index.js (40:27) (rsc)/./node_modules/@ffmpeg-installer/ffmpeg/index.js file:///Users/.../animation-capture/.next/server/vendor-chunks/@ffmpeg-installer.js (20:1) Next.js eval /./src/app/capture/page.tsx (rsc)/./src/app/capture/page.tsx file:///Users/.../animation-capture/.next/server/app/capture/page.js (286:1) Next.js # 코드 구현부 # import { NextApiRequest, NextApiResponse } from 'next'; import puppeteer from 'puppeteer'; import fs from 'fs'; import path from 'path'; import ffmpeg from 'fluent-ffmpeg'; import ffmpegInstaller from '@ffmpeg-installer/ffmpeg'; ffmpeg.setFfmpegPath(ffmpegInstaller.path); .... 중략.... const outputFilePath = path.resolve("./screenshots/video.mp4"); ffmpeg() .addInput(`${folderPath}/screenshot-%d.png`) .inputFPS(10) .output(outputFilePath) .on("end", () => { res.status(200).send(`Video created successfully at ${outputFilePath}`); }) .on("error", (err) => { console.error("Error generating video:", err); res.status(500).send("Failed to generate video"); }) .run(); } catch (error) { console.error("Error capturing screenshots:", error); res.status(500).send("Failed to capture screenshots"); }
개발자
#next.js
#fluent-ffmpeg
#mp4
답변 0
댓글 0
조회 87
10달 전 · 예빈 님의 새로운 댓글
타입스크립트 타입지정
리액트 쿼리로 OptimisticUpdate 를 구현했는데 onError 에서 context 타입 지정을 어떻게 해야할지 모르겠습니다 ㅠㅠ context : 타입 하면 오류나고, data : 타입 = context 해도 오류나고 as 를 쓰면 해결되긴 하는데 더 좋은 방법 없을까요? ㅠㅠㅠ 'use client'; import { useState } from 'react'; import { toast } from 'react-toastify'; import { usePostLikeCount } from '@/hooks'; interface LikeContextType { previousLikeCount: number; previousIsLike: boolean; } export const useOptimisticLike = ( boardId: number, initialLikeCount: number, initialIsLike: boolean, refetch: () => void ) => { const [optimisticLikeCount, setOptimisticLikeCount] = useState(initialLikeCount); const [optimisticIsLike, setOptimisticIsLike] = useState(initialIsLike); const { mutate: postMutate } = usePostLikeCount(boardId, { onMutate: async (): Promise<LikeContextType> => { setOptimisticLikeCount((prev) => optimisticIsLike ? prev - 1 : prev + 1 ); setOptimisticIsLike((prev) => !prev); return { previousLikeCount: optimisticLikeCount, previousIsLike: optimisticIsLike, }; }, onError: (err, variables, context) => { const data: LikeContextType = context; if (data) { setOptimisticLikeCount(data.previousLikeCount); setOptimisticIsLike(data.previousIsLike); } toast.error('좋아요 업데이트에 실패했습니다.'); }, onSuccess: () => { refetch(); }, }); const uploadLike = () => { postMutate(); }; return { optimisticLikeCount, optimisticIsLike, uploadLike, }; };
개발자
#react-query
#typescript
답변 1
댓글 1
조회 55
일 년 전 · 익명 님의 질문
RAG시 문서와 관련없는 내용
안녕하세요 질문이 있습니다! RAG챗봇 개발시 문서와 관련없는 질문또는 문서에 없는 내용을 질문했을때 임계치를 설정했어도 검색이 되서 context에 넣는 경우가 있는데 이런경우 어떤식으로 해결할 수 있을까요..? 참고자료가 있나면 공유해주시면 감사하겠습니다ㅠㅠ
개발자
#llm
#rag
#nlp
#chatgpt
답변 0
댓글 0
조회 82
일 년 전 · 김하림 님의 답변 업데이트
nextjs styled-component ssr 에러
모든 분들이 격어보셨을 에러에 대해 해결이 되지 않아 질문 드려봅니다. 아래 참고를 통해 nextjs ssr에서 styled-component가 적용되게 시도했습니다 (현재 app router 방식을 사용하고 있습니다) 하지만 동일하게 했을 때 여전히 아래와 같은 오류가 떴습니다. babel, swc 둘 다 시도 했을 때 동일 했고 혹시 제가 놓지고 있는 부분이 있을까요? 4번까지 진행했습니다. nextjs styled-component typescript 오류 : Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component 참고 : https://dev.to/rashidshamloo/using-styled-components-with-nextjs-v13-typescript-2l6m#5
개발자
#nextjs
#styled-component
#ssr
답변 2
댓글 8
조회 1,095
일 년 전 · 가애KAAE 님의 답변 업데이트
flutter 화면 전환
안녕하십니까! Flutter로 졸업 작품 앱 개발 진행 중인 대학생입니다. Splash 화면 구현과, 자동 로그인 및 사용자 초기 정보 입력 페이지를 구현하던 중, 화면 전환에 대해 궁금한 점이 생겼습니다. 1. Navigator.push()를 이용해서 route를 전환 2. route를 구성하는 전체 위젯을 갈아끼움 두 방법 중 사용자에게 또 다른 화면 구성을 제공하는 방법에는 어떤 것이 더 효율적이며, 무슨 차이가 있는지 궁금합니다!! 예시 1번 if (_autoLogin) { Navigator.push(context, (context) => FirstPage()); } else { Navigator.push(context, (context) => SecondPage()); } 2번 Scaffold( body: _autoLogin ? FirstPage() : SecondPage() )
개발자
#flutter
#route
#page
#navigator
#widget
답변 2
댓글 2
조회 490
일 년 전 · 김화창 님의 답변 업데이트
spring autowired 사용에 관해 질문드립니다.
@Configuration public class ControllerConfig { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MemberConfig.class); @Bean public SearchController serachController() { return new SearchController(ac.getBean("memberDao", MemberDao.class)); } } ------------------------------------------------------------------------------------ @Configuration public class ControllerConfig { @Autowired private MemberDao memberDao; @Bean public SearchController serachController() { return new SearchController(memberDao)); } } autowired 사용을 지양하고, 생성자 주입을 사용하는게 좋다고 들었는데 설정 클래스에서는 생성자 주입이 안되는데 위 코드 중 어느 방식으로 코딩하는게 맞는 방식일까요? 혹시 위 방식 말고 다른 방식이 있다면 알려주시면 감사하겠습니다.
개발자
#spring
답변 1
댓글 0
조회 100
일 년 전 · 우엉김밥 님의 새로운 댓글
리액트 context api
* ContextProvider 정의* const LocationContext = createContext() export const LocationProvider = ({children})=> return ( <LocationContext.Provider value={contextValue}> {children} </LocationContext.Provider> ); }; --------------------------- asd.jsx <ContextProvider> <A/> </ContextProvider> ---------------------- qwe.jsx <ContextProvider> <B/> </ContextProvider> ---------------------------------- 이런식으로 작성했을때 A컴포넌트에서 컨택스트 내부 값을 변경하면 B컴포넌트가 재 랜더링 되나요? (되는줄 알았는데 안돼서요..ㅠ)
개발자
#react
#context
답변 1
댓글 1
조회 50
일 년 전 · 익명 님의 질문
플러터 질문. Futuer 및 출
locate.dart를 만들어서 import 'package:geolocator/geolocator.dart'; class Locate{ Future<List<double>> location() async { List<double> m_l = []; // 위치 권한 요청 LocationPermission permission = await Geolocator.requestPermission(); // 현재 위치 가져오기 Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); // 위치 정보 리스트에 추가 m_l.add(position.longitude); m_l.add(position.latitude); return m_l; // 위치 정보를 포함한 리스트 반환 } Future<List<double>> get_loc() async { // 위치 정보를 가져오기 List<double> location = await this.location(); // 수정된 부분 return location; // 위치 정보를 포함한 리스트 반환 } } 를 작성하였구요 main_screen.dart 라는 파일에서 함수를 생성해서 my_locate() async{ Locate locator = Locate(); // 위치 정보 가져오기 List<double> location = await locator.get_loc(); } @override Widget build(BuildContext context) { // 함수 실행은 //요 부분에서 return Scaffold( 이 부분 안에서 실행시킬려고 하는데 자꾸 오류가 걸리네요. 방법 알려주실 분 있나요?
개발자
#flutter
#dart
답변 0
댓글 0
보충이 필요해요 1
조회 41
일 년 전 · 다형 님의 답변 업데이트
aws spring boot 배포 오류
안녕하세요 백엔드 공부 중인 학생입니다. aws ec2로 Spring boot 프로젝트를 배포 시도 중에 있습니다. (maven, java 8, jar) java -jar jar파일명.jar 명령어로 배포 시도 중에 에러메세지가 도저히 해결이 안되어서 도움 요청드립니다.. 도와주신다면 감사하겠습니다.. 아 참고로 rds로 데이터베이스 생성하지 않고 mysql(workbench)로 데이터베이스 생성했습니다 <오류메세지> Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-02-07 04:33:35.742 ERROR 31012 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.22.jar!/:5.3.22] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_392] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.2.jar!/:2.7.2] at com.se.social.SocialApplication.main(SocialApplication.java:13) [classes!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_392] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_392] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_392] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_392] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.22.jar!/:5.3.22] ... 22 common frames omitted Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed at org.apache.catalina.core.StandardService.addConnector(StandardService.java:238) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.7.2.jar!/:2.7.2] ... 24 common frames omitted Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1077) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.core.StandardService.addConnector(StandardService.java:234) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 26 common frames omitted Caused by: java.net.SocketException: Permission denied at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:461) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:453) ~[na:1.8.0_392] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) ~[na:1.8.0_392] at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:275) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:230) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1313) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:614) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1074) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 28 common frames omitted <전체> . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.2) 2024-02-07 04:33:27.975 INFO 31012 --- [ main] com.se.social.SocialApplication : Starting SocialApplication v0.0.1-SNAPSHOT using Java 1.8.0_392 on ip-172-31-39-15 with PID 31012 (/home/ubuntu/socialboardPJ/target/social-0.0.1-SNAPSHOT.jar started by ubuntu in /home/ubuntu/socialboardPJ/target) 2024-02-07 04:33:27.980 INFO 31012 --- [ main] com.se.social.SocialApplication : No active profile set, falling back to 1 default profile: "default" 2024-02-07 04:33:29.591 INFO 31012 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-02-07 04:33:29.681 INFO 31012 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 76 ms. Found 1 JPA repository interfaces. 2024-02-07 04:33:30.960 INFO 31012 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 80 (http) 2024-02-07 04:33:30.986 INFO 31012 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-02-07 04:33:30.987 INFO 31012 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65] 2024-02-07 04:33:31.641 INFO 31012 --- [ main] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 2024-02-07 04:33:31.880 INFO 31012 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2024-02-07 04:33:31.880 INFO 31012 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3717 ms 2024-02-07 04:33:32.215 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-02-07 04:33:32.569 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-02-07 04:33:32.659 INFO 31012 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-02-07 04:33:32.822 INFO 31012 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.10.Final 2024-02-07 04:33:33.157 INFO 31012 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2024-02-07 04:33:33.383 INFO 31012 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect 2024-02-07 04:33:34.255 INFO 31012 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2024-02-07 04:33:34.266 INFO 31012 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-02-07 04:33:34.906 WARN 31012 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2024-02-07 04:33:35.616 WARN 31012 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server 2024-02-07 04:33:35.620 INFO 31012 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-02-07 04:33:35.624 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-02-07 04:33:35.646 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2024-02-07 04:33:35.650 INFO 31012 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2024-02-07 04:33:35.676 INFO 31012 --- [ main] ConditionEvaluationReportLoggingListener : Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-02-07 04:33:35.742 ERROR 31012 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.22.jar!/:5.3.22] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_392] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.2.jar!/:2.7.2] at com.se.social.SocialApplication.main(SocialApplication.java:13) [classes!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_392] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_392] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_392] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_392] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.22.jar!/:5.3.22] ... 22 common frames omitted Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed at org.apache.catalina.core.StandardService.addConnector(StandardService.java:238) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.7.2.jar!/:2.7.2] ... 24 common frames omitted Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1077) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.core.StandardService.addConnector(StandardService.java:234) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 26 common frames omitted Caused by: java.net.SocketException: Permission denied at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:461) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:453) ~[na:1.8.0_392] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) ~[na:1.8.0_392] at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:275) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:230) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1313) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:614) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1074) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 28 common frames omitted
개발자
#aws
#springboot
#배포
답변 1
댓글 0
조회 596
일 년 전 · 김태현 님의 새로운 댓글
sql문 부적합합니다..
spring boot 4 에서 웹개발프로젝트를 진행중입니다.. jsp페이지에서 받아온 searchText값을 쿼리문으로 비교 후 foodinfolist를 반환해주는데 sql developer에서는 SELECT * FROM foodinfolist WHERE food_name LIKE '%' || '치킨' || '%'; 해당 코드가 정상동작 돼서 잘 검색하지만 mapper.xml에서 <mapper namespace="com.springproj.dietwebservice.repository.IFoodInfoDAO"> <select id="findfoodinfo" parameterType="java.lang.String" resultType="com.springproj.dietwebservice.domain.FoodInfoVO">> <![CDATA[ SELECT * FROM foodinfolist WHERE food_name LIKE '%' || #{searchText} || '%' ]]> </select> </mapper> 해당 코드를 실행하면 sql문이 부적합합니다 라고 에러가 발생합니다.. 뭐가 문제인지 모르겠습니다.. searchText: 치킨 으로 데이터도 잘 담겨오는데.. [2m2024-01-31T16:24:22.500+09:00[0;39m [31mERROR[0;39m [35m8208[0;39m [2m---[0;39m [2m[nio-8090-exec-9][0;39m [2m[0;39m[36mo.a.c.c.C.[.[.[/].[dispatcherServlet] [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-00900: SQL 문이 부적합합니다 선배님들 조언부탁드립니다..
개발자
#sql
#spring-boot
답변 4
댓글 2
추천해요 1
조회 581
일 년 전 · 익명 님의 질문
Jotai가 Provider 없이 컴포넌트간의 atom 공유가 가능한 이유
상태관리 라이브러리인 jotai를 사용할때, Provider로 감싸지 않아도 atom 선언과 useAtom을 이용해 컴포넌트간의 공유가 가능한걸로 알고 있는데, 그 이유가 무엇인가요? 내부적으로 context api를 사용하는걸로 알고 있는데 provider가 없이 어떻게 가능한걸까요?
개발자
#리액트
#jotai
#상태관리
답변 0
댓글 0
추천해요 1
조회 86
일 년 전 · 세혁 님의 새로운 댓글
Next.js App router + recoil 적용 방법에 질문이있습니다.
next.js 에 recoil 을 적용하려하니 RecoilRoot 컴포넌트로 감싸줘야하는 부분에서 어려움이 생겼습니다. RecoilRoot 는 react.createContext를 쓰기에 클라이언트 컴포넌트에서 사용해야 한다는 것인데 이를 위해 RecoilRoot만을 return 하는 클라이언트 컴포넌트를 만들고 root layout 에서 불러와 그것으로 children을 감싸주면 된다는 것이였습니다. https://velog.io/@pakxe/Next.js-Recoil%EC%9D%84-Next.js-%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0%EA%B3%BC-children-prop-pattern 위 블로그의 마지막 하단을 보면 ``` // ./app/layout.tsx // 보이는 코드 <RecoilRoot> {children} </RecoilRoot> // 실제 코드 <RecoilRoot children={<Home/>}/> ``` 처럼 동작하기에 RecoilRoot 클라이언트 컴포넌트 하위에 서버 컴포넌트 들이 들어가는게 아니라 RecoilRoot 와 chilren 이 같은 부모를 두고 서로 부모자식 관계가 아니니 클라이언트 컴포넌트 하위에 서버 컴포넌트가 들어가는 것이 아니다 라고 하는데 이 부분이 이해하기 어려워서요... 실제코드 부분을 보면 RecolRoot 가 children 이라는 컴포넌트를 파라미터로 받기에 파라미터로 받는 과정에서 이미 렌더링이 되어 넘어가기에 Recoil Root는 서버 컴포넌트인 children이 렌더링된 상태에서 파라미터로 받아 서버 컴포넌트가 클라이언트 컴포넌트 하위에서 렌더링 되는 것이 아니다.. 가 맞는 것인지 궁금합니다.
개발자
#next.js
#react
#recoil
답변 2
댓글 1
조회 644
일 년 전 · ㅇㅇㅇ 님의 새로운 댓글
프론트엔드개발자 미니 프로젝트
안녕하세요! 현재 왔다갔다 고민 중인 그런.. 상황입니다 ㅎㅎ 고민인 사항은 기존 todolist 를 리팩토링하는게 좋을지, 새로운 프로젝트를 만들어보며 좋을지 가 고민 사항입니다. 기존에 리액트를 학습하면서 정말 기본의 crud 만 구현해놓은 프로젝트가 있습니다. 그 흔한 context api를 사용하지 않은 상태입니다..ㅎㅎ zustand, tanstack query, ts 등등 이 스택들을 이제 막 익혀보려는 상황에 있는데요.. (습득 아닙니다 이제 막 시작하려고해요ㅠㅠ) 공식문서를 읽는다 해도 직접 사용해보지 않아서 잘 모르겠더라구요.. 그래서 저 스택들의 기여가 적어도 일단 적용은 해서 익혀볼까? 라는 마음인데 기존의 todolist 에 뭐 검색, 최신순 정렬 등의 기능을 추가하면서 저 스택들을 사용해볼까 , 아님 아예 새로운 미니 프로젝트를 각잡고 만들어보는게 나을까 싶은 고민입니다.. todo가 작은 프로젝트인데 규모에 비해 과하게 기술을 적용하는건가? 싶기도 하고 포트폴리오에도 넣어야하는데 todo 넣는게 맞나.. 다들 이렇다 할 프로젝트를 내놓는 마당에 아예 각잡고 새로운 프로젝트를 해야하는지 참 고민인 시점입니다 ㅠㅠ 아니면 리액트쿼리, zustand 등 익히기 위해서 괜찮은 학습방법에 대해 공유해주셔도 감사할 것 같습니다. 쏟아지는 기술들에 도대체 뭐부터 해봐야하나 정신이 혼미한 상태이므로...ㅎㅎ 도움이나 의견 주시면 감사하겠습니다 !!
개발자
#프로젝트
#고민
#프론트
답변 2
댓글 7
조회 353
일 년 전 · 익명 님의 질문
React - native 학습 러닝 커브에 대한 질문입니다.
안녕하세요. 올해 하반기에 부트캠프를 통해 React 프론트엔드 및 MERN 스택 기반의 백엔드를 어느 정도 맛본 프론트엔드 지망생입니다. 현재 어느 React 라이브러리와 firebase를 이용해 작은 사이드 프로젝트를 협소하게나마 배포해본 경험이 있습니다. 다음 사이드 프로젝트를 진행할 계획이 있는데 많은 사례에서 앱으로의 출시를 위해 React - native 기술 스택을 택하는 경우가 많더라구요. 그래서 React - native가 리액트를 기반으로 만들어진 모바일 기술인 만큼 연관성이 꽤나 높다고 들었는데 해당 기술을 습득하는 데에 어느 정도 걸리는지 여쭤보고 싶습니다. 당연히 기본적인 리액트의 훅에 대한 이해는 있으며 리덕스와 contextAPI를 기반으로 주로 상태 관리를 하고 recoil , React query 같은 것은 찍먹을 약간 해본 상태입니다. 또한 리액트 네이티브 학습은 그냥 바로 공식 문서를 보면서 따라갈지, 아니면 유튜브 등에 올라온 강의를 수강할지 여쭤보고 싶습니다.
개발자
#react-native
#react
#프론트엔드
#모바일
답변 0
댓글 0
조회 173
일 년 전 · 류호준 님의 답변 업데이트
카페24 웹호스팅 중 cors에러 관련 질문입니다.
정부 지원사업으로 3개월짜리 인턴십 진행중인 신입개발자 입니다. 현재 회사에는 시니어 개발자나 선임 개발자가 없어서 정말 초짜 백엔드 1명, 프론트 1명이서 프로젝트르 진행중입니다. node.js - react로 구현한 웹페이지를 카페24 웹호스팅을 통해 배포중입니다. (호스팅 : node.js 호스팅 일반형 / 도메인: htcoummunity.cafe24app.com) 배포된 웹페이지를 테스트 도중 cors에러를 만났습니다. 상황= 로그인 버튼을 누르면 로그인 정보를 체크하는 API가 cors에러로 인해 응답을 받아오지 못하고 있습니다.(모든 api가 안됩니다.) 에러메세지= Access to fetch at 'http://localhost:8001/api/signup/checkuser' from origin 'http://htcoummunity.cafe24app.com' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space `local`. POST http://localhost:8001/api/signup/loginEmail net::ERR_FAILED 자체적인 분석으로는 'http://htcoummunity.cafe24app.com' 가 public IP이기 때문에 로컬호스트로 요청하는 api는 리소스의 Private 수준이 더 높기때문에 cors정책에 의해 막힌 것이라고 해석했습니다. 하지만 적절한 해결책은 찾지 못하고 있습니다. Proxy설정까지는 시도해봤지만 문제가 해결되지는 않았습니다. 인턴십이 이제 3일정도 남아서 배포만이라도 깔끔하게 마무리하고 싶은데 해결이 되지 않고 있습니다. 부디 해결책을 제시해주시면 감사하겠습니다!
개발자
#react
#node.js
#cors
#카페24
답변 1
댓글 0
조회 670
일 년 전 · Ed 님의 답변 업데이트
Usecontext와 redux 차이 궁금합니다!
예전에는 usecontext 만으로는 상태관리 하기엔 부족하다고 해서 redux를 꼭 공부하라고 배웠는데, 요즘에 들어보면 많이 업데이트 되면서 context 하나만으로도 전역 상태관리가 충분하다 해서요 그런데도 굳이 redux를 사용하는 이유가 따로 있을까요?
개발자
#redux
#usecontext
#context
답변 2
댓글 0
조회 120
일 년 전 · 김인후 님의 새로운 답변
session과 router 처리
안녕하세요. React를 이제 갓 배워 클론코딩에 활용하고 있습니다. 로그인 기능을 구현하고 있는데, React에 useContext 훅이나 Redux 와 같은 유용한 서드파티가 있지만 보통 세션 처리는 서버에서 하는 걸로 알고있습니다. 여기서 생기는 의문이 그럼 처음 서비스에서 세션 정보를 취득했을 때 그 정보를 클라이언트에서 상태 관리하여 사용하는 건지, 아니면 지속적으로 서버와 통신하여 가져오는건지 궁금합니다. 라우터 처리도 비슷한 질문인데요. 서버에도 리다이렉션이 있고, React에도 Router 라이브러리로 리다이렉션을 구현할 수 있는데 각각 어느 상황에서 쓰는건지 구분이 가지 않습니다. 초보적인 질문이라 좀 부끄럽네요.. 감사합니다!
개발자
#react
#express
답변 1
댓글 0
조회 47
2년 전 · 도연 님의 댓글 업데이트
안녕하세요 NextAuth를 사용해서 구글 로그인을 구현하고 있는 중 어떻게 해결해야 할지 모르겠습니다ㅜㅜ...
아래 블로그를 참고하여 route.ts, AuthContext.tsx를 만들고 siginIn 이벤트는 사용하는 컴포넌트의 버튼 요소에 걸어주었습니다. 하지만 버튼을 누르면 404 페이지가 나오면서 url이 http://localhost:3000/api/auth/error로 뜹니다... .env 파일을 수정하고 NextAuthOptions를 사용해서 NEXTAUTH_URL, NEXTAUTH_SECRET 설정도 해보았고, 아래 코드처럼 스택 오버플로우 사이트를 참고해서 적어보기도 했지만 여전히 같은 에러가 반복됩니다... <button onClick={(e) => { e.preventDefault(); signIn('google', { callbackUrl: '/' }); }}> 구글 </button> 404 에러를 해결할 수 있는 방법이 있을까요... https://velog.io/@uni/NextAuth.js-%EA%B5%AC%EA%B8%80-%EB%A1%9C%EA%B7%B8%EC%9D%B8-Next%EB%B2%84%EC%A0%84-13.4.2
개발자
#next.js-13
#nextauth
답변 2
댓글 6
조회 702
2년 전 · 박예진 님의 질문 업데이트
채팅 새로고침시 연결 끊기는 문제
안녕하세요. 현재 Websocket과 stompjs v6.0.0을 활용해 채팅을 구현했습니다. roomId로 여러 채팅방을 만들 수 있게 구현했고, 현재 새로고침을 하지 않는 이상 잘 돌아갑니다. 그러나, 새로고침 할 시에는 바로 연결이 끊겨 이전의 채팅 내역도 보이지 않고, 연결, 구독 내역이 사라집니다 ... 어떻게 reconnect 해야할까요? 단순히 채팅 페이지에서 useEffect로 connect를 다시 하니 이미 연결 구독이 된 상태라고 뜨더라구요 .... ㅠㅠ (고민글을 올렸을 때 채팅방이 생성되고, 연결 구독이 됩니다. 채팅 시작 버튼을 눌렀을 경우에는 본인이 연결 구독이 되어 1대 1로 상대방과 채팅이 시작되는 구조입니다. ) import { CompatClient, Stomp } from "@stomp/stompjs"; import { createContext, useContext, useMemo, useRef } from "react"; import { useSetRecoilState } from "recoil"; import { messageState } from "../../states/chatting"; import audio from "../../assets/audios/chatting.mp3"; const ChatContext = createContext( {} as { connect: (roomId: number) => void; disconnect: () => void; send: (roomId: number, message: string) => void; }, ); export const useChatContext = () => useContext(ChatContext); export function ChatProvider({ children }: any) { const setMessages = useSetRecoilState(messageState); const token = localStorage.getItem("accessToken"); // 채팅 연결 구독 const client = useRef<CompatClient>(); const connect = (roomId: number) => { client.current = Stomp.over(() => { const sock = new WebSocket("wss://m-ssaem.com:8080/stomp/chat"); return sock; }); client.current.connect( { token: token, }, () => { client.current && client.current.subscribe( `/sub/chat/room/${roomId}`, (message) => onMessageReceived(message, roomId), { token: token!, }, ); }, ); return client; }; const onMessageReceived = (message: any, roomId: number) => { const audioElement = new Audio(audio); audioElement.play(); setMessages((prevMessages) => { const updatedMessages = { ...prevMessages, [roomId]: [...(prevMessages[roomId] || []), JSON.parse(message.body)], }; return updatedMessages; }); }; // 채팅 나가기 const disconnect = () => { if (client.current) { client.current.disconnect(() => { window.location.reload(); }); } }; // 채팅 보내기 const send = (roomId: number, message: string) => { if (client.current) { client.current.send( `/pub/chat/message`, { token: token, }, JSON.stringify({ roomId: roomId, message: message, type: "TALK", }), ); } }; const handlers = useMemo(() => ({ connect, disconnect, send }), []); return ( <ChatContext.Provider value={handlers}>{children}</ChatContext.Provider> ); } ----------이 부분은 connect 하는 부분입니다 --------- const { connect } = useChatContext(); const chatRoomId = worryBoard && worryBoard.chatRoomId; const handleStartChatting = () => { navigate(`/chatting`); connect(chatRoomId!!); }; ------------ 채팅 페이지는 따로 있습니다 --------------
개발자
#websocket
#stompjs
#채팅
#chatting
#react
답변 0
댓글 0
조회 327
2년 전 · 이건희 님의 질문 업데이트
ESLINT 어떤 것을 수정해야 내용처럼 fix 되는 현상을 막을 수 있을까요?
안녕하세요~ eslint, prettier에서 제가 무엇을 잘못했는지 계속 아래처럼 코드가 수정되고 있습니다. const res = (await request) < User > (context, `/users/${id}`); 어떻게 하면 고칠 수 있을까요? 1. (await request) 소괄호 제거 2. < User > 제너릭 사이 공백 제거 결론: const res = await request<User>(context, `/users/${id}`) 로 만들고 싶습니다.. 아래는 eslint 적용한 내용 입니다. ``` //eslint.config.js module.exports = { env: { browser: true, es2021: true, }, extends: [ 'plugin:react/recommended', 'airbnb', 'plugin:storybook/recommended', ], parser: '@typescript-eslint/parser', parserOptions: { project: ['./tsconfig.json'], ecmaVersion: 2018, sourceType: 'module', createDefaultProgram: true, }, plugins: ['react', '@typescript-eslint', 'prettier', 'import'], rules: { 'react/react-in-jsx-scope': 'off', 'react/jsx-props-no-spreading': 'off', 'import/prefer-default-export': 'off', 'implicit-arrow-linebreak': 'off', 'react/jsx-filename-extension': [ 2, { extensions: ['.js', '.jsx', '.ts', '.tsx'], }, ], 'object-curly-newline': [ 'error', { ObjectPattern: { multiline: true, minProperties: 2, }, ImportDeclaration: 'never', ExportDeclaration: { multiline: true, minProperties: 3, }, }, ], 'import/extensions': [ 'error', 'ignorePackages', { js: 'never', mjs: 'never', jsx: 'never', ts: 'never', tsx: 'never', }, ], 'import/order': [ 'error', { alphabetize: { order: 'asc', }, groups: [ 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type', ], }, ], 'import/no-unresolved': 'off', }, settings: { 'import/resolver': { typescript: { alwaysTryTypes: true, }, node: { paths: ['src'], }, }, }, }; ```
개발자
#eslint
#prettier
답변 0
댓글 0
조회 79
2년 전 · 익명 님의 질문 업데이트
React와 scss를 사용해서 개발시 style control
React와 scss기반으로 개발시 전체적인 layout과 관련하여 최상위 컴포넌트의 className이나 inline style을 변경해야할 경우에 아래 두 방식중 어떤 것이 좋은 방법일까요?? (1) state(context api) 사용하고 하위 컴포넌트의 전체 재실행 되는 것이 정상이다. (2) querySelector를 통해 직접 DOM 접근하여 하위 컴포넌트의 전체 재실행을 피한다.
개발자
#react
#scss
#dom
답변 0
댓글 0
조회 64
2년 전 · 석이 님의 답변 업데이트
해당 스프링부트 코드 해석 좀 부탁드립니다..
안드로이드에쓸 스프링부트 코드를 따왔는데 제가 잘이해사 안되서 상세히 알려주실 선배님조언 구합니다 package com.example.teamproject import MyAdapter import android.content.Context import android.content.Intent import android.icu.lang.UCharacter.GraphemeClusterBreak.L import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Toast import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.example.teamproject.databinding.ActivitySearchBinding import com.example.teamproject.login.LoginActivity import com.example.teamproject.model.RstrModel import com.example.teamproject.review.ReviewActivity import com.google.android.material.bottomnavigation.BottomNavigationView import retrofit2.Call import retrofit2.Callback import retrofit2.Response class SearchActivity : AppCompatActivity() { lateinit var binding: ActivitySearchBinding private lateinit var adapter: MyAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySearchBinding.inflate(layoutInflater) setContentView(binding.root) setSupportActionBar(binding.toolbar) supportActionBar?.setDisplayShowTitleEnabled(false) binding.toolbar.title = "검색" val loginSharedPref = applicationContext.getSharedPreferences("login_prof", Context.MODE_PRIVATE) val userId = loginSharedPref.getString("m_id", null) val userService = (applicationContext as MyApplication).userService // 하단바 초기값 설정 val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottommenu) bottomNavigationView.selectedItemId = R.id.second_tab // 하단바 선택시 이벤티 binding.bottommenu.setOnItemSelectedListener {item -> when(item.itemId) { R.id.first_tab -> { val intent = Intent(this@SearchActivity, MainActivity::class.java) startActivity(intent) } R.id.third_tab -> { val intent = Intent(this@SearchActivity, ReviewActivity::class.java) startActivity(intent) } R.id.fourth_tab -> { if ( userId == null){ val intent = Intent(this@SearchActivity, LoginActivity::class.java) startActivity(intent) } else { val intent = Intent(this@SearchActivity, MyDining::class.java) startActivity(intent) } } R.id.fifth_tab -> { if ( userId == null){ val intent = Intent(this@SearchActivity, LoginActivity::class.java) startActivity(intent) } else { val intent = Intent(this@SearchActivity, MyProfilePage::class.java) startActivity(intent) } } } true } binding.searchBtn.setOnClickListener { var rstr_nm = binding.searchText.text.toString() val getnamecount = userService.getNamecount(rstr_nm) getnamecount.enqueue(object: Callback<Int>{ override fun onResponse(call: Call<Int>, response: Response<Int>) { if ( response.isSuccessful ){ val ncount = response.body() if (ncount != null) { if ( ncount >= 1){ val getname = userService.getName(rstr_nm) getname.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val rstrlist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, rstrlist) binding.recyclerView.addItemDecoration( DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL) ) } } override fun onFailure( call: Call<List<RstrModel>>, t: Throwable ) { call.cancel() } }) } else { Toast.makeText(this@SearchActivity, "검색 결과가 없습니다!", Toast.LENGTH_SHORT).show() } } } } override fun onFailure(call: Call<Int>, t: Throwable) { call.cancel() } }) } binding.area1.setOnClickListener { val rstr_addr = binding.area1.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area2.setOnClickListener { val rstr_addr = binding.area2.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area3.setOnClickListener { val rstr_addr = binding.area3.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area4.setOnClickListener { val rstr_addr = binding.area4.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area5.setOnClickListener { val rstr_addr = binding.area5.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area6.setOnClickListener { val rstr_addr = binding.area6.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.area7.setOnClickListener { val rstr_addr = binding.area7.text.toString() val getarea = userService.getArea(rstr_addr) getarea.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type1.setOnClickListener { val rstr_list = binding.type1.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type2.setOnClickListener { val rstr_list = binding.type2.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type3.setOnClickListener { val rstr_list = binding.type3.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type4.setOnClickListener { val rstr_list = binding.type4.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type5.setOnClickListener { val rstr_list = binding.type5.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } binding.type6.setOnClickListener { val rstr_list = binding.type6.text.toString() val gettype = userService.getType(rstr_list) gettype.enqueue(object: Callback<List<RstrModel>>{ override fun onResponse( call: Call<List<RstrModel>>, response: Response<List<RstrModel>> ) { if ( response.isSuccessful ){ val arealist = response.body() binding.recyclerView.adapter = MyAdapter(this@SearchActivity, arealist) binding.recyclerView.addItemDecoration(DividerItemDecoration(this@SearchActivity, LinearLayoutManager.VERTICAL)) } } override fun onFailure(call: Call<List<RstrModel>>, t: Throwable) { call.cancel() } }) } } }
개발자
#스프링부트
#안드롱디ㅡ
#안드로이드
#spring\
#spring
답변 1
댓글 0
보충이 필요해요 3
조회 182
2년 전 · 김하림 님의 새로운 답변
getServerSideProps의 context를 nextjs13에서 사용하기.
현재 nextjs12로 짜여진 코드를 nextjs13으로 옮기는 작업을 하고 있습니다. 기존에 getServerSideProps의 context를 이용하여 많은걸 하고 잇었는데 nextjs13에서 getServerSideProps를 사용할 수 없게 되면서 애를 먹고 있습니다. context의 req, res, resolvedUrl 등을 nextjs13에서도 사용하고 싶은데 어떻게 해야 하나요 ㅜㅜ ??
개발자
#nextjs13
답변 2
댓글 0
추천해요 1
조회 1,091
2년 전 · 김병연(Vintz) 님의 새로운 댓글
리액트 상태관리, 어떻게 하고 계신가요?
안녕하세요, 주니어 프론트엔드 개발자입니다. 현재 저는 어드민 프로젝트를 리액트로 만드는 작업을 하고 있습니다. 프로젝트 규모가 꽤 크다보니, 상태관리에 대해 많은 고민을 하고 있어요. 그 동안 내가 알던 리액트가 맞나 싶을 정도로 상태에 대해 다시 생각해보고 있습니다. 처음에는 상태관리 라이브러리 없이 작업을 했습니다. 나름대로 기획서를 보고 상태를 저마다의 컴포넌트에 넣어 사용했어요. 그런데 진행하다보니 다른 곳에서도 해당 상태를 사용해야하는 일이 빈번하게 발생해서, 수정하는 시간이 길어질 때가 많았습니다. 그래서 결국 전역 상태관리 라이브러리(zustand)를 사용하게 됐어요. 막상 사용해보니 정말 좋았습니다. 제가 생각한 장점은 다음과 같아요. - 사용할 컴포넌트에서 바로 사용이 가능하다. - 스토어에서 뽑아 사용하다보니 데이터 동기화가 비교적 쉬웠어요. - 스토어별로 파일을 분리하고, 해당 로직만 담겨 있어 파악하기가 쉽다. - 며칠 뒤에 봐도 이어서 작업하기가 좋았습니다. - 이전에는 상태들이 어느 컴포넌트에서 쓰이는지 헷갈릴 때가 많았어요. - 컴포넌트는 뷰 컴포넌트로, 비즈니스 로직이 스토어에 담겨 있어서 좋았어요. 제 짧은 경험에 느낀 장점들로 계속 사용하고는 있지만 자꾸 의문이 듭니다. 거의 모든 상태들을 스토어에 담아 사용하다보니 '전역' 라이브러리의 역할에 맞지 않다고 생각이 들어요. 페이지 간에 공유하는 상태는 없다보니 context api도 고려해봤지만, zustand와 달리 하위 컴포넌트가 리렌더링이 되고, 해당 api는 다크 모드같은 기능에 쓰고, 러닝커브가 비교적 적은 zustand를 선택했습니다. 결론은, 여러분은 상태관리를 어떻게 하고 계신지 궁금합니다. 어떠한 기준이 있는지, 전역 상태관리 라이브러리는 어떤 경우에 쓰는지 등 제가 경험이 적고 혼자 프론트 개발을 하다보니 모든 의견 하나하나가 소중합니다. 리액트 상태관리에 대한 선생님들의 고견을 부탁드립니다.
개발자
#react
#상태관리
#zustand
#hooks
답변 1
댓글 1
추천해요 8
보충이 필요해요 1
조회 1,669
2년 전 · 시간 님의 새로운 댓글
NextJS에서 Component 호출 할 때 getServerSideProps 호출 방법이 있나요?
JSTL 이나 Thymeleaf 하다가 NextJS 하려니 많이 해메고 있네요. @,@;;; 우선 시나리오는 ProductList.html 페이지에서 서버로부터 상품 목록 주욱 받아 화면 출력 하는 것 까지는 했어요. 이때 서버 목록은 getServerSideProps 함수에서 받아 처리 했구요. 이제 상품 이름 클릭 했을 때 상세 정보를 Layer 화면으로 띄우려는데 그게 잘 안되네요. Thymeleaf에선 해당 페이지만 빌드 돼 html 형태로 받아 올 수 있었는데 nextjs는 어떻게 해야 하는지 모르겠어요. // 상품 상세 내용 export default function ProductModalLayer({ product }:IProduct) { return (<div> {product.name}</div>); } export async function getServerSideProps(context: any) { // 서버 통신으로 product 상세 정보 전달 const data = ... 생략... return { props: { product: data, }, }; } ------ ProductList 부분에서 상품 이름을 클릭 했을 때 const ModalView = dynamic(() => import("../ProductModal.layer")); // 선언 ... // 화면 그리기 <ModalView seq={prod.productSeq}></ModalView> 이런 형식으로 호출 하니까 getServerSideProps를 호출 하지 않네요. 다른 방법으로 fetch를 이용해 호출 해 봤는데 const res = await fetch("/ProductModal.layer?seq=" + seq); const content = await res.text(); 이렇게 하면 getServerSideProps를 호출 하지만 html Tag가 엄청 붙어 나오고 return 의 결과가 아닙니다. getServerSideProps를 고집 하는 이유는 서버 호출 인터페이스는 꼭 서버에서 이뤄지게 하고 싶어서에요. 브라우져 디버거로 노출 안되게 하고 싶어서. 힌트나 방법좀 부탁 드려요~ 다시 JSTL 이나 Thymeleaf로 돌아 갈 수 없어~~~~
개발자
#nextjs
#react
#ssr
#getserversideprops
답변 1
댓글 1
조회 185