🔥딱 8일간! 인프런x토스x허먼밀러 역대급 혜택

블로그

코드캠프

입문자도 가넝한 8주만에 개발자 되는 법

안녕하세요! 실무 코딩부트캠프, 코드캠프입니다 :)날씨가 조금씩 따뜻해지면서 식곤증이 부쩍 늘어나고 있지 않나요?(전지적 컴퓨터 시점)그래서 코드캠프가 눈이 번쩍! 뜨이는(👀) 강의 업데이트 소식을 준비해왔어요!특히 비전공이지만 개발 커리어에 관심이 있는 분들이라면, 주목해주셔도 좋아요 :)코딩을 몰라도(NEW!) 2개월만에 개발자가 되는 '관리형' 코딩 부트캠프인프런에 입성한지 얼마 되지 않았지만 뜨거운 관심과 애정 어린 피드백을 받으며, 더 나은 컨텐츠를 제공하기 위해 코드캠프도 열심히 성장 중인데요. (정말 감사합니다)그 중 사전 기초 지식 없이는 부트캠프 합류가 어려워 신청을 망설였던 분들을 많이 보았어요.그래서 상담 후 등록을 완료해주신 모든 분들께,[시작은 프리캠프], [강력한 CSS], [훈훈한 Javascript] 기초 강의를 무료로 제공합니다!사전 지식을 필요로 하시는 분들은 웹 개발의 기초를 습득하시고사전 지식이 이미 있으신 분들은 기초 내용을 복습하면서 튼튼하게 다져보세요 :)⚠️ 단, 기초 강의 수강 기간은 부트캠프 기간(8주)에 포함되지 않으므로 등록하신 기수의 개강 일정에 맞춰 수강해 주셔야 합니다!(MBTI가 P인 분들)개강 전 기초 강의 수강 계획을 짜기 힘드신 분들은 언제든 코드캠프에 문의해주세요!개강일에 맞춰 수강할 수 있도록 체계적인 시간표를 제공해드리겠습니다 😊👉 2기 일정 : 03.06 - 04.28 (선착순 모집) ▶ 20% 할인 중!👉 3기 일정 : 04.03 - 05.29 (선착순 모집) ▶ 20% 할인 중!

웹 개발웹개발프론트엔드백엔드부트캠프비전공자JavascriptNode.jsReactNext.jsNest.js

바다다다

[인프런 워밍업 스터디 클럽 3기 FE] 3주차 발자국

수강강의1: 따라하며 배우는 자바스크립트 A-Z수강강의2: 따라하며 배우는 리액트 A-Z[19버전 반영]Tip: 워밍업 스터디 클럽을 참여하게 되면 [할인쿠폰]으로 강의를 할인 된 가격에 수강할 수 있다! 3주차 강의 수강3주차를 되돌아 보며..이번주 강의는 전반적으로 React와 친해지는(?) 시간을 가지게 된거 같다.React로 실제 화면을 구현해보고 각종 함수와 툴들을 사용해서 개발의 편의성을 높이는 것을 체감할 수 있었다.특히 주어진 미션과제를 수행하면서 React의 동작성, 상태관리에 대해서 더 깊게 알 수 있을 시간이 되었다.사실 이번주는 강의를 많이 듣지 못했다ㅠ 현업과 병행하다 보니 퇴근하고 강의 듣는다는 게 쉬운 일은 아니다. 특히 이번주는 시험검증 기간이라 이슈가 조금 많이 발생해서 야근도 잦고 그랬다... (모든 직장인, 학생 분들 화이팅입니다ㅠ 열심히 살아가봐요!) 그리고... 미션과제도 밀려서 주말에 몰아서 구현을 했다.미션과제를 수행하면서 중간중간 필요한 지식들은 강의를 들으면서 기록하며 학습을 진행했다.Javascript 강의 때와는 다르게 React 는 실습위주 이다보니 강의 내용을 정리한게 많지는 않다. (강의보면서 코딩따라 해보며 기능을 확인하고 미션에 적용하려고 했다)강의 내용을 다시 정리해보며..(주로 개인적으로 새롭게 알게된 것, 다시 기억해야하는 것들 위주로 정리했다)리액트는 프레임워크가 아니라 라이브러리React는 라이브러리, Vue, Angular는 프레임워크왜 라이브러리? 리액트는 전적으로 UI를 렌더링하는 것에 관여하기 때문상태관리, 라우팅, 테스트 등등을 위해 다른 라이브러리가 추가적으로 필요함 (vue, angular는 이런 것들이 이미 포함되어 있음)프레임워크: 어떠한 앱을 만들기위해 필요한 대부분의 것을 가지고 있는 것라이브러리: 어떠한 특정 기능을 모듈화 해놓은 것프레임워크는 라이브러리의 집합리액트 컴포넌트 - Component리액트 앱을 이루는 최소한의 단위, 여러 컴포넌트를 조합하여 하나의 페이지가 완성되는 것클래스형 컴포너트 - class component함수형 컴포넌트 - funcional component브라우저가 그려지는 원리와 가상돔리액트의 주요 특징 중 하나가 가상돔을 사용하는 것이다웹 페이지 빌드 과정 (CRP) - Critical Render Pathbrowser가 서버에서 페이지에 대한 HTML문서를 응답으로 받고, 해당 문서를 읽는다. 그 후 스타일을 입히고 뷰포트에 표시하게 된다DOM tree생성 → Render Tree생성(화면에 표시되는 모든 노드의 콘텐츠 및 스타일 정보를 포함) → Layout(reflow) → Paint(화면에 그리기)화면에서 DOM에 변화가 생기면 Render Tree부터 다시 랜더링 해야한다는 문제점!! → 비효율적→ 가상돔: 실제 DOM을 메모리에 복사해준 것데이터가 바뀌면 가상돔에 랜더링되고 이전에 생긴 가상돔과 비교해서 바뀐 부분만 실제 돔에 적용 시킴. 바뀐 부분을 찾는 과정을 diffing이라고 부르고, 바뀐 부분만 실제 돔에 적용시켜주는 것을 재조정(reconciliation)이라 한다.리액트 구조 살펴보기이름이 수정되면 안되는 파일public/index.html → page템플릿src/index.js → 자바스크립트의 시작점SPA는 어떻게 가능하게 되나?HTML5에서 History API를 사용해서 가능하게 함. (실제 react-dom에서 사용하는 방식)JSXJavascript syntax extension자바스크립트의 확장 문법이다React에서 의무적으로 사용하는 것 XJSX는 babel을 통해 변환된다컴포넌트에 여러 엘리먼트 요소가 있다면 반드시 부모요소 하나로 감싸줘야한다.JSX Keykey는 리액트가 변경, 추가 또는 제거된 항목을 식별하는데 도움이 된다. 요소에 안정적인 ID를 부여하려면 배열 내부의 요소에 키를 제공해야 한다 (key값을 기준으로 바뀐 가상돔을 감지한다)key에는 unique한 값을 넣어주자. index는 비추!React State컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고있는 객체이다. state가 변경되면 컴포넌트는 리랜더링(re-rendering)된다. 또한 state는 컴포넌트 안에서 관리된다.React HooksReactConf 2018에서 발표된 class없이 state를 사용할 수 있는 새로운 기능리액트의 생명주기react hooks를 통해 함수형 컴포넌트에서도 생명주기를 사용할 수 있게 데이터를 가져와서 컴포넌트 시작하자 마자 API호출하고 많은 부분을 사용할 수 있게되었다→ 코드가 간결해짐 (useEffect를 통해 componentDidMount, componentDidUpdate, componentWillUnmount를 다 수행해줌)HOC(higher order component)를 Custom react hooks로 대체해서 너무 많은 wrapper컴포넌트를 줄이게 된다.→ HOC: 화면에서 재사용 가능한 로직만을 분리해서 component를 만들고, 재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방식 (wrapper가 많아지면 데이터의 흐름을 파악하기 어려워짐)State, Propsstate해당 컴포넌트 내부에서 데이터를 전달할 때state는 mutable 변경가능하다state 이 변하면 re-render된다props상속하는 부모컴포넌트에서 자식 컴포넌트로 전달한다읽기전용으로 작년 컴포넌트 입장에서는 변하지 않는다. (변하게 하고자 하면 부모 컴포넌트에서 state를 변겨해줘야한다)구조 분해 할당(Destructuring)배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JS표현식클린코드를 위해 객체, 배열에 대해 구조 분해 할당Redux상태 관리 라이브러리redux데이터는 하나의 방향으로만 흐른다flow: react component에서 어떠한 이벤트가 발생하면 → Action 객체(어떤 작업을 수행할 것인지 description을 담고 있음)를 통해 reducer함수에게 액션을 발생하라고 한다.(dispatch) → reducer함수에서 로직 처리 → store내부 상태 업데이트: redux store state update → 새롭게 업데이트 된 상태를 이용해서 다시 렌더링 → component re-renderingRedux Tookitredux로직을 작성하기 위한 공식 권장 접근 방식 강의 내용을 들으면서 아쉬웠던 점..앞서 언급한 대로 이번주에는 강의보다는 실습 과제에 조금 더 초점을 두었다. 미션을 수행하면서 모르는 부분을 강의에 가서 찾아 듣고 다시 구현하고 하는 식으로 학습을 진행했다.React는 이론 보다는 실제 사용하고 구현해보는게 더 빠르게 성장하는거 같다. 특히 상태관리, 페이지 라우터 등 강의에서도 알려주시지만, 미션과제를 수행하면서 직접 기능을 동작시킬 수 있게 구현하는게 더 깊이 이해할 수 있었던 거 같다.아쉬운점은ㅠ 강의를 많이 못 들었다는거? 수료식까지 아직 시간이 조금 남았으니까 남은 강의도 열심히 들어보겠다.3주차 미션 완료React미션 두 개(포켓몬, 쇼핑몰)를 토요일 벼락치기로 수행했다.간단하다고 생각했는데 React가 아직 익숙하지 않아 중간중간 오류가 많이 발생했었고, 특히 프론트엔드는 화면이 바로 눈에 보이다 보니까 CSS 스타일 적으로 내맘대로 적용되지 않아서 화가났다(?). 그래도 tailwindcss에서 만들어진 component, icon들을 활용해서 미션을 수행완료할 수 있었다.React - Mission3: 포켓몬 도감 앱 만들기Demo: https://pokemon-mission-3.netlify.app/Source Code: https://github.com/rim0703/React-study/tree/react/mission3/React/3-pokemonpokeAPI 라는 오픈소스 API를 제공하는 곳이 있어서 외부API를 호출해서 구현했다API문서가 얼마나 중요한 역할을 하는지 이번 미션에서 깊이 깨달았다.. ㄷㄷ(백엔드 화이팅)(지연로딩 적용) 사용자의 화면 로딩 속도를 고려하면 첫 화면에 20개씩 불러오도록 했고, 스크롤이 하단에 도달하면 추가로 호출하도록 구현했다.(Trick) 시연화면에서 로딩이 출력되는데 사실 화면이 너무 빨리 렌더링 완료돼서 로딩이 보이지 않아 로딩 동글뱅이를 보기 위해 setTimeout으로 1초 지연을 넣었다 ^^;;(검색창) 조금 버그가 있다. 페이지를 영문이 아닌 한글로 만들다보니 검색도 한글로 하도록 했는데 상태를 상위-하위 컴포넌트 간에서 전달하다 보니 조금 어려웠다. 또한 API문서 기본은 영문으로 제공해서 영문과 한글을 매칭시키는 별도의 작업도 필요했다. redux를 사용해서 검색창을 상단 navigation바에 위치해보려고 한다.  React - Mission6: 리덕스를 이용한 쇼핑몰(버거몰) 앱 만들기Demo: https://burger-mall-mission-6.netlify.app/Source Code: https://github.com/rim0703/React-study/tree/react/mission6/React/6-shopping-mall1주차 미션 내용에서 언급했듯이.. JS강의에서 만들었던 메뉴 화면을 그대로 따와서(CSS공부가 아니니까^^) 쇼핑몰과 비슷한 기능들이 있는 버거몰을 만들어보았다.(컴포넌트화) HTML,JS,CSS로 구현된 내용을 React로 옮겼고, 원래 파일 1개씩 정의된 내용을 React Component로 분류하였다.(장바구니-localstorage) DB를 별도로 연동된게 아니여서 localstorage를 활용해서 장바구니를 구현하였다.(Redux) 리덕스 강의 내용에 기반한 프로젝트이지만 Redux강의를 듣고 이해가 잘되지 않아서 우선 기본 방식으로 앱을 구현하였다. Redux공부를 조금 더 하고 리팩토링을 진행할 예정이다. 마지막으로 3주차 회고이제 수료까지 얼마남지 않았는뎅,, 남은 시간동안 강의를 열심히 들어야겠다.너무 빡빡한 일정이었지만 3주차까지 버텨오고 React에 대해 친해질 수 있는 시간이되어서 뿌듯하다.현업에서 Vue를 사용하다 기술 전환을 위해 React를 도입한다고 해서 급하게 스터디에 신청해서 힘들지만 조금만 더 버티면되지 않을까? 직장과 병행하니.. 이게 쉬운일은 아닌거 같다. 모든 직장인들 화이팅입니다!흑흑.. 미션 기능 중에 동작하지 않는게 있어서 수정하고 다시 배포하고 이제 자러간당ㅠㅠ다음주는 더 성장한 내가 되어 있기를!! 모두 완주까지 화이팅입니다~(2025.03.23 새벽 03:26)<끝>

프론트엔드워밍업스터디3기프론트엔드미션JSJavascriptReactRedux회고

Javascript 정리

이벤트 로드 시점 요소가 로드되기 이전에 이벤트를 먼저 호출할 경우 이벤트가 적용되지 않는 문제가 있다. 이런 경우, 기본적인 요소는 html에 구성해놓은 후에 원하는 작업을 진행해야한다.   객체 서버와의 통신 방식이 JSON 객체 방식이라면, 데이터 요청과 응답 시 객체{}를 이용해야한다.   기능에 따른 분리 요소의 속성을 다루거나 event listener 상태 관련 객체, 같은 서비스 수준으로 기능(함수)들을 묶은 객체 요소 검증 관련 함수  Ajax 등 서버와의 통신     es6 문법 객체 = { name: "name" }키와 값 이름 값을 시 하나로만 제공해도 됨객체 = { name } const { id, name } = 객체;객체 속성을 사용할 때 일일히 객체에서 꺼내쓰는 것이 아닌 변수에 할당하여 사용 가능const { id, name: studentName } = 객체; 이런 식으로 새로운 속성 이름으로 매핑도 가능하다.배열 또한 매번 인덱스를 활용하여 꺼내쓰는 것이 아닌 변수에 할당하여 사용 가능하다. 복사const arrayCopy = [...array];[...array, { key: 'value'}] -> 새로운 요소도 추가 가능{ ...obj } -> 객체도 같은 방식으로 복사 가능서로 다른 객체, 배열을 병합하는 것도 가능배열 병합 -> [...array1, array2]객체의 경우에는 키 값이 같으면 마지막 객체의 값으로 덮어씌워진다. default parameterfunction printMessage(message = "defaultMessage"){}보통은 값을 확인하는 if문이 제공되지만 default parameter로 제공되었기 때문에항상 값이 있으며, 바로 값을 활용하는 코드로 들어가면 됨 Ternary Operator - 삼항 조건 연산자조건문 ? 값1 : 값2조건이 참일 경우 값1, 거짓일 경우 값2 사용 Template Literals``문자열 속에서 ${}를 활용하여 변수 사용 가능   es11 optional chaining없는 속성을 호출할 경우 오류가 난다. 이 경우 optional chaining 활용person.job?.manager?.nameperson의 job이 있을 경우 그리고 manager가 있을 경우 manager의 name 가져오게 됨null일 수 있는 중첩된 객체를 불러올 때 복잡하지 않은 형태로 호출 가능하다. nullish coalescing operatorfalse는 '' 0 null undefined에 해당한다.즉, || 연산자 사용 시 0과 ''은 값으로 처리하려면 ?? 연산자로 대체하여 사용해야한다.    

JavascriptJQuery

바다다다

[인프런 워밍업 스터디 클럽 3기 FE] 2주차 발자국

수강강의1: 따라하며 배우는 자바스크립트 A-Z수강강의2: 따라하며 배우는 리액트 A-Z[19버전 반영]Tip: 워밍업 스터디 클럽을 참여하게 되면 [할인쿠폰]으로 강의를 할인 된 가격에 수강할 수 있다!2주차 강의 수강2주차를 되돌아 보며..이번주에는 지난주 Javascript강의를 마무리하고 드디어 React에 대한 학습에 진입하게 되었다.Javascript후반부 강의에서는 주로 디자인 패턴, Iterator, Generator에 대해 알아가고 마지막으로 Todo app, spread sheet 등을 따라 만들어 보면서 Javascript문법에 대해 조금 더 익숙해지고 복습하는 시간을 가지었다.React는 초반에 설치와 프로젝트 환경설정을 시작으로 처음부터 앱을 따라 만들어 보면서 React의 구조에 대해 알아보았다. TODO앱과 Netflix따라 만들기 강의를 따라서 코딩을 진행을 하였지만 환경설정이나 알수없는 오류등이 발생해서 바로 미션 과제를 중점으로 학습을 진행하였다.강의에서 언급한 이론을 실제 미션 과제에서 실습으로 결과물을 얻을 수 있어서 뿌듯했다. 지난주 과제에 비해 난이도가 많이 높아져서 진도를 따라잡기에 많이 버거웠던것도 사실이다. (특히 직장인이라면...More and more...hard..)강의 내용을 다시 정리해보며..(주로 개인적으로 새롭게 알게된 것, 다시 기억해야하는 것들 위주로 정리했다)Generator Generator사용자의 요구에 따라 다른 시간 간격으로 여러 값을 반환할 수 있음일반 함수 → 한번 실행으로 끝까지 실행됨generator 함수 → 일시적으로 정지될 수도 있고, 다시 시작할 수도 있음function* sayNumbers() {...} 별표로 generator함수 생성yield 함수를 정지시킴 → 일반함수에서 return과 동일function* sayNumbers(){ yield 1; yield 2; yield 3; } const number = sayNumbers() console.log(number.next()) // {value:1, done:false} console.log(number.next()) // {value:2, done:false} console.log(number.next()) // {value:3, done:false} console.log(number.next()) // {value:undefined, done:true} lazy evaluation에 활용가능계산의 결과값이 필요할 때까지 계산을 늦춰서 필요한 데이터를 필요한 순간에 생성Singleton Pattern클래스의 인스턴스화를 하나의 객체로 제한하는 디자인 패턴. 시스템 전체에서 작업을 조정하는 데 정확히 하나의 객체가 필요한 경우에 유용하다클래스가 존재하지 않는 경우 클래스의 새 인스턴스를 생성하는 메서드로 클래스를 생성하여 구현할 수 있음. 인스턴스가 이미 존재하는 경우 해당 개체에 대한 참조를 반환⇒ 객체는 1개만 만들고 그것을 계속 재사용하는 것 (값이 한곳에서 바뀌면 전역으로 바뀜)Factory Pattern특수 함수인 팩토리 함수를 사용하여 비슷한 객체를 많이 만들 수 있음⇒ 비슷한 객체를 반복적으로 생성해야하는 경우 사용Mediator Pattern (중재자 패턴)객체 그룹에 대한 중앙 권한을 제공한다. (예: 채팅방)Observer Patternevent-driven시스템을 이용하는 것 (예: facebook알림)topic에 대해 register하고 publisher-subscriber구조를 가지게 됨Module Pattern코드를 더 작고 재사용 가능한 조각으로 분할하는 것을 도와준다js코드를 작성하고 export지시자를 변수나 함수 앞에 붙이면 외부 모듈에서 해당 변수나 함수에 접근가능하게 된다import로 외부 모듈을 가져올 수 있음모듈은 특수한 키워드나 기능과 함께 사용되므로 HTML에서 script태그를 넣을 때 type='module' 속성을 추가해줘야 한다항상 strict모드로 실행된다지연 실행 된다인라인 모듈 스크립트도 비동기 처리할 수 있다외부 orgin에서 스크립트를 불러오려면 CORS헤더가 있어야 한다중복된 스크립트는 무시한다 (최초 호출될 때 한번만 실행)구형브라우저에서는 <script nomodule> ... </scirpt> 로 module을 지원하지 않을 경우 예외처리를 할 수 있음리액트는 프레임워크가 아니라 라이브러리React는 라이브러리, Vue, Angular는 프레임워크왜 라이브러리? 리액트는 전적으로 UI를 렌더링하는 것에 관여하기 때문상태관리, 라우팅, 테스트 등등을 위해 다른 라이브러리가 추가적으로 필요함 (vue, angular는 이런 것들이 이미 포함되어 있음)프레임워크: 어떠한 앱을 만들기위해 필요한 대부분의 것을 가지고 있는 것라이브러리: 어떠한 특정 기능을 모듈화 해놓은 것프레임워크는 라이브러리의 집합리액트 컴포넌트 - Component리액트 앱을 이루는 최소한의 단위, 여러 컴포넌트를 조합하여 하나의 페이지가 완성되는 것클래스형 컴포너트 - class component함수형 컴포넌트 - funcional component브라우저가 그려지는 원리와 가상돔리액트의 주요 특징 중 하나가 가상돔을 사용하는 것이다웹 페이지 빌드 과정 (CRP) - Critical Render Pathbrowser가 서버에서 페이지에 대한 HTML문서를 응답으로 받고, 해당 문서를 읽는다. 그 후 스타일을 입히고 뷰포트에 표시하게 된다DOM tree생성 → Render Tree생성(화면에 표시되는 모든 노드의 콘텐츠 및 스타일 정보를 포함) → Layout(reflow) → Paint(화면에 그리기)화면에서 DOM에 변화가 생기면 Render Tree부터 다시 랜더링 해야한다는 문제점!! → 비효율적→ 가상돔: 실제 DOM을 메모리에 복사해준 것데이터가 바뀌면 가상돔에 랜더링되고 이전에 생긴 가상돔과 비교해서 바뀐 부분만 실제 돔에 적용 시킴. 바뀐 부분을 찾는 과정을 diffing이라고 부르고, 바뀐 부분만 실제 돔에 적용시켜주는 것을 재조정(reconciliation)이라 한다.  강의 내용을 들으면서 아쉬웠던 점.. 강의 내용에 대해서 불만족 스러운 부분은 없다! 너무 알차게 구현되어진 강의이고 다만 진도에 따라서 많은 양의 강의를 한꺼번에 들어야 하다보니 모두 소화하기에는 어려웠다.강의 외에 미션과제도 수행해야 하다 보니 시간적으로 지난주에 비해 많이 부족했다. 아래 미션과제에서도 볼 수 있겠지만, 지난주와 달리 기본적인 모든 기능을 구현하지는 못했다.(특히! 디즈니플러스 클론코딩ㅜ)2주차 미션 완료Javascript미션은 지난주에 이어서 그나마 완성하기 했으나,React미션은 초보자의 입장에서 강의내용 수준으로 따라가기에는 어려웠다.처음이다보니 모든게 낯설게 느껴졌고, 그래도 다른 강의 및 자료를 통해 많은 학습을 할 수 있었다.특히 컴포넌트를 나누는 기준과 React에서 컴포넌트를 조합해서 웹 페이지를 구성한다는 것을 미션 실습과제를 통해 좀 더 쉽게 깨달을 수 있었던 것 같다. Javascript - Mission6: 비밀번호 생성기Demo: https://rim0703.github.io/React-study/Javascript/6-pw-generator/Source Code: https://github.com/rim0703/React-study/tree/main/Javascript/6-pw-generator Javascript - Mission7: 타이핑 테스트Demo: https://rim0703.github.io/React-study/Javascript/7-typing-test/Source Code: https://github.com/rim0703/React-study/tree/main/Javascript/7-typing-test React - Mission1: 예산 계산기Demo: https://gentle-starburst-b5ca45.netlify.app/Source Code: https://github.com/rim0703/React-study/tree/react/mission1 React - Mission2: 디즈니 플러스 앱Demo: https://disney-plus-clone-mission2.netlify.app/Source Code: https://github.com/rim0703/React-study/tree/react/mission2참고자료: https://www.youtube.com/watch?v=3NHYl0Lo74A이건 할말이 많은데.. 사실 아래 데모처럼 메인화면만 완성했다. 맨땅에서 시작하기에는 너무 막막해보여서 유튜브에 클론코딩 영상이 있어서 따라 만들어보았다.추가로 메인 로그인 화면, 영화 상세 내용 팝업화면이 추가로 구현일 필요하다.(추후 시간이 있으면 보완할 예정!)마지막으로 2주차 회고이번 한주간은 너무 정신없이 지난거 같다. 강의, 미션과제 외에 처음으로 접하는 React 내용에 설정이나 오류 등에 대해 검색하면 이슈 attack을 하기 위해 많이 시간이 필요했다. 이런 부분은 점차 많이 연습해보면 적응하지 않을까 싶다.진도표에 따르면 이제 3일만 더 수강하면 강의내용과 미션은 끝나는 일정이다. 최대한 남은 시간에 React강의를 끝내고 미션 과제 구현에 집중할 계획이다. 단기간에 많은 시간과 노력을 쏟아올린 만큼 프론트엔드에서 React에 대한 부담감(?) 두려운 마음을 조금이나마 떨쳐보고자 한다.강의수강이 끝나면 지금까지 구현한 미션 과제에 대해 보완할 부분이 있는지, 그리고 지금까지 강의를 들으면서 노션에 정리해두었던 내용을 다시 한번 복습할 계획이다.마지막 남은 기간도 화이팅 해보자!!!<끝>

프론트엔드워밍업스터디3기프론트엔드2주차발자국JavascriptHTMLCSSReact

바다다다

[인프런 워밍업 스터디 클럽 3기 FE] 1주차 미션 회고

1주차 발자국은 여기에: [인프런 워밍업 스터디 클럽 3기 FE] 1주차 발자국발자국 글이 길어져 미션을 따로 회고를 작성하였다.Mission1 - 음식 메뉴 앱Demo (클릭연결)SourceCode (클릭연결) 문제해결첫 미션 이여서 조금 설렜다(?)주어진 과제 안내 동영상에서 기본 화면 + 버튼으로 리스트를 화면에 뿌려주는 형식을 보고 따라 만들어 보았다.맥도날드를 좋아해서 맥도날드의 메뉴로 앱을 구성했다.정적 웹페이지로 구성된 화면이다보니 Github Page를 통해 배포까지해서 Demo화면을 구성하였다.고도화마지막 주차에 React 미션에서 쇼핑몰 앱 구현 미션이 있던데 해당 미션에서 구현한 화면으로 맥도날드 주문 앱을 구성해보아도 괜찮을 거 같다는 생각 회고가장 기본적인 HTML, CSS, JS를 활용해서 만든 웹 페이지라 맛보기에 좋았다.Mission2 - 가위 바위 보 앱Demo (클릭연결)SourceCode (클릭연결)문제해결플레이어는 가위, 바위, 보 3가지 중 한가지를 버튼 클릭 방식으로 제출하고, 컴퓨터는 랜덤으로 가위, 바위, 보를 제출하여 게임의 득점을 계산 한다.10회의 가위 바위 보 게임이 끝나면 최종 결과를 출력하는 앱이다.추가로 컴퓨터와 플레이어의 게임 결과를 출력되도록 화면 구성을 하였다.고도화가위 바위 보를 텍스트가 아닌 아이콘으로 표시하면 사용자가 좀 더 식별하기 쉬울 거 같다.현재는 마지막 단계에서 새로고침을 직접 해야하지만, 새로고침 버튼을 추가하여 사용성을 높일 수 있을거 같다.뒷 부분에서 webSocket을 사용한 채팅 앱도 미션으로 나와있던데 webSocket을 통한 양방향 게임도 구현할 수 있는 하나의 방향이라 생각한다.회고JS문법을 조금 더 많이 활용해볼 수 있었던 미션이다.CSS를 구성하는게 어려웠다ㅠ Mission3 - 퀴즈 앱Demo (클릭연결)SourceCode (클릭연결)문제해결미션 영상에서 안내된 내용대로 구현하려고 했다.여러 개의 답을 랜덤으로 생성하는데 "답이없는 경우"도 있다는 것이다. 우선 정답을 저장해두고 랜덤으로 답안 개수를 생성하면서 저장해둔 정답이 버튼으로 생성되지 않는다면 "답이 없음"버튼을 추가하도록 구현했다.정답을 맞추지 않으면 다음문제로 넘어가지 않도록 하였고, 정답을 제출하면 해당 계산식 문제에서 "?" 물음표가 정답으로 바뀌도록 구현하였다.고도화현재 구현된 버전에서는 정답을 맞추지 않으면 다음 문제로 넘어가지 않기 때문에 "O문제 정답"으로 표기하기 보다 풀이 문제수를 표시하고 있다는게 더 명확할 거 같다.무한대로 문제를 출제하도록 구현하여 문제 풀이의 끝이 없다. 문제수를 설정하고 해당 앱을 시작하는 방법도 생각해볼 수 있겠다.또한, 현재 10이내의 범위에서 덧셈 문제만 출제되고 있는데 좀 더 다양한 퀴즈(수학문제가 아니어도)들을 포함할 수 있다.회고 역시나 CSS로 화면을 표시하는 것에 시간이 많이 필요했다. (버튼 색상 변경, 배경 색 변경 등)alert을 미션에서 처음 띄워보았다. 근데.. 사실 사용자 입장에서는 조금 많이 거슬리는 거 같다. 생각해보면 대부분의 웹사이트에서 alert대신 팝업으로 메시지를 띄워주는 경우가 더 많은 거 같다. Mission4 - 책 리스트 나열 앱Demo (클릭연결)SourceCode (클릭연결)문제해결책 목록에 책을 저장해두고 저장해둔 내용을 아래 테이블에 표시해주는 형태이다.추가적으로 수정기능을 넣었고, 책 배열에서 선택된 객체의 값을 변경하여 이를 구현할 수 있었다.시인성을 높이기 위해 삭제된 책은 책이름이 출력되도록 수정하였다.고도화이게 중요한 책 목록 저장 시스템이라면 DB연동해서 영구적으로 저장해두는게 맞지만, 여기서는 미션이고 JS를 학습하는 목적이니 간단하게 화면에 표시만 했다. 로컬에 저장하는 것을 고려해보면 브라우저 내장 storage를 사용해서 잠깐의 저장 기능도 구현할 수 있지않을까라는 생각을 했엇다.회고앞에 3번 정도 미션을 수행하니 이제 CSS도 조금 적응한 듯 싶다.DB연동을 해보지 못해서 조금 아쉬웠지만, 일단 기초를 다지는 단계이니까 기초에 좀 더 집중하자는 생각. Mission5 - Github Finder 앱Demo (클릭연결)SourceCode (클릭연결)문제해결fetch함수로 github API를 사용하여 사용자의 정보를 얻어올 수 있다.얻어온 데이터를 화면에 적절히 뿌려주면되는 과제 였는데, 추가로 repository로 연결되도록 구현하였다.안내 동영상에는 사용자의 input을 감지하여 입력이 발생될 때 마다 API호출을 해서 화면이 랜더링 되도록 구현한 것으로 추측되는데, 이를 좀 더 효율성을 높이고자 사용자가 input을 입력하고 제출할 때 API call을 한 번 하도록 수정하였다.고도화현재 보여지는 profile정보 등은 간략하게 표시하고 있다.github API를 활용하여 클론 코딩도 가능할 거 같다. 회고외부 API를 호출해서 미션을 진행하며 잘 구현된 API가 화면을 구현하는 데에 많은 도움이 된다는 것.<끝>

프론트엔드워밍업스터디3기프론트엔드미션JSJavascriptHTMLCSS회고

바다다다

[인프런 워밍업 스터디 클럽 3기 FE] 1주차 발자국

수강강의: 따라하며 배우는 자바스크립트 A-ZTip: 워밍업 스터디 클럽을 참여하게 되면 [할인쿠폰]으로 강의를 할인 된 가격에 수강할 수 있다!1주차 강의 수강1주차를 되돌아 보며..이번 주 강의는 Javascript에 기본 문법부터 시작해서 중급 문법과 ES6에서 지원하는 class, promise등의 기능까지 학습하는 시간을 가질 수 있었다.강의가 단순하게 이론내용만 전달되는 것이 아니라 실제 코드를 구성하고 해당 Javascript코드가 HTML화면에서 어떤 동작을 하게되는지 실습과 함께 진행되어서 이해하기 더 쉬웠다. 물론 Javascript를 사용하는게 처음은 아니라 좀 더 여유롭게 강의를 이해할 수 있었지만, 중간중간 잊고 있었던 Javascript내용을 다시 복습하기에 좋은 시간이었다.또한 실습 과제도 강의 내용과 연관성이 있어서 단순 강의만 듣는 것보다 더 성취감을 높일 수 있었다. 강의 내용을 다시 정리해보며..(주로 개인적으로 새롭게 알게된 것, 다시 기억해야하는 것들 위주로 정리했다)var, let, const var를 왜 사용하지 말라는지 명확하게 알 수 있었다. let, const로 좀 더 관리하기 편한 코드를 작성하자.for VS forEach 사실 실제 사용할 때 그냥 편하다고 생각하고 forEach를 많이 사용했던 나의 모습이 떠올랐다. 또한 for..of도 많이 사용했었다. 성능적인 측면에서 데이터의 양이 늘어나면 성능이 떨어진다는 것을 알게되었고, 코드를 작성할 때 왜 사용하는지를 좀 더 고민 해야겠다. (절대적인 것이 아니다. 테스트 환경에 따라 결과가 다를 수 있음) CRP과정: Critical Rendering Path DOM tree 생성 → Render tree생성 → Layout → Paint DOM을 생성하는 것은 비용이 많이 발생하지 않지만, render, layout, paint에서 많은 비용이 발생한다. → 따라서 React에서는 가상의 DOM을 사용해서 최적화className VS classList className:특정 element의 클래스 속성의 값을 가져와서 설정할 수 있다.기존에 className을 전부 지우고 추가한다. classList: 읽기전용 property.classList.add()를 통해 기존 className을 유지한 채로 class명을 추가할 수 있다Event 종류가 너무 많다...이것들을 현업에서 사용가능하게 하려면? 공식 문서를 잘 찾아봐야 할 거 같다.어떤 기능을 구현하려고 하는데 이미 지원하는 메서드가 존재하지 않을까?를 생각해보자.Event Delegation (이벤트 위임):하위 요소의 공통 이벤트를 상위 요소에 위임함(강의 듣다가 신기한 코드 발견!)<div id="buttons"> <p>123</p> </div> <script> const buttonList = document.querySelector("#buttons"); buttons.addEventListener("click", () => alert("clicked")); </script> Q: 여기서 buttons는 HTML 요소의 id값 인데 js에서 그대로 사용해서 접근할 수 있다?A: 요소의 id또는 name은 window객체의 property로 추가되어 그대로 사용할 수 있지만, 다른 window객체의 property와 충돌될 수 있으니 사용하지 말자. (결론: 이렇게 쓰지마) JS에서 method VS function (이부분이 강의에서 언급되었는지는 잘 모르겠다. 강의 들으면서 궁금해서 찾아봤다) method: 호출방식, 함수를 호출하는 객체가 있는 경우, 즉 사용자가 정의한 객체의 property가 함수인 경우 해당 함수는 method라고 한다. function: 함수를 호출하는 객체가 없는 경우 Lexical this: 화살표 => 함수에서 this는 상위 스코프를 가리키게된다. bind, call, apply this를 function안에서 사용하면 window객체를 참조하게 되는데, 이를 다른 객체를 참조하도록 도와주는 함수들call(): 함수를 호출하는 함수const fullName = function(city, country){ console.log(this.firstName + ' ' + this.lastName, city, country); } const person1 = { firstName: 'John', lastName: 'Smith' } fullName.call(person1, "Oslo", "Norway") // call함수를 통해 person1 객체를 함수로 넘겨줌 apply() - 배열로 함수의 parameter를 전달함const fullName = function(city, country){ console.log(this.firstName + ' ' + this.lastName, city, country); } const person1 = { firstName: 'John', lastName: 'Smith' } fullName.apply(person1, ["Oslo", "Norway"]) // call함수와 달리 배열 형식으로 넘겨주는 방식 bind() - binding만으로 호출이안되고 새로 call을 해줘야함.function func(language){ if(language === 'kor'){ console.log(`language:${this.korGreeting}`) } else { console.log(`language:${this.engGreeting}`) } } const greeting = { korGreeting: '안녕', engGreeting: 'Hello' } const boundFunc = func.bind(greeting) //binding 만 시켜줌 따라서 새로운 값에 할당하고 호출해야함 boundFunc('eng') Javascript는 동기 언어이다. 어떻게 비동기를 실행가능한가? setTimeout()은 JS가 아니다. 브라우저에서 사용하는 것이면 브라우저 API를 사용하는 것(Window Object), Node에서 사용한다면 Node API를 사용하는 것이다(global Object) JS엔진 Memory Heap: 메모리 할당이 발생하는 곳 (변수를 정의하면 저장해두는 곳) Call Stack: 코드가 실행될 때 스택들이 쌓이는 곳 -> 여기서 이벤트 루프가 call stack, callback queue를 주시하고 있다가 call stack이 비어지면 callback queue에 대기중인 setTimeout작업을 실행하게 됨.setTimeout()을 0초로 설정하면 0초(즉시 실행)를 보장할까?Nope! 이벤트 루프를 타고 callback queue를 들렀다가 오는거니까 즉시실행은 아님.Closure다른 함수 내부에 정의된 함수(innerFunction)이 있는 경우 외부 함수(outerFunction)이 실행을 완료하고 해당 변수가 해당 함수 외부에서 더 이상 엑세스할 수 없는 경우에도 해당 내부 함수는 외부 함수의 변수 및 범위에 엑세스 할 수 있다.function outerFunction(outerVariable) { return function innerFunction(innerVariable) { console.log("Outer Variable: " + outerVariable); console.log("Inner Variable: " + innerVariable); }; } const newFunction = outerFunction("outside"); newFunction("inside"); // 여기서 outerVariable은 여전히 outside를 기억하고 있다.Map, Filter, Reduce Map(): 배열내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환함Filter(): 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환 Reduce(): 배열의 각 요소에 대해 주어진 리듀서(reducer)함수를 실행하고, 하나의 결과값을 반환한다.undefined VS null 원시 자료형 undefined타입은 undefined이 유일하고, null타입은 null값이 유일하다. undefined는 자바스크립트 엔진이 변수를 초기화할 때 사용한다. 개발자가 의도적으로 undefined를 할당하는 것은 권장하지 않는다. null: 비어있는, 존재하지 않는 값을 의미 NULL, Null과는 다르다! 변수 값이 없을 경우 명시하기 위해서는 undefined가 아닌 null을 사용한다null을 할당하면 변수가 이전에 참조하던 값을 명시적으로 참조하지 않겠다고 하는 것이므로, JS엔진이 이 변수에 메모리 공간에 대해 가비지 콜렉션을 수행한다. (garbage collection: 더이상 사용하지 않는 메모리를 자동으로 정리하는 것)얕은 비교 VS 깊은 비교숫자, 문자열 등의 원시 자료형은 값을 비교한다배열, 객체 등 참조 자료형은 값 혹은 속성을 비교하지 않고, 참조되는 위치를 비교한다.객체의 경우 깊은 비교가 필요함- 깊이가 깊지 않을 경우: JSON.stringify()- 깊이가 깊을 경우: lodash라이브러리의 isEqual()사용함수 표현식(Expression), 함수 선언문(Statement)함수표현식 let funcExpression = function() {...}함수선언문 function funcDeclaration() {...}차이: 함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않는다.  강의 내용을 들으면서 아쉬웠던 점..우선 단기간에 많은 양의 강의를 들어야해서 강의에서 진행한 실습을 전부 따라하기에는 힘들었다. 기존에 JS에 대한 기초 지식이 있어서 강의를 다 따라올 수 있었지만, 처음 스터디에 참여하신 분이라면 많이 힘들었을 수 있겠다는 생각을 했다. (특히 직장인은.. 더..)자기 주도학습인 스터디 형식이다 보니 미션 과제를 제출해서 과제 전체 내용에 대한 코드리뷰는 받기 어려웠다. 그래서 미션 과제를 진행하면서 어떤 기능을 더 추가할 수 있을까, 어떻게 하면 편의성을 높일 수 있을까를 많이 생각했던거 같다. 또한 과제 제출시간에 맞춰서 미션을 수행해야 하다보니 코드가 생각보다 깔끔하게 짜여진거 같지는 않았다. (이 부분은 추후에 시간나면 리팩토링 진행할 생각이다..)다음주는 React 프로젝트가 시작되는데,, 조금 걱정이긴하다.. 잘 할 수 있을까? 1주차 미션 완료(글이 길어져 미션에 대해서는 간략하게 시연 위주로 작성하고, 회고는 여기 링크에 따로 작성해두었다.)https://www.inflearn.com/blogs/94751주차 미션은 주로 강의내용에 기반해서 HTML, JS, CSS를 사용해서 Single-page application을 작성하는 과제들이었다. HTML, CSS는 강의에서 다루는 범위가 아니고, JS를 중점으로 다루고 있기때문에 JS의 문법 동작성을 확인하는 데에 더 초점을 두었다고 생각한다. 따라서 과제를 수행할 때 HTML, CSS는 최소한으로 간략하게 작성하고 script파일 작성에 좀 더 중점을 두었다. 제출한 미션은 Github Page를 사용해서 배포하였다.Demo: https://rim0703.github.io/React-study/Source Code: https://github.com/rim0703/React-study/tree/main/Javascript Mission1 - 음식 메뉴 앱(맥도날드를 좋아해서 맥도날드 메뉴판을 간략하게 구성해보았다. 뭐든 관심있는 주제가 더 재밌지 않은가?)Mission2 - 가위 바위 보 앱(과제 참고 영상에서는 컴퓨터에 대한 결과가 출력되지 않아 추가로 컴퓨터의 결과와 플레이어의 결과를 비교할 수 있도록 구현하였다.)Mission3 - 퀴즈 앱(오답 시 다음 퀴즈로 넘어가지 않도록 구현하였다) Mission4 - 책 리스트 나열 앱(삭제 기능 외에 수정 기능을 추가 구현하였다) Mission5 - Github Finder 앱(사용자input을 감지해서 API call하는 대신, 버튼을 통해 input을 제출하면 API call하는 방식으로 개선하였다)(예시 화면은 향로님 깃헙 ^^7) 마지막으로 1주차 회고전반적으로 확실하게 자기주도 학습이 강한 느낌을 받았다. 본인의 일정에 맞춰서 일주일 내에 강의를 수강하고, 과제를 제출하는 것이 쉬운 일이 아닌거 같다. 그럼에도 첫 주를 잘 마무리 할 수 있어서 뿌듯하다.처음에는 React에 대해 학습하고자 스터디에 참여하게 되었지만, 실제 기초적인 Javascript에 대한 내용도 잊은 부분이 많다는 것을 깨닫게되었다.진도표에 보면 다음 주에는 JS강의가 끝나고 React 강의가 본격적으로 시작된다.React 미션과제는 또 어떤 구현 내용들이 기다리고 있을까?기대반 걱정반이다.. 다음주도 화이팅해보자! <끝>

프론트엔드워밍업스터디3기프론트엔드1주차발자국JavascriptHTMLCSSReact

kk

[인프런 워밍업 스터디 클럽 3기 FE] 1주차 발자국

강의 내용을 정리하기엔 많아서 강의 내용 보다는 들으면서 궁금했던 내용 위주로 정리해보았다.강의를 들으며 궁금했던 점 🧐1. Symbol 타입강사님이 생략하고 넘어간 타입인데 궁금해서 찾아봤다.Symbol이란?ES6에서 추가된 Primitive 타입 중 하나. 고유하고 변경 불가능한(immutable) 값을 생성할 때 사용된다. 또한 값을 은닉하고 싶을 때 사용한다.const sym1 = Symbol(); const sym2 = Symbol(); console.log(sym1 === sym2); // falseSymbol() 함수를 호출해 생성함위 코드는 각각 새로운 Symbol을 생성하므로 다른 값을 가짐const sym3 = Symbol("description"); const sym4 = Symbol("description"); console.log(sym3 === sym4); // false생성 시 description을 받을 수 있지만 심볼의 고유성과는 연관이 없다.디버깅 용도로 사용된다.Symbol의 특징고유성 위와 같이 같은 설명을 가진 Symbol도 항상 다른 값이다.변경 불가능한번 생성된 Symbol은 변경 불가능하다.자동 형 변환 불가자동으로 문자열이나 숫자로 변환되지 않는다.Symbol과 객체 프로퍼티객체의 고유한 프로퍼티 키로 사용이 가능하다const ID = Symbol("id"); const user = { name: "Alice", [ID]: 12345 // Symbol을 키로 사용 }; console.log(user[ID]); // 12345 console.log(Object.keys(user)); // ["name"] console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)]Object.keys(), Object.values() 등으로 확인할 수 없음 (은닉)Object.getOwnPropertySymbols()로만 가져올 수 있다.Symbol.for과 전역 심볼 레지스트리Symbol.for()를 사용하면 Global Symbol Registry에 심볼을 저장하고 검색할 수 있다.Symbol.for("key")를 사용하면 같은 key를 가진 Symbol을 공유할 수 있다.const sym1 = Symbol.for("sharedKey"); const sym2 = Symbol.for("sharedKey"); console.log(sym1 === sym2); // true (같은 키를 공유하므로 동일한 심볼)Symbol.keyFor()로 전역 레지스트리에 저장된 Symbol의 key를 찾을 수 있다.const globalSym = Symbol.for("globalSymbol"); console.log(Symbol.keyFor(globalSym)); // "globalSymbol" const localSym = Symbol("localSymbol"); console.log(Symbol.keyFor(localSym)); // undefined (전역 레지스트리에 등록되지 않음)전역 심볼 레지스트리, 그래서 이거 언제 쓸까?모듈간 데이터 공유 시, 같은 키를 사용하면 다른 모듈에서도 동일한 Symbol을 재사용 할 수 있다.싱글톤 패턴 구현 시 사용한다.애플리케이션 내에서 유일한 인스턴스 유지할 때 활용한다.내장 심볼 (Well-known Symbols)ECMAScript에서는 특정 기능을 커스터마이징 할 수 있도록 미리 정의된 Symbol을 제공한다.Javascript 엔진의 기본 동작을 변경할 수 있도록 설계된 심볼이다.활용 시 객체의 이터러블 구현, 원시값 반환, instanceof 동작 변경 등을 할 수 있다. 내장 심볼 예시Kotlin의 override와 비슷한 듯 하다. 2. for 문에서 출력하는 부분const user = { name: "Ko", province: "경기도", city: "용인시", }; for (let x in user) { console.log(`${x}: ${user[x]}`); }x 그리고 user[x]로 출력하고 있다.user로 출력하면 어떻게 나오는지 확인해보니 [object Object]라고 나온다.찾아보니 for .. in .. 으로 반복 시 객체의 key 값으로 꺼내온다고 한다.따라서 값을 얻기 위해서는 user[x] 와 같은 방식을 사용해야한다. for .. of ..for .. of .. 의 경우 iterable 객체(Array, Set, Map)의 value 값을 순회한다.const arr = ["A", "B", "C"]; for (let item of arr) { console.log(item); // A, B, C }Array의 경우 정상 출력된다.for (let value of user) { console.log(value); } // TypeError: user is not iterable객체에 사용하면 에러가 난다. 객체에서 for .. of .. 를 사용하려면?Object.keys(), Object.values(), Object.entries() 를 사용하면 가능 // key만 순회 for (let key of Object.keys(user)) { console.log(key); } // value만 순회 for (let value of Object.values(user)) { console.log(value); } // key-value 쌍 순회 for (let [key, value] of Object.entries(user)) { console.log(`${key}: ${value}`); } 3. forEach의 인자const locations = ['서울', '부산', '경기도', '대구']; locations.forEach(function (location, index, array) { console.log(`${index} : ${location}`); console.log(array); })여기서 어떻게 location, index, array를 지정해서 쓸 수 있나 궁금해서 찾아봤다.Array.prototype.forEach()는 배열의 각 요소에 대해 한 번씩 지정된 콜백 함수를 실행하는 메서드이다.기본적으로 매개변수 element, index, array로 내부 콜백함수로 정의되어 있다.element : 현재 순회 중인 배열 요소 (ex: 서울, 부산..)index: 현재 요소의 인덱스 (ex: 0, 1..)forEach()가 호출된 원본 배열 (ex: locations)  4. Function과 Method의 차이Function (함수)독립적으로 정의되고 실행될 수 있는 일반적인 코드 블록특정 객체에 속하지 않는다function 키워드 또는 const 함수명 = () => {} 형식으로 사용 가능function sayHello() { console.log("Hello, world!"); } const add = (a, b) => a + b; Method (메서드)객체의 프로퍼티로 정의된 함수객체에 속하기 때문에 해당 객체의 데이터를 조작하는 역할을 한다.const person = { name: "Alice", greet: function() { console.log(`Hello, my name is ${this.name}`); } };This 키워드 차이Method는 객체 내부에서 this를 사용해 객체 프로퍼티에 접근이 가능함Function의 경우 this가 글로벌 객체(ex: window 또는 undefined(strict mode))를 가리킨다.5. Constructor Functionfunction Audio(title) { this.title = title; console.log(this); } const audio = new Audio('a')강의를 보다가, 해당 코드가 왜 title을 따로 설정(?)도 안하고 바로 this.title을 쓸 수 있는지 이해가 안갔다.관련해서 찾아보니 아래와 같았다.생성자 함수를 사용해 새로운 객체를 만들고, 그 객체의 속성(title)을 동적으로 할당하는 것 new Audio('a')를 실행시 new 키워드의 동작새로운 빈 객체 {}를 생성this를 새로 생성된 객체로 바인딩생성자 함수의 코드를 실행 (this.title = title;)새로 생성된 객체를 반환new 없이 호출한다면 this가 전역 객체를 가리키게 되서 title이 전역 변수로 선언되거나 strict mode에서는 오류가 발생한다. 따라서 의도하지 않은 동작을 방지하려면 new를 꼭 사용해야한다. 6. Strict Mode"use strict"; 추가시 사용이 가능함var, let, const 없이 변수 선언이 금지된다.읽기 전용 속성 변경이 금지된다. (애초에 왜 되는데?)같은 이름의 매개변수가 금지 된다.delete로 변수 삭제가 금지된다.this 값이 undefined가 된다.일반적으로 JS에서는 this는 전역 객체를 가리키는데 strict mode에서는 this가 undefined로 설정된다.따라서 잘못된 this 사용을 막는다.모든 최신 JavaScript 프로젝트에서 기본적으로 사용하는게 좋다.7. IIFE (Immediately Invoked Function Expression)기본 구조  (function() { console.log("즉시 실행됨!"); })(); (() => { console.log("즉시 실행됨!"); })();왜 IIFE를 사용할까?전역 변수 오염 방지JS는 기본적으로 전역 스코프(Global Scope)를 가져서 코드가 길어질 수록 충돌할 가능성이 큼IIFE를 사용하면 함수 내부의 변수는 외부에서 접근할 수 없도록 보호할 수 있음 // 전역 변수를 오염시키는 경우 let counter = 0; function increment() { counter++; console.log(counter); } increment(); // 1 increment(); // 2 console.log(counter); // 2 (외부에서 counter 변경 가능) // IIFE를 사용하여 보호 const increment = (() => { let counter = 0; // 외부에서 접근 불가 return () => { counter++; console.log(counter); }; })(); increment(); // 1 increment(); // 2 console.log(typeof counter); // undefined (외부에서 접근 불가) 한 번만 실행되는 초기화 코드즉시 실행 되므로 초기화 코드 실행하는데 유용함 클로저 활용 가능const increment = (() => { let counter = 0; // 클로저로 보호된 변수 return () => { counter++; console.log(counter); }; })(); increment(); // 1 increment(); // 2 increment(); // 3 console.log(typeof counter); // undefined (외부에서 접근 불가)counter가 클로저에 의해 보호되어 있기 때문에 외부에서 직접 변경이 불가능하고 오직 함수 호출을 통해서만 조작이 가능함 객체를 사용해 상태를 관리하는 방식과의 차이IIEF 사용하는 경우const increment = (() => { let counter = 0; return () => { counter++; console.log(counter); }; })(); increment(); // 1 increment(); // 2 console.log(typeof counter); // undefined (외부 접근 불가)IIFE 내부에 counter가 있어서 외부에서 변경이 불가능객체를 사용하는 경우const obj = { counter: 0, increment: function() { this.counter++; console.log(this.counter); } }; obj.increment(); // 1 obj.increment(); // 2 console.log(obj.counter); // 2 (외부에서 변경 가능)counter 변수가 객체 내부에 있지만 외부에서 수정 가능 차이점 정리IIFE 방식 / 객체 방식스코프 보호 : counter 외부에서 접근 불가 / counter 외부에서 수정 가능전역 오염 방지 : 변수는 IIFE 내부에만 존재 / 변수는 객체에 저장되어 외부에서 접근 가능사용 목적 : 한정된 기능 (ex: 특정 함수의 상태 유지) / 여러 속성과 메서드를 관리하는 구조  8. Curry Function커링 함수란?function addCurry(a) { return function (b) { return a + b; }; } const add3 = addCurry(3); console.log(add3(5)); // 8 console.log(addCurry(3)(5)); // 8함수를 쪼개서 여러 단계로 호출할 수 있도록 변환하는 기법하나의 함수에서 여러 개의 인자를 한 번에 받는 대신, 부분적으로 받아서 실행하는 방식이다.강의를 들으면서, 어떻게 쓰는지는 알겠는데 왜 쓰는지 모르겠어서 찾아보았다. 🤔 커링 함수, 왜 쓸까?재사용성 증가 function multiply(a) { return function (b) { return a * b; }; } const double = multiply(2); // 2를 미리 적용 const triple = multiply(3); // 3을 미리 적용 console.log(double(5)); // 10 console.log(triple(5)); // 15여기서 double은 2를 미리 적용해서 항상 2 * b를 실행하는 함수가 된다.함수 조합(Function Composition)에 유용함const add = a => b => a + b; const multiply = a => b => a * b; const add5 = add(5); const multiply3 = multiply(3); console.log(add5(10)); // 15 console.log(multiply3(10)); // 30함수를 조합해 더 작은 단위의 함수를 쉽게 만들 수 있다.부분 적용, 함수 조합, 설정 저장 등에 유용하다.코드 가독성 및 유지보수성 향상const log = level => message => console.log(`[${level}] ${message}`); const errorLog = log("ERROR"); const warningLog = log("WARNING"); errorLog("서버가 다운되었습니다."); // [ERROR] 서버가 다운되었습니다. warningLog("메모리가 부족합니다."); // [WARNING] 메모리가 부족합니다.코드를 더 읽기 쉽게 만들고 유지보수하기 쉬운 형태로 관리할 수 있다. 9. 생성자 함수와 Class, Object.create()의 차이생성자 함수function Person(name, age) { this.name = name; this.age = age; } Person.prototype.greet = function() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); }; const john = new Person("John", 30); john.greet(); // "Hello, my name is John and I am 30 years old."생성자 함수는 new 키워드와 함께 호출될 때 새로운 객체를 생성함.this를 사용해 객체의 속성을 설정한다ES6에 도입된 class 문법이 좀 더 직관적임.명시적으로 프로토타입을 지정해야 메서드 공유가 가능복잡해질수록 코드가 길어지고 가독성이 낮아진다.Classclass Person { constructor(name, age) { this.name = name; this.age = age; } greet() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } } const john = new Person("John", 30); john.greet(); // "Hello, my name is John and I am 30 years old."class 키워드를 사용해 정의메서드를 클래스 내부에 선언해 프로토 타입을 활용함자동으로 프로토타입을 활용해 메서드를 공유함객체지향 언어와 유사한 형대로 직관적인 코드 작성이 가능하다.기능적으로 생성자 함수와 동일함Object.create()const personPrototype = { greet: function() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } }; const john = Object.create(personPrototype); john.name = "John"; john.age = 30; john.greet(); // "Hello, my name is John and I am 30 years old." 특정 객체를 프로토타입으로 명확하게 설정 가능같은 프로토타입을 공유하면서 새로운 객체 생성 가능클래스 없이도 객체 상속이 가능프로토타입을 명확히 컨트롤할 필요가 있을 때 사용하면 유용함하지만 class가 더 직관적이고 가독성이 좋아서 class를 사용하는 것이 좋음 미션 1메뉴판 화면에서 메뉴 카테고리 선택 시 카테고리별로 보여주는 화면을 만드는 것해결 과정해결 방안 고민HTML을 여러개 사용해 메뉴 클릭시 화면을 전환하게 한다.기본 틀 HTML을 하나를 두고 카테고리 클릭 시 JS로 화면을 변경한다여기서 1번은 비효율적으로 보이고, 또 미션에서 보이는 화면이 각 메뉴별로 동일한 화면을 쓰고 있어서 2번을 채택함.개발 과정일단 기본적으로 div로 html/css 뼈대를 잡음<body> <h1 class="food-menu text-3xl font-bold underline"> Food Menu </h1> <div class="button-container"> <button class="food-button">All</button> <button class="food-button">Breakfast</button> <button class="food-button">Lunch</button> <button class="food-button">Shakes</button> <button class="food-button">Dinner</button> </div> <div class="image-container"> <div class="column"> <img class="food-img" src="images/food1.jpg"/> <img class="food-img" src="images/food2.jpg"/> <img class="food-img" src="images/food3.jpg"/> </div> <div class="column"> <img class="food-img" src="images/bread.jpg"/> <img class="food-img" src="images/breakfast.jpg"/> <img class="food-img" src="images/cake.jpg"/> </div> <div class="column"> <img class="food-img" src="images/potato.jpg"/> <img class="food-img" src="images/shake.jpg"/> <img class="food-img" src="images/salad.jpg"/> </div> </div> <script src="js/script.js"></script> </body>카테고리 값을 구분하려면 어떻게 해야할까?사용자 정의 속성을 넣을 수 있음<body> <h1 class="food-menu text-3xl font-bold underline"> Food Menu </h1> <div class="button-container"> <button class="food-button" data-category="all">All</button> <button class="food-button" data-category="breakfast">Breakfast</button> <button class="food-button" data-category="lunch">Lunch</button> <button class="food-button" data-category="shakes">Shakes</button> <button class="food-button" data-category="dinner">Dinner</button> </div> <div class="menu-items"> <div class="menu-item" data-category="breakfast"> <img class="food-img" src="images/food1.jpg"/> </div> <div class="menu-item" data-category="lunch"> <img class="food-img" src="images/food2.jpg"/> </div> <div class="menu-item" data-category="shakes"> <img class="food-img" src="images/food3.jpg"/> </div> <div class="menu-item" data-category="dinner"> <img class="food-img" src="images/bread.jpg"/> </div> <div class="menu-item" data-category="breakfast"> <img class="food-img" src="images/breakfast.jpg"/> </div> <div class="menu-item" data-category="lunch"> <img class="food-img" src="images/cake.jpg"/> </div> <div class="menu-item" data-category="shakes"> <img class="food-img" src="images/potato.jpg"/> </div> <div class="menu-item" data-category="dinner"> <img class="food-img" src="images/shake.jpg"/> </div> <div class="menu-item" data-category="breakfast"> <img class="food-img" src="images/salad.jpg"/> </div> </div> <script src="js/script.js"></script> </body>사용자 정의 속성으로 속성을 구분하도록 수정const buttons = document.querySelectorAll(".food-button"); buttons.forEach(button => { button.addEventListener("click", function() { const category = this.dataset.category; if (category === "all") { console.log("all"); } else { console.log("else"); } }); });사용자 정의 속성 사용시 dataset으로 사용이 가능하다data- 이후의 이름으로 가져올 수 있다.const buttons = document.querySelectorAll(".food-button"); const menuItems = document.querySelectorAll(".menu-item"); buttons.forEach(button => { button.addEventListener("click", function() { const category = this.dataset.category; menuItems.forEach(item => { if (category === "all") { item.style.display = "flex"; } else { if (item.dataset.category === category) { item.style.display = "flex"; } else { item.style.display = "none"; } } }); }); });display=none 옵션으로 일부 메뉴를 가려준다.const buttons = document.querySelectorAll(".food-button"); const menuItems = document.querySelectorAll(".menu-item"); buttons.forEach(button => { button.addEventListener("click", function () { const buttonCategory = this.dataset.category; menuItems.forEach(item => { const itemCategory = item.dataset.category; item.style.display = ["all", itemCategory].includes(buttonCategory) ? "flex" : "none" }); }); });코드를 좀 더 함수형으로 리팩토링 해본다. 회고CSS가 더 어렵다 😔아직 JS에 익숙하지 않아서 머리로 로직을 세우는 것과 실제로 어떤걸 써야할지 감이 잘 안오는 것 같다.실제로 구현해보니 강의만 듣는 것보다 어떤식으로 개발해야할지 감이 오는 것 같다. 미션2가위바위보플레이어와 컴퓨터가 있고 가위/바위/보 선택시 승리한 경우 플레이어 또는 컴퓨터의 카운트가 올라감최종 게임 승리 여부를 출력해 줌.해결 과정기능 파악플레이어와 컴퓨터는 각각의 승리 카운트 상태값을 가지며 승패 여부에 따라 카운트가 업데이트 됨.가위/바위/보 클릭 시, 컴퓨터는 랜덤하게 가위/바위/보 값을 가짐가위/바위/보 클릭 시, 선택하기 카운트가 줄어듬.플레이어의 가위/바위/보 상태와 컴퓨터의 상태를 비교해 승리 여부를 판단함최종 플레이어 승리 카운트와 컴퓨터의 승리 카운트를 비교해 최종 승패 여부를 출력함.다시 시작 클릭시 게임을 다시 시작할 수 있음.개발 과정html과 연동 하는 부분이 익숙하지 않아서, 일단 JS로 로직부터 개발함let playerWinCount = 0; let computerWinCount = 0; let roundCount = 10; function computerPlay() { let choices = ['rock', 'paper', 'scissors']; return choices[Math.floor(Math.random() * choices.length)]; }; function playRound(playerSelection, computerSelection) { if (playerSelection === computerSelection) { return '무승부'; } else if ( (playerSelection === 'rock' && computerSelection === 'scissors') || (playerSelection === 'paper' && computerSelection === 'rock') || (playerSelection === 'scissors' && computerSelection === 'paper') ) { playerWinCount++; return '플레이어 승리'; } else { computerWinCount++; return '컴퓨터 승리'; } } function playerPlay() { document.querySelectorAll('.player-choice').forEach((button) => { button.addEventListener('click', function() { return button.id; }); }); } function game() { for (let i = 0; i < roundCount; i++) { let playerSelection = playerPlay(); let computerSelection = computerPlay(); console.log(playRound(playerSelection, computerSelection)); } if (playerWinCount > computerWinCount) { console.log('플레이어 승리'); } else if (playerWinCount < computerWinCount) { console.log('컴퓨터 승리'); } else { console.log('무승부'); } }이후 html 연동하는 부분을 붙임 (길어서 코드 생략)최종 코드let playerWinCount = 0; let computerWinCount = 0; let roundCount = 10; const resultDiv = document.querySelector('#result'); const resultMessage = document.querySelector('#result-message'); const playerWinCountDiv = document.querySelector('#player-win-count'); const computerWinCountDiv = document.querySelector('#computer-win-count'); const roundCountDisplay = document.querySelector('#round-count'); const resetButton = document.querySelector('#reset'); function computerPlay() { let choices = ['rock', 'paper', 'scissors']; return choices[Math.floor(Math.random() * choices.length)]; }; function playRound(playerSelection, computerSelection) { if (playerSelection === computerSelection) { return '무승부'; } else if ( (playerSelection === 'rock' && computerSelection === 'scissors') || (playerSelection === 'paper' && computerSelection === 'rock') || (playerSelection === 'scissors' && computerSelection === 'paper') ) { playerWinCount++; updateUI(); return '플레이어 승리'; } else { computerWinCount++; updateUI(); return '컴퓨터 승리'; } } function updateUI() { playerWinCountDiv.textContent = playerWinCount; computerWinCountDiv.textContent = computerWinCount; roundCountDisplay.textContent = roundCount; } function game(playerSelection) { if (roundCount === 0) { alert('게임이 끝났습니다. 게임을 다시 시작하려면 [다시 시작] 버튼을 누르세요.'); return; } roundCount--; updateUI(); let computerSelection = computerPlay(); let playResult = playRound(playerSelection, computerSelection); console.log(playResult); resultDiv.style.display = 'block'; resultMessage.textContent = playResult; if (roundCount === 0) endGame(); } function endGame() { if (playerWinCount > computerWinCount) { console.log('게임에서 이겼습니다.'); resultMessage.textContent = '게임에서 이겼습니다.'; } if (playerWinCount < computerWinCount) { console.log('게임에서 졌습니다.'); resultMessage.textContent = '게임에서 졌습니다.'; } if (playerWinCount === computerWinCount) { console.log('무승부입니다.'); resultMessage.textContent = '무승부입니다.'; } resultDiv.style.display = 'none'; resetButton.style.display = 'block'; } function resetGame() { playerWinCount = 0; computerWinCount = 0; roundCount = 10; updateUI(); resultMessage.textContent = ''; resetButton.style.display = 'none'; } document.querySelectorAll('.player-choice').forEach((button) => { button.addEventListener('click', function() { game(button.id); }); }); resetButton.addEventListener('click', function() { resetGame() });회고CSS는 신경 안쓰고 기능 개발에만 집중하니 훨씬 수월했다.처음에는 막막했는데 일단 BE 개발하듯 로직부터 접근하니 개발하기 쉬웠다. 미션3퀴즈 앱해결 과정기능 파악정답을 틀리거나 맞출 경우 Next 버튼이 생성되며 다음 퀴즈를 할 수 있음퀴즈는 회색 화면에 answer 3가지가 존재 (값/정답이 없는 경우)정답을 맞출 경우 초록 화면 / 틀릴 경우 빨간 화면퀴즈 종료 시 restart 버튼이 생성 됨.개발 과정로직개발까지는 문제 없었으나 next 버튼과 reset이 제대로 동작안하는 이슈가 발견됨알고보니 addEventListener 를 함수 내부에 선언해 함수를 중복해서 사용해 리스너가 중복으로 실행된 것리스너를 함수 밖으로 빼고 해결함.회고Listener의 동작 방식을 모르고 사용한 것 같다.글로벌 변수를 안쓰는 방향으로 가고 싶은데 어떤식으로 해야할지 아직은 잘 모르겠다. 미션 4책 관리 앱 해결 과정기능 파악form에 책 데이터를 입력 받는다데이터 입력 후 submit 시 하단에 책목록에 추가된다책목록에 있는 데이터는 X 버튼으로 삭제할 수 있다.책 추가 또는 삭제시 알림 메세지가 뜬다.개발 과정submit 이벤트를 어떻게 받는지부터 고민 했는데 addEventListener에서 가능했다받아온 event는 event.target 을 통해 값을 꺼내올 수 있다.createElement를 통해 책목록, 알림요소들을 추가해주었다.회고  이전 과제들보다 오히려 쉬운 느낌이었다. (특히 퀴즈..) 미션 5Github Finder 앱해결 과정기능 파악유저가 입력하는대로 Github User를 검색하는 AppSearch 버튼을 따로 누르지 않고 입력 받는대로 API 호출을 한다.개발 과정일단 API 호출을 하기 위해 await fetch 를 사용함그리고 UI를 만듦...API를 여러번 호출하는데 debounce 라는 개념이 있어서 알아보았다 회고debounce 를 적용하는 것 외에는 딱히 어려운 점은 없었다.

프론트엔드Javascript

kk 5개월 전
채널톡 아이콘