tl.set('#emart .pick', { opacity: 0 }) .to(map, { scale: 1, x: 0, y: 0 }) .set('#emart .pick', { opacity: 1 }) .fromTo('#emart .path', { strokeDashoffset: 496 }, { strokeDashoffset: 0 }) .to( '#emart .pick', { motionPath: { path: '#emart .path', align: '#emart .path', alignOrigin: [0.5, 0.5], }, }, '<' ); 위 코드에서 맨 처음 set 으로 opacity: 0 을 줘서 pick을 안 보이게 한 다음에 후에 다시 set으로 opacity: 1을 주게 되는데요 궁금한 것이 아직 순서상 motionPath 가 실행될 차례가 아니어서 마트 위치에서 pick 이 보여질 것인데 어째서 강남역 위치에서 부터 보여 지게 되는지 궁금합니다. 아래에 있는 set을 위로 올려서 tl.set('#emart .pick', { opacity: 0 }) .set('#emart .pick', { opacity: 1 }) .to(map, { scale: 1, x: 0, y: 0 }) 이렇게 위치를 바꾸면 그때서야 제가 이해한 형태로 움직이게 되네요. 왜 그런지 궁금합니다.
본 강의에서는 resize 핸들러를 사용해서 구성이 되었는데, (function () { const houseElem = document.querySelector(".house"); window.addEventListener("scroll", function () { const maxScrollValue = document.body.offsetHeight - window.innerHeight; const zIndex = (pageYOffset / maxScrollValue) * 880 - 900; houseElem.style.transform = `translateZ(${zIndex}vw)`; }); })(); 이런식으로 scroll 이벤트 내부에 maxScrollValue를 사용하면 화면이 height이 변경되더라도 문제가 없는게 아닐까 생각이 되서요! 여러가지 방법이 있을 수 있겠지만 scroll 이벤트 안에 넣은게 아닌 resize 이벤트에 넣은 이유가 maxScrollValue이 재사용성될 가능성이 있기 때문일까요??
function sum2(left, right){ return left+right; } document.write(sum2(2,3)+'<br>'); document.write('<div style="color:red">'+sum2(2,3)+'</div>'); document.write('<div style="font-size:3rem;">'+sum2(2,3)+'</div>'); sum2 함수의 출력 결과와 아래 sum1 함수의 출력 결과가 다른 이유를 알고 싶습니다. function sum(left, right){ document.write(left+right+'<br>'); } document.write(sum(2,3)+'<br>'); document.write('<div style="color:red">'+sum(2,3)+'</div>'); document.write('<div style="font-size:3rem;">'+sum(2,3)+'</div>'); sum도 똑같이 출력해봤는데, 중간에 undefined가 함께 출력되더라고요. 확인해보니 리턴값이 없는 경우에 udefined가 출력된다고 하던데, 그 이유가 궁금합니다. 이전 26강 실습에서는 다음과 같이 출력했을 때 아무 문제 없었는데, 무엇이 다른걸까요? 한번 write한걸 다시 write하는 과정에서 생기는 문제인걸까요? onePlusOne(); function sum(left, right){ document.write(left+right+'<br>'); } sum(2,3); // 5 sum(3,4); // 7
안녕하세요~ 데이터베이스 이해와 실습 CRUD 실습을 진행하다가 오류로 인하여 다음차시 진행이 불가하여 질문드립니다. PS C:\Users\폴더이름\Desktop\database> node db.js Error: querySrv ENOTFOUND _mongodb._ tcp.cluster0.mongodb.net at QueryReqWrap.onresolve [as oncomplete] (node:internal/dns/promises:291:17) { errno: undefined, code: 'ENOTFOUND', syscall: 'querySrv', hostname: '_mongodb._ tcp.cluster0.mongodb.net ' 관련하여 챗GPT에 오류 내용을 검색해본 후 원인 및 해결방법에 대해 아래 내용을 얻을 수 있었는데요 인터넷 연결 확인: 인터넷 연결이 정상적으로 이루어지고 있는지 확인하세요. 특히, 네트워크에 제한이 있거나 프록시 서버를 사용하는 경우 문제가 발생할 수 있습니다. DNS 설정 문제: DNS 설정 문 제로 인해 _mongodb._tcp.cluster0.mongodb.net 도메인이 해결되지 않을 수 있습니다. DNS 서버를 Google Public DNS(8.8.8.8, 8.8.4.4)로 변경하여 문제가 해결되는 지 확인해보세요. Windows에서 DNS 설정 변경 방법: 제어판 > 네트워크 및 인터넷 > 네트워크 및 공유 센터 > 어댑터 설정 변경 으로 이동합니다. 사용 중인 네트워크 연결을 마우스 오른쪽 버튼으로 클릭하고 속성 을 선택합니다. 인터넷 프로토콜 버전 4 (TCP/IPv4) 를 선택한 후 속성 을 클릭합니다. 하단에 있는 다음 DNS 서버 주소 사용 을 선택하고, 8.8.8.8 과 8.8.4.4 를 입력합니다. 설정을 저 장하고 다시 시도해보세요. MongoDB Atlas의 클러스터 주소 확인: cluster0.mongodb.net 이 아니라 클러스터의 정확한 호스트명을 사용하고 있는지 확인하세요. MongoDB Atlas에서 클러스터의 연결 문자열을 다시 복사하여 확인하세요. Atlas UI에서 데이터베이스 > Connect > Connect Your Application을 선택하고, 제공된 연결 문자열을 확인하세 요. 예를 들어: bash 코드 복사 mongodb+srv://<username>:<password>@cluster0.mongodb.net/test?retryWrites=true&w=majority useUnifiedTopology 옵션 사용: 최신 버전의 MongoDB 드라이버를 사용하고 있는지 확인하고, useUnifiedTopology 옵션이 활성화되어 있는지 확인하세요. javascript 코드 복사 const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); 방화벽 또는 네트워크 제한: 회사 네트워크나 특정 ISP에서 DNS 쿼리 또는 MongoDB Atlas에 대한 연결을 제한할 수 있습니다. 이런 경우, 다른 네트워크(예: 휴대폰 핫스팟)에서 시도해보거나, 네트워크 관리자에게 문의하세요. SRV 레코드 대신 표준 연결 문자열 사용: SRV 레코드( mongodb+srv:// ) 대신 표준 MongoDB 연결 문자열( mongodb:// )을 시도해보세요. SRV 레코드를 지원하지 않는 네트워크 환경에서 표준 연결이 문제를 해결할 수 있습니다. 현재 회사에서 지급한 노트북으로 진행하여 보안상 문제가 있어 작업이 불가한건지.. 위 내용을 읽어봐도 명확하지 않아 질문드립니다.
안녕하세요. 면접준비에 도움이 될 거 같고 개념적으로도 궁금해서 질문드립니다. 장바구니에서 삭제를 하면 갱신되는데에 동작원리에서 처음엔 router.replace(router.asPath) 때문에 url이 변경되진 않아도 단순하게 /cart 로 이동이란 동작을 해서 페이지를 다시 그린다고 생각했습니다. CartList 는 CartPage 의 자식 컴포넌트이다. CartPage 는 getServerSideProps 로 서버에서 받아온 데이터를 프롭스(carts)로 받으며, 그 프롭스를 CartList 에게 전달해주고 있다. CartList 는 부모컴포넌트에게 받은 carts 프롭스를 통해 장바구니 목록을 보여주고 있다. 장바구니에서 상품을 삭제하면, 선택한 상품을 서버에서 삭제하고 router.replace 를 통해( router.push 도 동일) 현재 페이지(asPath)인 /cart 로 이동한다. /cart 페이지(즉, CartPage.jsx )가 리렌더링된다. 리액트는 리렌더링되면 컴포넌트의 모든 코드를 다시 실행하게 된다.(고 알고 있습니다.) 그로 인해 getServerSideProps 가 다시 실행되고 갱신된(장바구니에서 상품을 삭제한) 데이터를 다시 CartPage 에게 프롭스로 내려주게 된다. 프롭스가 변경됐으니 자식 컴포넌트인 CartList 도 리렌더링되어 모든 코드가 다시 실행된다. 바뀐 장바구니 데이터로 보여지게 된다. 라고 생각했는데요. https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props#behavior 공식문서를 살펴보니 사용자가 Link 컴포넌트 또는 router를 통해 페이지를 방문할 때 , Next.js는 서버에 API 요청을 보내 getServerSideProps를 실행 합니다. 라고 되어있습니다. 이러면, 현재 CartList 는 CartPage 의 자식 컴포넌트이다. CartPage 는 getServerSideProps 로 서버에서 받아온 데이터를 프롭스(carts)로 받으며, 그 프롭스를 CartList 에게 전달해주고 있다. CartList 는 부모컴포넌트에게 받은 carts 프롭스를 통해 장바구니 목록을 보여주고 있다. 장바구니에서 상품을 삭제하면, 선택한 상품을 서버에서 삭제한다. router.replace 를 통해( router.push 도 동일) 현재 페이지(asPath)인 /cart 로 이동한다. router를 통해 페이지를 방문했으므로 CartPage 의 getServerSideProps 가 다시 실행되고 갱신된 데이터를 CartPage 에게 프롭스로 내려주게 된다. 프롭스가 변경됐으니 자식 컴포넌트인 CartList 도 리렌더링되어 모든 코드가 다시 실행된다. 바뀐 장바구니 데이터로 보여지게 된다. 이렇게 이해하면 될까요? 그리고, getServerSideProps 가 있는 페이지 컴포넌트는 getServerSideProps 가 재실행되면 자동으로 리렌더링되게 되는 구조인가요? 설명해주셨는데 제가 놓친거면 죄송합니다.
범샘님! 빠른 답변 및 업데이트 감사합니다, 답변해주신것처럼 section1, section4에서 스크롤문제가 발생합니다. 이 부분은 질문드리기 전에 확인한 부분이라 해결하였으나, 다만 답변해주신 두번째 경우는 제가 드린 질문의 방향과 조금 달라 재질문 드립니다. section4까지 스크롤을 내린후, 다시 section3까지 스크롤을 end-section3 지점까지 올리고, 다시 section4로 스크롤 할 경우 스크롤이 작동되지 않습니다. 이 부분은 첫번째 질문 드린 경우와 비슷한 상황인거 같은데, 이번에는 반대로 스크롤하는 경우라 direction을 down으로 하는 조건문을 추가하면 되는건지, 조금 더 명확한 답변과 코드를 확인하고 싶어 다시 질문드립니다. 여러모로 바쁘실텐데, 감사합니다!
안녕하세요, 쉬운 강의 덕분에 gsap 을 쉽게 접하고 사용할 수 있어서 감사합니다. 근데 해당 부분 구현중에 범샘께서 작성하신 코드(ScrollTrigger-finished)에서 확인해보면 1) section3 도달 후, section2로 스크롤을 올리는 경우 2) section4 도달 후, section3에서 다시 section4 로 스크롤을 내리는 경우 해당 2가지 경우에서 section03을 기준으로 스크롤이 위아래로 작동을 잘 하지 않습니다. if(currentPageIndex === 3) return; 때문인 것 같은데, 스크롤을 자유롭게 올렸다 내렸다 하면서 페이지를 확인할 수 있도록 하려고 하는데 잘 안되네요. 코드를 어떤 방식으로 수정해야할지 질문 남깁니다. 감사합니다.
it('최소 가격 또는 최대 가격을 수정하면 setMinPrice과 setMaxPrice 액션이 호출된다.', async () => { const { user } = await render(<ProductFilter />); const minPriceInput = screen.getByPlaceholderText('최소 금액'); const maxPriceInput = screen.getByPlaceholderText('최대 금액'); await user.type(minPriceInput, '10'); await user.type(maxPriceInput, '10000'); expect(setMinPriceFn).toHaveBeenCalledWith('10'); expect(setMaxPriceFn).toHaveBeenCalledWith('10000'); }); 전 이런식으로 작성했습니다. 단위 테스트에서 알려주신 AAA패턴을 해당 통합테스트에서도 적용하면 깔끔할 것 같아서 이렇게 작성했어요. 어차피 검증할건 setMaxPriceFn & setMinPriceFn이 호출됐는지 여부라 최소금액 및 최대금액 인풋을 연속적으로 조작하게 했습니다. 혹시 이렇게 하면 문제가 있는지 궁금합니다
[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
현재 듣고 있는 강의 부분은 Guard chapter에서 basic, bearer guard를 적용하는 부분입니다. @Injectable() export class BearerTokenGuard implements CanActivate { constructor( private readonly authService: AuthService, private readonly usersService: UsersService, ) {} async canActivate(context: ExecutionContext): Promise<boolean> { const req = context.switchToHttp().getRequest(); const rawToken = req.headers['authorization']; if (!rawToken) { throw new UnauthorizedException('토큰이 없음'); } const token = this.authService.extractTokenFromHeader(rawToken, true); const result = await this.authService.verifyToken(token); // payload 반환 /** * req 객체에 넣을 정보 * 1) 사용자 정보 - user 객체 자체 * 2) token - token * 3) tokenType - access | refresh */ const user = await this.usersService.getUserByEmail(result.email); req.user = user; req.token = token; req.tokenType = result.type; return true; } } 제 개인적인 생각으로는 적어도 제목에 적힌 두 엔드포인트에 대해서는 현재의 BearerTokenGuard를 적용하는 것이 굳이 라는 생각이 듭니다. refreshToken을 이용하여 새로운 토큰을 발급받는 역할을 하는 두 엔드포인트에 대해 다른 줄은 다 문제가 크게 없다고 생각하지만 req.user = user;로 굳이 요청에 user 객체를 붙이는 것은 굳이라는 생각이 듭니다. 제 낮은 식견으로는 위 두 엔드포인트에 대한 guard는 또 따로 만들어야 한다고 생각이 드는데 강사님 생각이 궁금합니다.
2.5) 원시타입 VS 객체타입 약 08:50. 안녕하세요, 강사님의 강의를 만족하며 잘 듣고있는 수강생입니다. 해당부분에 다소 오해의 소지가 될 내용으로 추가 강의 업데이트시 반영되었으면 하는부분이 있어서 올려봅니다. '객체의 참조값을 복사함' 이라는 문장은 맞다고 볼 수 있지만, 이를 얕은 복사라 부르기엔 오해의 소지가 많을것으로 보입니다. o2는 o1의 포인터값을 그대로 똑같이 가지고 있을 뿐, o2가 가리키는 값이 o1과 동일하게 '새로운 값이 만들어지지 않았기 때문' 입니다. 또한, '새로운 객체를 생성하면서 프로퍼티만 따로 복사함'이라는 문장또한 맞다고 볼 수 있지만, 이를 깊은 복사라 부르기엔 오해의 소지가 역시 많을것으로 보입니다. 실제로 공식문서에서도 이를 논하기에는 쓸모없다고 얘기하고있지만, 그러면서 Shallow copy에 대해서 아래와 같이 강조하고있습니다. For shallow copies, only the top-level properties are copied, not the values of nested objects. 때문에, 추가적인 nested objects에 문제가 따르며 실제로 이때문에 이를 얕은복사라고 많은 개발자들이 소통하고 있는것으로 알고있습니다. 특히, '원본 객체가 수정될 수 없어 안전함' 까지 있으니, 더욱더 top-level의 중요성이 강조되지 않는 것으로 보여 모호한것으로 보입니다. 평소 강사님의 강의, 강연등을 즐겨듣고 있는 수강생으로써 약간의 다소 오해의 소지가 있는부분을 언급해 볼 뿐이오니 너그러이 내용을 참조해주시면 감사하겠습니다. 항상 감사합니다. 이상입니다.
실무에 바로 적용하는 프런트엔드 테스트 - 2부. 테스트 심화: 시각적 회귀・E2E 테스트
unit-test-example에서 테스트를 실행하니 테스트코드 통과 여부에 관계없이 Test result not found만 뜨며 실패합니다. 이유를 모르겠어요ㅠㅠ Test result not found. If you set `vitest.commandLine` please check: Did you set `vitest.commandLine` to `run` mode? (This extension requires `watch` mode to get the results from Vitest api) Does it have the ability to append extra arguments? (For example it should be `yarn test --` rather than `yarn test`) Are there tests with the same name? Can you run vitest successfully on this file? Does it need custom option to run?