질문 남겨주셔서 감사합니다. 막히면 언제든 무엇이든 자주 질문 던져주세요. 수학/과학이나 알고리즘과는 달리 업무자동화 코딩은 고민해서 풀리는 경우가 정말 드뭅니다. 다시 말씀드리지만, 질문을 자주자주 남겨주세요. 저도 최대한 빠르게 회신 드리겠습니다. 당부드릴 두 가지가 있습니다. ① 가급적 구체적으로 설명해주세요. ② 특정 챕터 관련 질문 남겨주실 때는, 어느 챕터인지 알려주세요ㅜ ==================================== 안녕하세요 일코님 메일드렸는데 많이 바쁘신듯 하네요~ ㅠ.ㅠ 열심히 구현하고 있는데, (1) 블록 설정된 내에서 표가 몇개 있는지 확인 하는것 (2) 표의 갯수를 확인하고 차례로 그 표를 찾아서 진입하는 방법 을 잘 모르겠습니다. (3) 이전에 블록 내에서 텍스트를 검색하는 방법을 알려주셨었는데, 그것을 잘 활용하고 있는데요. def 블록내_텍스트_포함_여부(text): try: hwp.InitScan(Range=0xff) # 0xff <<선택된 범위 내에서 검색 except: hwp.InitScan(range=0xff) _, range_text = hwp.GetText() # 텍스트만 추출 hwp.ReleaseScan() # releaseScan이란 함수는 스캔을 해제. hwp.HAction.Run("MoveParaEnd") return f"{text}" in range_text # 이경우, 해당 target이 text에 포함되어있으면 True, 아니면 False를 반환. python 터미널에서 행별로 코드를 실행할 때, Range=0xff 를 했을때 올바른 파라미터가 아니라고 오류가 뜰때가 많더라구요 근데 또 이걸 py파일을 실행해서 했을떄는 되는거 같구요. 그래서 그냥 try except 구문을 쓰고있는데, 제가 뭔가를 잘못사용하고 있는 걸까요? 감사합니다.
(강의 색션 7_8 - 14:30) 안녕하세요 선생님. 좋은 강의 만들어 공유해 주셔서 진심으로 감사드립니다. Pydantic 모델 초기화 과정에서 아래의 코드처럼 Optional 이 설정하지 않으면 Swagger UI 에서 입력 값이 null 이여서 엔티티 타입 불일치로 422 에러가 발생합니다. 또한, parse_user_form에서 Optional 체크를 하고 Item에서는 별도로 설정하지 않으면 같은 에러가 발생하더군요. Q) FormData 부분은 Optional 체크를 하지 않아도 되고, pydantic model에서는 반드시 Optional 체크를 해야지만 문제 없이 정상 동작하는 이유에 대한 보충 설명 부탁드려도 될까요? 주석한 부분이 기존 코드입니다. 주석한 부분으로 코드를 변경하면 에러가 발생합니다. class Item(BaseModel): name: str = Field(..., min_length=2, max_length=50) # description: str = Field(None, max_length=500) description: Optional[str] = Field(None, max_length=500) price: float = Field(..., ge=0) # tax: float = None tax: Optional[float] = None @model_validator(mode='after') def tax_must_be_less_than_price(cls, values): price = values.price tax = values.tax # if tax > price: # tax가 NoneType이라 에러가 남. if tax is not None and tax > price: raise ValueError("Tax must be less then price") return values 감사합니다.
useEffect(() => { localStorage.setItem('todoData', JSON.stringify(todoData)); }, [todoData]); 이렇게 작성을 하고, 나머지는 다 주석을 처리했는데도 정상 작동하는 것 같더라구요. 하지만 의문인게 setTodoData((prev) => [...prev, newTodo]); localStorage.setItem('todoData', JSON.stringify([...todoData, newTodo])); 여기도 주석처리를 했는데, 여기는 조금 작성하는 게 다르 지 않나요? handleRemoveClick = () => { setTodoData([]) } 여기도 그렇구요. 그런데 그냥 다 정상 작동 하네요?
로그인 방식을 구현하면서, 쿠키로만 개발할 경우 완전히 백엔드에 의존하게 되어 로컬로, 동시에 키고 개발을 하지 않는이상, 도메인간 불일치를 해결 할 방법이 없어, msw를 사용해야 한다고, 이전에 말씀해주셨습니다!! 보통, 회사나, 개인 소프트웨어를 만들 때 어떤 방식으로 로그인을 주로 만드시는지 조금 알고 싶어 궁금하여 질문을 남깁니다!! 로그인 방식 고찰 로그인 성공시, accessToken을 body로 받고, refreshToken은, httpOnly 쿠키로 받는 경우 (서버에서, DB or Redis를 통해 refreshToken 관리) → 인증 필요 요청 (Bearer accessToken), 리프레시 필요 요청 (refreshToken 심긴 쿠키를 바탕으로 요청) - DB에서 관리하는 것 보다, redis를 통해 관리했을 떄 읽기 속도가 빠름을 확인! 응답: accessToken과 refreshToken 모두 body로 클라이언트에게 전달. 인증 필요 요청과, 리프레시 토큰 재발급 요청 모두 헤더의 Bearer에 accessToken이나, refreshToken을 넣어서 전달.) 현재 방식: accessToken, refreshToken 모두 쿠키로 응답받고, 요청또한, 쿠키를 포함하여 전달. 제로초님은, Next.js를 활용하여, 웹 사이트를 만드실 떄, 어떠한 방식으로 로그인을 구현하시는지 궁금하고, 많은 회사에서 사용하는 방식은 보통 어떤 방식인지도 알고싶습니다!
강의대로 eslint 설정한 후 { "extends" : [ "react-app" ] } npm run dev 하면 아래와 같은 에러가 납니다. VITE v6.0.3 ready in 354 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help 오후 4:41:35 [vite] Internal server error: C:\Dev\fullstack-app\frontend\src\main.jsx 1:1 error Parsing error: The keyword 'import' is reserved ✖ 1 problem (1 error, 0 warnings) Plugin: vite-plugin-eslint File: C:/Dev/fullstack-app/frontend/src/main.jsx at TransformPluginContext._formatError (file:///C:/%EC%94%A8%EC%97%94%ED%8B%B0%ED%85%8C%ED%81%AC/Dev/fullstack-app/frontend/node_modules/vite/dist/node/chunks/dep-yUJfKD1i.js:47158:41) at TransformPluginContext.error (file:///C:/%EC%94%A8%EC%97%94%ED%8B%B0%ED%85%8C%ED%81%AC/Dev/fullstack-app/frontend/node_modules/vite/dist/node/chunks/dep-yUJfKD1i.js:47153:16) at TransformPluginContext.transform (file:///C:/%EC%94%A8%EC%97%94%ED%8B%B0%ED%85%8C%ED%81%AC/Dev/fullstack-app/frontend/node_modules/vite-plugin-eslint/dist/index.mjs:1:1989) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async EnvironmentPluginContainer.transform (file:///C:/%EC%94%A8%EC%97%94%ED%8B%B0%ED%85%8C%ED%81%AC/Dev/fullstack-app/frontend/node_modules/vite/dist/node/chunks/dep-yUJfKD1i.js:47001:18) at async loadAndTransform (file:///C:/%EC%94%A8%EC%97%94%ED%8B%B0%ED%85%8C%ED%81%AC/Dev/fullstack-app/frontend/node_modules/vite/dist/node/chunks/dep-yUJfKD1i.js:40852:27) 오후 4:41:35 [vite] Pre-transform error: C:\Dev\fullstack-app\frontend\src\main.jsx 1:1 error Parsing error: The keyword 'import' is reserved 파싱 오류 같은데 어느 설정파일을 수정해야 할까요?
- 학습 관련 질문을 남겨주세요. 질문을 상세히 작성하면 더 좋습니다. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요, coroutine 강의를 듣고 ktor server 공부를 하는 중에 delay 관련 질의가 생겨 글 남깁니다. delay 의 경우 coroutine 이 스레드를 양보하고, 일정 시간 후에 다시 스레드가 비어있으면 점유하는 형식으로 진행될텐데, 아래와 같은 경우 delay 이후 코드가 실행되지 않습니다. 사용자 → KTOR Server → suspend function call → loop { logic → 너무 많은 동작을 제한하기위한 delay } ktor 는 기본적으로 요청이 IO Dispatcher 를 사용하는 것 같은데, coroutine 에서 delay 이후 기능이 동작하지 않는 것에 대한 이유가 있을까요..? (강의랑 무관한 내용이라 죄송합니다 ㅠ.ㅠ) /* Routing.kt */ fun Application.configureRouting(searcher: BaseSearcher) { routing { post("/search") { val params = call.receive<Map<String, String>>() searcher.logging("Received POST request with params: $params") val result: List<BaseDTO> = searcher.search(params) searcher.logging("POST Result: $result") call.respond(HttpStatusCode.OK, mapOf("result" to result)) } get("/") { call.respondText("Hello World!") } } } /* Searcher.kt */ /** * 함수 이름 : search * 내용 설명 : 입력된 map<string, string> param 을 바탕으로 요청 전송 및 응답 반환 */ override suspend fun search(searchParam: Map<String, String>): List<SimpleSearchLandResultDTO> { // 별도의 Job 으로 분리해서 오류시 상위 전파 제한 return HttpClient(CIO).use { client -> val parseResultLst: MutableList<SimpleSearchLandResultDTO> = mutableListOf() try { val initRequestResultDto: SimpleSearchResultDTO = sendFormedRequest(client, SearcherConst.URL_MAIN_PAGE, false) // 기본 페이지 요청이 성공했을 때 다음 요청을 진행 if (initRequestResultDto.isSuccess) { val mutableSearchParam = searchParam.toMutableMap() delay(300) while (true) { val eachPageSearchResultDto: SimpleSearchResultDTO = sendFormedRequest(client, makeGetUrl(mutableSearchParam), true) // 실패한 경우 종료 if (!eachPageSearchResultDto.isSuccess) { logging("[search] 조회 중 오류가 발생하였습니다.") break } // 결과가 빈 경우도 종료 else if (eachPageSearchResultDto.landSearchResultLst.isEmpty()) { break } // 결과가 있는 경우엔 전부 더해줌 parseResultLst.addAll(eachPageSearchResultDto.landSearchResultLst) logging("[search] result(${eachPageSearchResultDto.landSearchResultLst[0].currentPage} : ${eachPageSearchResultDto.landSearchResultLst}") // 마지막 페이지인 경우 종료 if (eachPageSearchResultDto.landSearchResultLst[0].currentPage == eachPageSearchResultDto.landSearchResultLst[0].maxPage ) { break } else { // 다음 페이지 수집 진행 mutableSearchParam["currentPage"] = (eachPageSearchResultDto.landSearchResultLst[0].currentPage + 1).toString() delay(300) } } } } catch (e: Exception) { logging("[search] search 함수 중 오류가 발생하였습니다. param: $searchParam, exception: $e") } logging("[search] Result : $parseResultLst") // parseResultLst 반환 parseResultLst } } private suspend fun sendFormedRequest(client: HttpClient, url: String, isResultNeed: Boolean): SimpleSearchResultDTO { return try { val response = client.get(url) { headers { append(HttpHeaders.Cookie, cookie.toCookieString()) append(HttpHeaders.Accept, SearcherConst.DEFAULT_HTTP_ACCEPT) append(HttpHeaders.AcceptEncoding, SearcherConst.DEFAULT_HTTP_ACCEPT_ENCODING) append(HttpHeaders.Connection, SearcherConst.DEFAULT_HTTP_CONNECTION) append(HttpHeaders.AcceptLanguage, SearcherConst.DEFAULT_HTTP_ACCEPT_LANGUAGE) append(HttpHeaders.UserAgent, SearcherConst.DEFAULT_HTTP_USER_AGENT) } } cookie.putAll(response.headers[HttpHeaders.SetCookie]?.split(";")?.map { it.split("=") }?. filter { it.size == 2 }?.filter { it[1] != "/" && it[1].isNotEmpty() }?.associate { it[0] to it[1] } ?: mapOf()) if (response.status != HttpStatusCode.OK) { SimpleSearchResultDTO(false) } else { SimpleSearchResultDTO(true, if(isResultNeed) parseData(response.bodyAsText()) else mutableListOf()) } } catch(e: Exception) { logging("[sendFormedRequest] Error : $e", Level.ERROR) SimpleSearchResultDTO(false) } }
11:42 아래와 같이 for in을 배열에서도 사용이 가능한 것 같습니다! 다만 권장되지는 않는 방법이라고 하네요. let arr = [1, 2, 3]; for (let i in arr) { console.log(arr[i]); } 권장되는 방법: for...of, 일반 for 루프, forEach() 메서드 등
먼저 next와 react의 버전은 각각 15버전과 19버전입니다 next 15 부터는 http.ts 의 코드가 간결하게 바뀌어서 적용해보던 중 세팅 단계에서 해당 오류가 발생하였습니다 TypeError: Cannot read properties of undefined (reading 'url' 구글에 검색해보니 최신버전에서도 발생하는 것 같습니다 ㅠㅠ
[문제점] MSW의 nodejs Server를 Server-Side 에서 실행하려고 할 때 Module not found Error '_http_common' 와 같은 에러 발생으로 빌드가 실패하는 상황을 겪고 있습니다. 저만 겪고 있는 상황인지 싶지만 질문 드립니다. [현상황] 아래와 같이 SSR Component안에서 API를 사용하여 데이터를 받아온 후 화면을 그리고나면, export const Home = async () => { const res = await fetch("https://api.github.com/users/zerocho"); const data = await res.json(); return ( <div className="flex flex-1 items-center justify-center"> <h1>{data.name}</h1> <img src={data.avatar_url} alt={data.name} className="rouneded" /> </div> ); }; 아래와 같은 화면을 확인 할 수 있습니다. 이를 MSW의 Server-side를 사용하기 위해서 Layout단에서 server를 listen하도록 실행하면 if ( process.env.NEXT_RUNTIME === "nodejs" && process.env.NODE_ENV !== "production" ) { const { server } = require("@/mocks/http"); server.listen(); } export default function RootLayout({ children }: { children: React.ReactNode; }): JSX.Element { return ( <html lang="en"> <body className={inter.className}> <MSWProvider> <Suspense>{children}</Suspense> </MSWProvider> </body> </html> ); } 아래와 같은 Build Error로 Module not found: Can't resolve '_http_common' 나게 됩니다. [찾아본 원인?] _http_common 이 Node.js built-in module인데, Next.js Webpack의 config에서 해당 module을 자동 import 하지 않아서 발생하는 에러라고 합니다. (출처: https://github.com/mswjs/msw/issues/2291 ) [시도한 해결 방안 1] - src/instrumentation.ts 파일을 아래와 같이 추가. export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") { const { server } = await import("./mocks/http"); server.listen(); } } - next.config.js를 아래와 같이 수정 /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, transpilePackages: ["@repo/ui"], experimental: { instrumentationHook: true }, }; 결과 동일 [시도한 해결방안 2] - next.config.js에 webpack 내용 추가 /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, transpilePackages: ["@repo/ui"], experimental: { instrumentationHook: true }, webpack: (config, { isServer }) => { if (isServer) { if (Array.isArray(config.resolve.alias)) // server일시 browser를 제외 시킨다 config.resolve.alias.push({ name: "msw/browser", alias: false }); else config.resolve.alias["msw/browser"] = false; } else { if (Array.isArray(config.resolve.alias)) config.resolve.alias.push({ name: "msw/node", alias: false }); else config.resolve.alias["msw/node"] = false; } return config; } }; 결과 동일 [추가 조사한 내용들] - 현재 github issue에 아래와 같이 등록되어 있습니다. https://github.com/mswjs/msw/issues/2291 Server-Side를 사용하지 않고도 MSW를 사용할 수는 있지만, 해결 방안이 있을지 해서 질문드립니다!
[0] Failed running 'server/index.js' [1] [1] VITE v4.4.4 ready in 271 ms [1] [1] ➜ Local: http://localhost:5173/ [1] ➜ Network: use --host to expose [0] Restarting 'server/index.js' [0] file:///Users/kim-yongmin/test-example-shopping-mall/server/index.js:9 [0] import productsJSON from './response/products.json' assert { type: 'json' }; [0] ^^^^^^ [0] [0] SyntaxError: Unexpected identifier 'assert' [0] at compileSourceTextModule (node:internal/modules/esm/utils:337:16) [0] at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:164:18) [0] at callTranslator (node:internal/modules/esm/loader:439:14) [0] at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:445:30) [0] at async ModuleJob._link (node:internal/modules/esm/module_job:106:19) [0] [0] Node.js v22.5.1 [0] Failed running 'server/index.js' 3.1 강의 시청 후 test-example-shopping-mall 브랜치에서, 작업을 시작할려고, 서버와 프로젝트를 모두 킬려고 하는데 잘 동작하지 않습니다. 이에 대한 해결방법이 있을까요?
안녕하세요 TextField 커스텀 관련하여 여러 기능을 살펴보고 있는데요. 구글에서 찾아봐도 Cursor의 두께를 설정하는 프로퍼티를 찾지 못하여서 질문드립니다. Cursor를 커스텀하는 방법이 있나요? 두께를 줄이거나 높이를 낮추는 등의 커스텀을 진행하고 싶습니다. 감사합니다.
안녕하세요, 저는 3년차 Spring 개발자입니다. 때문에 앱 개발에 대한 지식이 부족한 상황이라서 해당 방법론이 다른 개발 환경에도 적용되는지 궁금합니다. 제가 토이 프로젝트로 Flutter를 사용하여 앱을 만든 적은 있는데 이번 강의를 들으면서 강의 내용을 적용하기 위해 Android 개발을 다시 학습 해야할 지 고민 입니다. 다른 개발 환경에도 적용할 수 있는지 제 상황에 Flutter와 Android 중 어떤 것을 추천하시는지 감사합니다!
안녕하세요 실습 코드에서 반복문 내 전략 구현 부분에 강의 설명과 코드 내용이 일치하지 않는 것 같아서 질문 드립니다. 종가가 3일 최저가인지 여부를 체크하는 코드에서 rolling 함수인자를 3으로 맞춰서 새로 컬럼을 추가한 뒤, 종가를 data['3d_min']과 비교해줘야하는게 맞을까요? 강의 코드는 if data['close] == data['5d_min'] 적혀 있어서 질문드립니다.
SignupModal 에서 에러가 하나 나오는데 관련해서 질문드립니다. S2322: Type '(formData: FormData) => Promise<{ message: string; } | undefined>' is not assignable to type 'NonNullable<string | ((formData: FormData) => void | Promise<void>) | undefined>'.<br/>Type '(formData: FormData) => Promise<{ message: string; } | undefined>' is not assignable to type '(formData: FormData) => void | Promise<void>'.<br/>Type 'Promise<{ message: string; } | undefined>' is not assignable to type 'void | Promise<void>'.<br/>Type 'Promise<{ message: string; } | undefined>' is not assignable to type 'Promise<void>'.<br/>Type '{ message: string; } | undefined' is not assignable to type 'void'.<br/>Type '{ message: string; }' is not assignable to type 'void'. 이런 에러가 나옵니다. formData 의 타입이 정확하지 않아서 생기는 에러 같습니다. 근데 정상적으로 실행은 됩니다. 제 꺼에선 이렇게 에러가 나오는데 제로초님 화면에서는 에러가 나오는 것 같지 않아서 어떻게 그렇게 된 것인지 궁금해서 질문 남깁니다. 감사합니다.
안녕하세요. 섹션8 진행하던 중 오류 해결에 도움이 필요해 글 남겨요.. Axios 인터셉터와 Access Token, Refresh 토큰 이용한 Access 토큰 자동 갱신 강의 내용의 코드를 강사님처럼 입력했는데 계속 오류가 납니다.. 콘솔 화면에 나타난 오류 찾아보니 TypeError: Cannot read properties of undefined (reading 'map') 오류가 serverData.dtoList 가 정의되지 않아서 발생했다고 하는데 어떻게 처리 해야 할지 모르겠어요. 참고로 강사님과 코드 내용이 같아 제 코드는 따로 첨부하지 않았어요. 필요하시면 첨부 하겠습니다.
많은 분들이 memo 기능 관련하여 문의 주신것 같은데 내용이 다 동일하네요.. 영상을 보면 변경 전/후 전부다 하이라이트가 표시가 되어서 리렌더링이 발생하는지 시각적으로 확인이 안됩니다. 문의 남기신 글에는 console.log로 확인을 하라고 하시는데.. 그럴것 같으면 강의 내용 자체가 바껴야 되는거 아닌가요?? 이 부분이랑 context 설명하는 부분도 마찬가지인데요.. context 설명할때 onUpdate, onDelete, onCreate는 useCallback을 사용하여 재생성을 방지하게 이미 설정되어있는데, 왜 memo 기능을 써야하나요?? 이 부분도 설명할때 화면상에 하이라이트가 전과 후 다 발생하는데.. 강사님 혼자 뭐 없어진거 확인하는데.. 화면상으로 전혀 확인이 안되는데.. 혼자 진행하시니 혼란스럽네요.. 확실하게 딱 표시가 나는게 아니라면 그에 대한 설명이 있어야 하지 않을까 싶습니다.