블로그

볼드 UX

[인프런 워밍업 스터디 1기 디자인] 오리엔테이션 준비하기

 안녕하세요! 지식공유자 볼드입니다. 최근에 인프런 워밍업 스터디 클럽 1기에서 프로덕트 디자인 코치로 참여하게 되었어요.준비 과정이 꽤 새로웠고, 많은 것을 배우는 시간이었습니다. 오늘은 제가 어떻게 러너분들과 첫 만남을 위해 준비를 하였는지 알려드리고자 해요.   첫 만남을 미리 계획하다저는 4주 전부터는 0기 코치님들이 남겨둔 자료들을 보며 어떻게 하면 더 좋은 오리엔테이션을 만들 수 있을지 고민했어요. 구조부터 차근차근 짜고, 내용을 채워 넣어서 빠르게 프레젠테이션을 완성했습니다. 첫만남인 만큼 어떻게 하면 더 재미있고, 참여자들과 적극적으로 소통할 수 있을까 고민을 많이 했어요. 그래서 피그잼을 사용한 워크샵 형태로 진행하기로 결정하고, 세 가지 큰 원칙을 세웠습니다:많은 정보를 빠르게 명확하게 전달하기최대한 재미있고 인터랙티브하게 이야기가 살아있는 컨셉 유지하기 다행히 ‘러너’라는 주제가 이미 있어서 그걸로 컨셉을 잡았고, 다음과 같은 여정으로 구성해 보았어요.🚀 출발: 워밍업 클럽을 시작하게 된 이유🗺 코스: 워밍업 클럽의 미션들🎯 도착: 워밍업 클럽을 마치고 받게 되는 혜택들    OT 시작 전에는 새 직장에서 바쁠 것 같아서 미리 인프런 담당자 셰리님과 자료를 공유하고 점검하는 시간을 가졌어요.그리고 막상 OT 주간이 되니, 예상대로 정신 없었습니다. OT 당일에는 반차를 내고, 오전에 교회에서 성경공부를 마치고 집에 돌아와 커피 한 잔 마시며 마지막 준비를 했죠.    러너 분들과 드디어 만나다영국시간으로 12시에 시작했어요.(한국 시간으로는 오후 8시), 제가 먼저 짧게 발표를 먼저 진행하고 러너 분들은 질문에 따라 각자 글을 작성하셨어요.  작성 후에는 서로의 글을 보며 하트를 남기는 시간을 가졌는데, 이게 생각보다 더 재미있었던 것 같아요.  미리 준비한 탭으로 미션 정보를 빠르게 효과적으로 보여드리고, 원래 OT 전까지 블로그 글을 쓰지 못했는데 셰리님의 빠른 대처로 발자국 미션 시연을 성공적으로 마칠 수 있었어요.  OT 끝나고 난후워크샵이 끝난 후, 참가자분들의 피드백을 부탁드렸어요. 피드백을 보고 나니 제가 준비한 만큼 결과도 좋았다는 생각이 들더군요.(아래는 제가 몇개 선정한 감사한 피드백!)  2기에도 제가 참여할지는 아직 모르겠지만 2기에도 오리엔테이션 준비 경험을 살리거나 또 다른 코치님들이 사용할 수 있도록 이 피그잼 보드를 템플릿화하면 좋을 것 같아요. 또한, 이 방식을 다른 온라인 강의에서도 활용할 수 있을 것 같아요. (필요하신 분들은 알려주세요. 무료 나눔해드릴게요!) 마지막으로 인프런 워밍업 클럽 이전에 제가 진행한 인증샷 스터디에서 수강생과 교류가 있으면 좋을 것 같다는 의견이 있었어요. 처음엔 이걸 어떻게 개선해야할지 막막했는데, 인프런 워밍업 클럽을 참여하면서 이 문제를 해결할 수 있었어요. 그리고 셰리님을 포함한 인프런 팀이 없었다면 이 모든 게 불가능했을 거예요. 정말 감사드립니다! 인프런팀 만세! 앞으로 남은 세 번의 특강, 워크샵을 어떻게 준비할지 계획 중인데, 라이브 튜토리얼과 프레젠테이션을 어떻게 잘 조합할지, 함께 만들어가는 워크샵 과정이 어떨지 기대되네요. 인프런 워밍업 클럽 1기에 참여하신 모든 러너분들 다같이 파이팅해요 🔥     

UX/UI워밍업클럽디자인시스템피그마

장서윤

[인프런 워밍업 클럽 0기] 2주차 발자국 👣

이번 발자국은 과제 진행 과정을 작성해 볼 예정이다. 목차는 다음과 같다.1. 기능 목록 작성2. 공통 컴포넌트 구현3. 결과물4. 고민했던 부분 ✅️ 1. 기능 목록 작성1. 항목 추가/수정할 수 있다.지출 항목 + 비용을 입력받는다 (조건을 만족할 때까지)지출 항목은 문자열이여야 한다.비용은 숫자여야 한다.지출 항목 + 비용 모두 입력되어야 한다. (공백 제외)  조건을 만족할 경우, 버튼이 enable 된다. 추가/수정을 완료했을 경우, toast 메시지를 띄워준다. 2. 항목 리스트를 보여준다. (테이블 형식)각 항목(row) 마다 수정/삭제 버튼이 존재한다.수정 버튼을 누른 경우[ 기능목록 1. 항목 추가/수정할 수 있다 ] 로 이동한다.삭제 버튼을 누른 경우항목이 삭제되며, toast 메시지를 띄워준다. 총 지출 금액을 보여준다.항목 리스트가 없을 경우, '존재하지 않습니다' 를 보여준다.   3. 모든 항목을 삭제할 수 있다.목록 지우기 버튼을 누른 경우모든 항목이 삭제되며, toast 메시지를 띄워준다. ✅ 2. 공통 컴포넌트 구현MUI와 같은 UI 라이브러리를 쓰지 않고, tailwind css로만 구현할 것이기에, 필요한 컴포넌트는 직접 만들어야한다. 먼저 공통된 디자인을 위해 rounded만을 사용하고자 했다. ( 컴포넌트마다 rounded를 다 다르게 사용하지 않는다)색상은 emerald + slate 만을 최대한 사용했다. 그렇게 해서 필요한 컴포넌트는 다음과 같다. Outlined Input시간을 투자한 부분이다. 기본 html의 input은 굉장히 단순하기에 커스텀이 필요했다.focus 했을 때, label 을 input 박스 위로 가게 하고, 부드러운 애니메이션을 넣고자 했다.Contained Button + Text Button배경을 채운 Contained Button오직 text 만 존재하는 Text ButtonTable기본 table에 css만 추가했다.Toast 메시지 success : 초록색 체크 아이콘추가, 수정, 삭제가 성공적으로 완료되었음을 표시한다. warn : 노란색 경고 아이콘입력값의 유효성검사가 일치하지 않을때 표시한다.  ✅ 3. 결과물 ✅ 4. 고민했던 부분 지출 항목이 문자여야하는데, 이를 어떻게 판별하는가? 이다.애매한 부분이 지출 항목이 "맥북 pro 16" 처럼 오직 문자 type으로 이뤄지지 않고, 여러 type이 같이 존재할 수 있다. 그래서 이걸 어떻게 예외처리 해줄지 고민했었는데, 일단은 지출 항목을 절대 숫자로만 이뤄지지는 않을 것 같아서, isNaN()만을 판별했다. 이 부분은 고민이 더 필요할 것 같다.. toast 메시지의 색상을 어떻게 할 것인가? 이다.상품을 "삭제" 했을 경우, toast 메시지의 아이콘 색상을 고민했었다.빨간색 -> 부정적 의미 -> 삭제와 연관된다! -> 그러나 error 와도 연관됨 -> 사용자 입장에서 "에러가 났다..!" 로 혼동할 수 있음.초록색 -> 삭제가 완료되었다! 에 의미를 둠-> 그러나, 추가, 수정, 삭제도 어쨌든 완료이기에, 다른 기능임에도 아이콘 색상이 같아서 구별이 어렵다는 문제가 존재함.고민 끝에 error와 연관되는 빨간색보다는 초록색으로 가되, "추가", "수정", "삭제" text 를 크고 두껍게 처리해주는 것으로 합의를 보았다!후기UI 라이브러리만 사용하다가, tailwind css로 직접 컴포넌트를 만드니까, 생각보다 시간이 오래 걸렸다. 중간에 계속 애니메이션도 적용된 라이브러리를 사용하고 싶었지만, 이를 css로(비록 tailwind css지만) 직접 완성시켰을때 상당히 뿌듯했다!또한, 기능목록을 제대로 작성한건지 모르겠다. 조금 더 깔끔하게 작성하고 싶은데, 어디까지 자세하게 적어야하는지, ui 부분도 자세하게 적어야하는지(버튼 색깔이 바뀐다거나)를 잘 모르겠다. 더 공부해봐야겠다!  

웹 개발프론트FE워밍업클럽

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 2 발자국

발자국워밍업 스터디 클럽이 2주 차에 접어들었습니다. 해당 발자국은 따라 하며 배우는 리액트 A-Z (섹션 0-5) 중심으로 작성되었습니다.요약React를 사용하려면 Node.js가 필요하다. Node.js를 설치하면 NPM도 같이 설치되니 꼭 Node.js를 설치하자. Node.js 공식 홈페이지에 접속하면 2개의 Node 버전이 있는데, 그중에서 안정적인 버전인 LTS를 설치하면 된다. Section 01. React[ React란? ]리액트는 사용자 인터페이스(user interface, UI)를 만들기 위해서 사용되는 자바스크립트의 라이브러리다. 리액트는 인터렉션이 많은 웹 앱을 개발하기 위해서 주로 사용된다. 이렇게 사용자 인터페이스를 만들기 위해 도움을 주는 TOOL로는 리액트 말고도 Vue.js와 Angular.js가 있다.React: 라이브러리Angular, Vue: 프레임워크[ Framework vs Library ]프레임워크와 라이브러리를 대략 설명하자면 다음과 같다.Framework : 어떠한 앱을 만들기 위해 필요한 대부분의 것을 가지고 있다.Library : 어떠한 특정 기능을 모듈화 해 놓은 것이다.프레임워크는 앱을 만드는데 필요한 대부분의 라이브러리를 가지고 있으며, 라이브러리들은 특정 기능을 위해 모듈화 되어있다.리액트는 라이브러리이다. 왜냐? 리액트는 전적으로 UI를 렌더링 하는 데 관여하기 때문이다. 리액트는 여러 모듈을 사용하며 앱을 관리한다.라우팅: react-router-dom …상태관리: redux, mobx …빌드: webpack, npm …테스팅: Eslint, Mocha …[ React Component ]리액트를 공부하다보면 무조건 마주치는 단어가 있다. 바로 컴포넌트이다. 리액트는 컴포넌트 기반이라고 하는데, 이 컴포넌트는 무엇을 말하는 것일까?컴포넌트(Component): React로 만들어진 웹/앱을 이루는 최소한의 단위리액트는 이 컴포넌트를 통해서 웹/앱을 개발하게 된다.리액트는 여러 컴포넌트 조각으로 되어있다. 이것은 블록같다고 생각하면 된다. 여러 블록 조각을 맞추고 쌓아 올려 하나의 블록 작품을 완성하는 것. 리액트도 마찬가지로 컴포넌트를 이리저리 조합하고 쌓아올려 하나의 웹 페이지를 구성하게 된다.리액트 컴포넌트에는 2가지가 있다.클래스형 컴포넌트함수형 컴포넌트React는 여러 컴포넌트 조각으로 구성된다.개인적인 설명을 덧 붙이자면 리액트는 레고 블럭과 같다고 생각한다. 레고 블럭들을 하나 둘 씩 쌓아 올려 하나의 완성된 레고 작품을 만드는 것이다.[ Component 종류 ]React는 2개의 컴포넌트 종류가 있다.클래스형 컴포넌트(Class Components)class App extends Component { render() { return <h1>Hello, ReactJS!</h1>; } }함수형 컴포넌트(Functioanl Components)function App() { return <h1>Hello, ReactJS!</h1>; }💡 현재 함수형 컴포넌트를 HOOK이랑 해서 많이 사용한다.💡 참고로 컴포넌트를 작성할 때 반드시 대문자 시작을 해야 한다. 소문자 시작 시 body, h1, p 같은 DOM 태그로 인식해 버린다.[ 브라우저가 그려지는 원리와 가상 돔 ]React의 가장 큰 특징은 가상 돔(Virtual DOM)이다. 이것을 사용하는 이유는 인터렉션 때문이다. 이 인터렉션에 의해 DOM에 변화가 발생하면 다시 DOM을 재구성하기 시작한다.JS 발자국에도 남겼었지만 웹 브라우저의 경우 다음과 같은 과정을 겪고 이 과정은 비용이 꽤 든다.Critical Render Path (웹 페이지 렌더링 과정): 데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ PaintDOM을 재구성 한다는 것은 위 렌더링 과정을 다시 반복한다는 것이다. 즉, 인터렉션이 일어날때마다 위 과정을 다시 한다. 이것을 보완하기 위해서 나온 것이 가상 돔이다.가상돔 과정을 살펴보자..!데이터가 바뀌면 가상 돔에 렌더링 되고, 이전에 생긴 가상 돔과 비교를 해서 바뀐 부분만 실제 돔에 적용 시킨다.바뀐 부분을 찾는 과정을 Diffing이라고 부른다.바뀐 부분만 실제 돔에 적용 시키는 것을 Reconciliation(재 조정)이라고 부른다.[ Create React App 을 이용해서 리액트 설치하기 ]create-react-app 을 통해서 원하는 위치에 리액트를 설치할 수 있다. 이 때, Webpack과 Babel이 함께 설치가 된다. 따라서 React 앱 생성 전에 Webpack과 Babel에 대해서 간단히 알고 가자.Webpack정의: Webpack: 웹팩은 오픈 소스 자바스크립트 모듈 번들러써 여러 개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축고 최적화하는 라이브러리이다.장점여러 파일의 자바스크립트 코드를 압축하여 최적화할 수 있기 때문에 로딩 줄일 수 있. (네트워크 비용 줄음)모듈 단위로 개발이 가능하여 가독성과 유지 보수가 쉽다.Babel정의: 최신 자바스크립트 문법을 지원하지 않는 브라우저들을 위해서 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 변환 시켜주는 라이브러리이다.⇒ 이러한 Webpack과 Babel은 개발자가 React 개발 시 알아서 설정 해야 하지만 Create-React-App을 사용해서 React 앱을 생성하면 Babel이나 Webpack 설정이 이미 되어있기 때문에 준비 시간이 단축된다.[ Create-React-App ]프로젝트를 진행할 폴더 생성VSC에서 해당 프로젝트 폴더 열기Termial에 npx create-react-app 생성할파일명 입력강의에서는 npx create-react-app ./을 입력하였다../는 현재 위치를 뜻한다.[ npx create-react-app 에 대하여 ]npx: 노드 패키지 실행을 도와주는 도구이다.npx create-react-app이란 npm 레지스트리에 잇는 패키지를 ./에 실행시켜서 React를 설치해 주는 것이다.실행하는 방법실행하고자 하는 리액트 파일 위치에서 npm run start 입력(강의에서는 npm run start방법만 소개시켜 주셧는데 npm start도 가능하다.)🤔 개인적으로 요즘 vite에 관한 이야기가 보이는데 이도 조사해 보아야겠다… Section 2. 간단한 To-Do 앱 만들며 리액트 익히기[ create react app ]create-react-app으로 리액트를 설치하면 여러 파일이 등장하는데, 이 중에서 절대로 이름을 수정해서는 안되는 파일이 존재한다.public/index.html: 페이지 템플릿src/index.js: 자바스크립트 시작 점조심하자!💡그리고 우리가 새로 js, jsx, css 등 직접 생성할 파일들은 src 폴더에서 하면 된다. Webpack이 src/ 부분에만 작동하기 때문이라고 한다.[ package.json ]해당 프로젝트에 대한 정보들이 들어있다. 프로젝트 이름, 버전, 필요한 라이브러리와 라이브러리들의 버전이 명시되어 잇다.[ 싱글 페이지 애플리케이션(single-page application, SPA) ]싱글 페이지 애플리케이션(single-page application, SPA)은 서버로부터 완전한 새로운 페이지를 불러오지 않고 현재의 페이지를 동적으로 다시 작성함으로써 사용자와 소통하는 웹 애플리케이션이나 웹사이트를 말한다.위키백과React.js는 SPA이다. 즉, 어떠한 데이터에 관한 교체 이벤트가 발생했을 때, 서버로부터 페이지를 새롭게(html 파) 받아와 구성하는 것이 아니라 content를 바꿔치기 한다. 이는 HTML 5의 History API를사용해서 가능하게 만든다.[ History API ]전통적인 웹 사이트는 a page에서 b page로 이동할 때 a.html을 보여주다가 b.html을 보여주면 되었지만 SPA의 경우 오직 1개의 HTML(index.html)이 존재한다. 따라서 페이징 전환을 하기 위해서 HTML 5 History API를 이용한다.History.back(): 세션 기록의 바로 뒤 페이지로 이동하는 비동기 메서드History.forward(): 세션 기록의 바로 앞 페이지로 이동하는 비동기 메서드History.go(): 특정한 세션 기록으로 이동하게 해 주는 비동기 메서드History.pushState(): 주어진 데이터를 세션 기록 스택에 넣어준다.History.replaceState(): 최근 세션 기록 스택의 내용을 주어진 데이터로 교체한다.생성했던 React 프로젝트에서 public/index.js를 살펴보면 <div id="rood"></div>가 있다.그리고 src/index.js 코드에는 document.getElementById('root')라는 코드가 있다.자바스크립트 파일의 시작 점인 src/index.js에서 id값이 rood인 요소를 찾아 그곳에 해당 요소들을 렌더링하는 것이다. 즉, div라는 최상위 루트 노드 아래에 직접 정의한 요소를 더해 화면을 꾸며나가는 것이다!![ JSX ]JSX는 Javascript Syntax Extension의 약자로 자바스크립트의 확장 문법이다.리액트에서는 이 JSX를 이용해서 화면에서 UI가 보이는 모습을 나타내준다.JSX 사용이 필수는 아니나 사용하면 가독성이 너무 좋아서 필수 아닌 필수이다. (애초에 리액트 개발자들 대부분이 JSX를 사용한다고 한다.)JSX는 createElement를 쉽게 사용하기 위해서 사용한다.모든 UI를 만들때 마다 createElement를 사용해서 컴포넌트를 만들 수 없다.Ract는 React.crateElemnt API를 사용해서 엘리먼트를 생성한 후에 이 엘리먼트를 In-Memory에 저장한다. 그리고 RaectDOM.render 함수를 통해 웹 브라우저에 그린다.JSX를 사용하면 Babel이 사용한 문법을 crateElemnt로 자동 변환해준다. 따라서 그냥 개발자는 자유롭게 JSX 사용하면 된다.단, JSX는 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸줘야 한다.// 안된다. // 자식 요소가 여러 개 라면 부모 요소로 감싸줘라. function hello() { return ( <div>Hello, Raect!</div> <div>Hello, Wrold!</div> ); } // 이렇게 말이다. function hello() { return <div> <div>Hello, Raect!</div> <div>Hello, Wrold!</div> </div>; }💡 만약 JSX에서 JS 코드를 사용하고 싶다면 { } 내부에 작성해주면 된다.[ React와 Key ]map()을 사용한다면 언제나 명심해야 하는 것. KEY. 이것을 넣지 않는다면 에러가 발생한다.React에서 요소의 리스트를 나열할 때는 Key를 넣어줘야 한다. Key는 React가 변경, 추가 또는 제거된 항목을 식별하는 데 도움이 된다.추가적으로, 이 Key에 지정하는 값은 순회하고자 하는 목록의 아이템에 대한 ID 값이면 된다. 즉, 고유한 값이여야 한다. 정 없으면 index 넣어도 되지만 index 값은 권장하지 않는다.리액트는 가상 돔을 이용해서 바뀐 부분만 실제 돔에 적용한다. 그렇다면 리스트를 나열할 때 바뀐 부분만 어떻게 찾을까? 바로 이 key를 이용해서 어떠한 부분이 바뀌었는 인식하는 것이다.[ state ]정말 정말 중요한 개념!!!리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서 React State를 사용한다. State란 무엇일까?간단히 말해서 변수이다.단, 이 변수의 값이 변경되면 컴포넌트들이 재렌더링 된다.state에는 리액트의 흐름에 관한 데이터와 관련이 있다. Section 3. To-Do 앱 최적화 하기[ React HOOK ]엄청나게 중요하다. 이 HOOK은 클래스형 컴포넌트처럼 함수형 컴포넌트에서도 state와 생명주기 메서드를 사용할 수 있도록 해주는 메서드이다.클래스 형 컴포넌트에서는 Mounting, Updating, Unmounting 3단계 따라서 생명주기 메서드를 제공한다.Mounting: componentDidMount()Updating: componentDidUpdateUnmounting: componentWillUnmount()함수형 컴포넌트에서는 이를 위해 HOOK을 사용한다.[ HOC(Higher Order Component) ]화면에서 재사용 가능한 로직만을 분리해서 component로 만들고, 재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법이다.HOC는 HOOK이 나오기 전에 사용했던 부분이다.Wrapper가 많아지면 흐름 파악이 어려워서 이제 잘 안 쓴다.HOC를 만들고 싶으면 Custom HOOK을 사용하자.[ HOOK ]기본적으로 알고 있어야 할 HOOK은 다음과 같다.useState()리액트의 유동적인 데이터들은 state에 담아 사용하기 위해 이용하는 HOOK클래스형 컴포넌트의 setState와 같이 state 객체에 대한 업데이트 실행단!!! state 변경 시 재 렌더링이 일어남useEffect()사이드 이팩트 처리 HOOK클래스형 컴포넌트의 생명 주기 함수 역할 수행useMemo()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 지정한 함수를 실행하여 해당 반환 값을 반환useCallback()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 함수를 반환useRef()요소의 참조를 위해 사용하는 HOOK[ Props ]Props는 Properties의 줄임말상위 컴포넌트에서 하위 컴포넌트로 데이터를 전송하고 싶을 경우 사용읽기 전용으로 자녀 컴포넌트에서 강제로 이 값을 변경할 수 없다.전달 받은 props가 state고 이 값을 바꾸고 싶다면 props로 set함수를 넘기고 이것을 이[ TailWindCSS ]HTML 안에서 CSS 스타일을 할 수 있게 해주는 CSS 프레임워크빠른 스타일 작업 가능id 혹은 class 명을 작성하기 위해 머리를 혹사 시키지 않아도 된다.class에 특정 키워드를 넣어서 CSS 조작정해진 속성 키워드가 워낙 많으니 공식 홈페이지 검색 필수다[ 리액트 불변성 ]불변성을 지키며 개발을 하자!참조 타입에서 객체나 배열의 값이 변할 때 원본 데이터가 변경되면 예상치 못한 오류가 발생할 수 있다.불변성을 지킬 수 있는 참조 관련 메서드:spread operator, map, filter, slice, reduce불변성을 해치는 참조 관련 메서드:splice, push[ React.memo ]React.memo는 Higher-Order Components(HOC)이다. 불필요한 컴포넌트 렌더링을 방지할 수 있게해준다. (일종의 최적화 용 HOC) Section 4-5. Netflix 앱 만들기주로 실습 내용 이었다. 정리할 이론만 추려내 보겠다.[ Styled Component ]자바스크립트 파일 안에서 CSS를 처리할 수 있게 해주는 라이브러리[ React Router Dom ]React Router DOM을 이용하면 웹/앱에서 동적 라우팅을 구현할 수 있다. 라우팅이 실행 중인 앱 외부의 구성에서 처리되는 기존 라우팅 아키텍처와 달리 React Router DOM은 앱 및 플랫폼의 요구 사항에 따라 컴포넌트 기반 라우팅을 용이하게 한다.React Router DOM을 사용하기 위해서는 몇 가지 설정을 해야한다.index.js에서 BrowerRouter로 루트 컴폰너트를 감싸준다.BrowserRouter은 HTML 5 History API를 사용하여 UI를 URL과 동기화 된 상태로 유지해준다.import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter > <App /> </BrowserRouter> </React.StrictMode> ); 여러 컴포넌트 생성 및 라우트를 정의한다.Routes와 Route를 사용한다.Routes: 앱에서 생성될 모든 개별 경로에 대한 컨테이너 상위 역할을 한다.Route: 단일 경로를 만드는 데 사용된다.path 속성: 원하는 컴포넌트의 URL 경로를 지정한다.element 속성: 경로에 맞게 렌더링 되어야 하는 컴포넌트를 지정한다.import { Routes, Route } from "react-router-dom"; function App() { return ( <div className="app"> <Routes> <Route path="/" element={<Home />}> <Route path="about" element={<About />} /> <Route path="contact" element={<Contact />} /> </Route> </Routes> </div> ); } +) <Link />를 통해 경로 이동하기Link 구성 요소는 HTML의 a 태그와 유사하다.to 속성은 링크가 유저를 데려가는 경로를 지정한다.앱 구성 요소에 나열된 경로 이름을 생성했기 때문에 링크를 클릭하면 경로를 살펴보고 해당 경로 이름으로 구성 요소를 렌더링한다.import { Link } from "react-router-dom"; function Home() { return ( <div> <h1>홈페이지</h1> <Link to="about">About 페이지를 보여주기</Link> <Link to="contact">Contact 페이지를 보여주기</Link> </div> ); } [ 중첩 라우팅 ]라우팅은 중첩 처리가 가능하다.[ Outlet ]자식 경로 요소를 렌더링하려면 부모 경로 요소에서 Outlet를 사용해야한다.하위 경로가 렌더링될 때 중첩된 UI가 표시될 수 있다.부모 라우트가 정확히 일치하면 자식 인덱스 라우트를 덴더링하거나 인덱스 라우트가 없으면 아무것도 렌더링하지 않는다.[ useNavigate ]경로를 바꿔준다.naviate(”/home”) ⇒ localhost:3000[ useParams ]:style 문법을 path 경로에 사용했다면 useParams()로 읽을 수 있다.function test() { return ( <Routes> <Route path="invoices/:invoiceId" element={<Invoice />} /> </Routes> ); } function Invoice() { let params = useParams(); return <h1>Invoice {params.invoiceId}</h1>; } [ useLocation ]현재 위치의 객체를 반환현재 위치가 변경될 때마다 일부 side effect를 수행하려는 경우 유용하다.[ useRoutes ]<Routes>와 기능적으로 동일하나 <Route> 요소 대신 자바스크립트 객체를 사용하여 경로를 정의한다.일반 <Route> 요소와 동일한 속성을 갖지만 JSX가 필요하지 않는다.[ Custom HOOK ]개발자가 정의하는 HOOK이다.HOOK의 이름은 use로 시작해야 한다.참고로 HOOK은 함수형 컴포넌트 또는 커스텀 HOOK에서만 호출이 가능하다.따라서 커스텀 HOOK도, 함수용 컴포넌트 또는 HOOK 내부에서 호출되어야 한다.강의에서는 useDebounce과 useOnClickOutside HOOK을 만들었다.useDebounce: input 요소에서 데이터 입력이 발생하면 설정한 set함수 때문에 매번 state 값이 바뀌고 재 렌더링이 일어난다. 따라서 keyup 이벤트의 처리를 지연시키는 커스텀 HOOK이다. (코드는 강의를 참고하자!)useOnClickOutside HOOK: 모달 창 밖의 부분을 클릭하면 해당 모달 창이 꺼지는 기능을 수행하는 HOOK이다. (코드는 강의를 참고하자!)이런 식으로 HOOK을 만들고 활용하는구나 싶었다…미션과제 총 합본 https://www.inflearn.com/blogs/7021 JS 미션 03. 퀴즈 앱[ 구현 해야하는 기능 ]1. 퀴즈 문제, 문제에 해당 하는 선택지 (선택지의 갯수가 매번 다름)2. 답 선택 시, 정답 여부에 따라 배경의 색상이 변경되어야 함문제는 data.json을 직접 작성하여 동적 생성했습니다. JS 복습 겸으로 해당 주제로 퀴즈 앱을 간단하게 만들어 봤습니다. 미션을 진행하며 문제는 없었습니다. JS 미션 04. 책 나열 앱[ 구현 해야하는 기능 ]1. 책 이름 입력 란2. 책 저자 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함4. 제출된 데이터는 책 리스트에 출력 됨아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 책 이름, 저자5-2. 각 아이템에는 삭제 기능이 있어야 함 구현하는데 문제가 없었습니다. REACT 01. 예산 계산기[ 구현 해야하는 기능 ]1. 지출 항목 입력 란2. 지출 비용 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 지출 항목, 지출 비용5-2. 각 아이템에는 수정 및 삭제 기능이 있어야 함수정 버튼 클릭 시 수정 모드로 변경전체 삭제 기능이 있어야 함정말 막힘 없이 진행되다 딱 한 군데에서 문제를 맞았습니다. 상황에 맞게 알림을 띄우는 기능이었는데, JS에서는 아무런 문제 없이 해결했던 이 기능을 React에서 구현 하려고 하니 이상한 문제가 발생하더군요. 여러 동작을 해서 메시지가 많이 발생할 경우, 메시지가 예시처럼 모두 생성되는 것이 아니라 같은 자리에서 텍스트만 바뀌어서 출력이 되었습니다. 물론 잘 해결해서 과제를 마쳤습니다.회고워밍업 스터디의 2주 차에 진입하며 자바스크립트 공부를 마치고 새롭게 React 공부를 진행하며 React의 다양한 기술을 접하게 되었습니다. 특히 state, props, hook, 그리고 라우팅 부분은 처음에는 이해하기가 어려웠습니다. 그러나 부족한 이해를 보완하기 위해서 강의 내용을 정리하고, 추가적인 학습 자료를 찾아가며 개념을 확실히 파악하려고 노력했습니다.React 학습을 마치고 시작한 미션도 초반에는 막막함을 느꼈지만 코드를 작성해 나가며 수업 때 배운 내용을 적용해 가며 문제를 해결해 나갔습니다.워밍업 스터디도 이제 끝을 향해 가네요. 마무리되는 날까지 열심히 학습에 참여하고 미션 해결을 위해 도전해 보겠습니다. 

프론트엔드워밍업클럽FE

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 1 발자국

들어가기 앞서...2024년의 첫 해가 밝으며, 지금까지는 단순히 관심만 갖고 있었던 웹 개발에 대한 공부를 시작해보기로 결심했습니다. 먼저 HTML과 CSS의 공부를 마치니 운이 좋게 인프런에서 JS와 ReactJS 스터디를 진행한다는 소식을 듣게 되었습니다. 이런 좋은 기회를 놓치지 않겠다고 생각하고, 워밍업 클럽에 참여하게 되었습니다.발자국OT를 참가한지 엊그제 같은데 시간은 정말 순식간에 지나가는 것 같습니다. 벌써 스터디가 시작된 지 1주차가 되었습니다. 이제 그 동안의 강의 내용을 간단하게 요약하고, 회고를 남겨 보려고 합니다. 이번 주 강의는 따라하며 배우는 자바스크립트 A-Z (섹션 0~8) 부분을 진행하였습니다.요약Section 01. 자바스크립트 기초[ Console 객체 ]자바스크립트의 console 객체는 코드를 작성하고 테스트를 할 때, 사용하기 좋은 함수를 제공해준다. 다음은 강의에서 소개한 주요 Console 객체의 함수들이다.console.log(): console에 메시지를 출력한다. console.table(): console에 배열이나 객체의 데이터를 테이블 형태로 출력한다. console.error(): console에 에러 메시지를 출력한다. console.warn(); console에 경고 메시지를 출력한다. console.time(), console.timeEnd(): 세트로 사용되며, 두 함수 사이의 코드 실행 시간을 측정한다. [ var, let, const과 스코프 ]변수/상수를 선언할 때 let, const 그리고 var 키워들 사용한다. let과 const는 ES6에 새롭게 추가된 키워드이다. var 키워드는 오래된 선언 키워드로 let과 const 사용을 권장하고 있다.let: 변수 키워드, 재선언 X, 재할당O const: 상수 키워드, 재선언 X, 재할당Xvar: 재선언 O, 재할당 O 그리고 사용한 let/const와 var 키워드에 따라 스코프가 다르게 처리된다. 스코프(scope, 유효/참조 범위)란 어떠한 변수를 참조하려고 할 때, 그 변수에 접근 가능한 유효 범위이다.let/const: 모든 코드 블록 { } 내부에서 선언된 변수는 코드 블록 내에서만 유효. var: 함수 내에서 선언된 var 변수는 함수 내에서만 유효하며, 함수 내에서 블록 내·외부에 관계없이 접근 가능. [ 호이스팅 ]코드가 실행되기 전에 변수 및 함수 선언을 로컬 범위(유효 범위)의 맨 위로 끌어 올려지는 경우를 말한다.[ 자바스크립트 타입과 타입 변환 ]자바스크립트의 데이터 타입(자료형)은 다음과 같다.원시 타입: Boolean, String, Number, null, undefined, Symbol고정된 크기로 Call Stack 메모리에 저장실제 데이터가 변수에 할당참조 타입: Object, Array데이터 크기가 정해지지 않고 Call Stack 메모리에 저장데이터의 값이 Heap에 저장되며 메모리의 주소 값이 할당 자바스크립트 변수에 저장된 값은 다른 데이터 유형으로 변환될 수 있다.명시적 데이터 변환(개발자가 직접 함수를 사용해서 변환)자동 데이터 변환(자바스크립트 자체에 의해 자동으로 변환) [ 연산 및 Math ]자바스크립트에서는 기본적인 산술 연산자, 논리 연산자, 비교 연산자를 제공한다.Math를 통해 더 많은 연산을 이용할 수 있다. [ Template Literals]Backtick(`)을 사용하여 문자열을 표현한 것을 템플릿 리터럴이라고 한다. 템플릿 리터럴을 이용하면 다음과 같은 이점이 있다.줄 바꿈이 쉽다.${}을 사용하여 내부에 표현식을 포함할 수 있게 한다. [ Loops ]for: 초기식, 조건식, 증감식을 포함하는 반복문으로 주어진 조건이 참일 경우 블록 안의 코드를 반복 실행for/in: 객체의 열거 간으한 속성들을 반복하는데 사용.while: 주어진 조건이 true일 동안 코드 블록을 계속해서 실행.do/while: 먼저 코드 블록을 실행한 후, 조건을 확인한다. 그러고 나서 조건이 true일 동안 반복 실행한다. Section 02. Window 객체 및 DOM[ Window 객체 ]브라우저에 의해 자동으로 생성된다. (자바스크립트 객체 X, 브라우저에서 제공 O)이 window 객체는 다음과 같은 역할을 수행한다.브라우저에 접근 및 조작 가능자바스크립트 코드의 전역 객체 역할 [ DOM ]문서 객체 모델(Document Object Model, DOM)요소로 이루어진 HTML 파일을 Tree 구조로 표현한 객체 모델최상단에는 document 노드가 위치해 있으며, 이를 통해 DOM 접근 및 조작 가능Critical Render Path (웹 페이지 렌더링 콰정)데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ Paint +) 강의에서 수 많은 Property 및 Method를 소개해 주셨지만 너무 많은 관계로 생략... Section 03. Event[ Event ]만약 인프런에서 로그인 버튼을 누르면 무엇이 일어날까? 당연히 로그인 페이지로 이동할 것이다. 이렇게 웹 페이지에서 발생하는 사용자의 행동에 대응하여 브라우저에서 일어나는 특정 사건을 "이벤트"라고 한다. 자바스크립트에서는 다음과 같은 이벤트가 존재한다.UI 이벤트load, change, resize, scroll, error 키보드 이벤트keydown, keyup, keypress마우스 이벤트click, dblclick, mousedown, mouseout, mouseover, mousemove, mouseup포커스 이벤트focus, blur폼 이벤트input, change, select, reset, submit, cut/copy/paste 이벤트를 등록하기 위해서는 addEventListener()를 사용하면 된다. 또한 이벤트 흐름에는 이벤트 bubbling과 Capturing라는 2가지의 기본 모델이 존재한다.[ Event Bubbling과 Event Capturing ]이벤트 bubbling은 가장 깊게 중첩된 요소에 이벤트가 발생했을 때, 이벤트가 위로 전달 되는 것을 의미한다. 이벤트 bubbling은 target 이벤트에서 시작해서 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 만약 bubbling 중단을 원한다면 event.stopPropagation()을 호출하면 된다.event.stopPropagation()DOM Tree를 통한 이벤트 흐름 중지 가능브라우저 기본 동작은 취소 X 이벤트 Capturing은 bubbling과 다르게 제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것을 말한다.[ Event Delegation ]이벤트 bubbling과 이벤트 Capturing을 통해서 이벤트 위임을 이해할 수 있다. 이 이벤트 위임은 '하위 요소의 이벤트를 상위 요소에 위임하는 것'이다. Section 04. 자바스크립트 중급[ this]Method의 this: 해당 객체를 가리킨다.함수에서 this: window 객체를 가리킨다.constructor의 this: 빈 객체를 가리킨다. [ bind, call, apply]call():함수를 호출하는 함수.첫 번째 인자 값으로 어떠한 것을 전달해 주면 호출되는 함수의 this가 인자 값으로 지정apply(): call()과 유사하나 인수 부분에 배열을 넣어줘야함.bind(): 해당 함수가 지정한 인자 값을 가리키도록 하지만 call(), apply()와 다르게 직접 함수 실행 X [ 삼항 연산자 ]다음과 같은 구문을 갖는다.조건 ? true이면 반환 : false이면 반환 [ Event Loop]자바스크립트는 동기 언어이다. 하지만 가끔 비동기로 작동하는 setTimeout()를 사용하는 예시를 볼 수 있다. 자바스크립트는 비동기 코드를 작성하기 위해서 자바스크립트 이외의 도움을 받는다.[ Closure ]다른 함수 내부에 정의된 함수가 있는 경우, 외부 함수가 실행을 완료하고 해당 변수가 해당 함수의 외부에서 더 이상 엑세스할 수 없는 경우에도, 해당 내부 함수는 외부 함수의 변수 및 액세스가 가능하다. 이 기능을 Closure라고 부른다.[ 구조 분해 할당 ]배열이나 객체의 속성을 해제하여 그 값을 개별 변수에 담을 수 있게 해주는 표현 식이다.[ Map, Filter, Reduce ]Map, Filter, Reduce은 배열 메서드의 대표적인 예시이다.map(): 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출하고 나온 결과를 모아 새로운 배열로 만들어 반환한다.filter(): 주어진 함수의 필터를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.reduce(): 배열의 각 요소에 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결괏값을 반환한다.[ 얕은 비교 VS 깊은 비교 ]숫자, 문자열 등 원시 자료형은 값을 비교하게 된다. 하지만 배열, 객체 등의 참조 자료형은 참조되는 위치를 비교하게 된다. 얕은 비교를 하게 되면 원시 값의 경우 문제가 없지만 참조 값의 경우 실제 값이 아닌 저장된 위치(참조 값)이 비교되기 때문에 문제가 된다.깊은 비교를 사용하게 되면 참조 자료형도 실제 값으로 비교할 수 있게 된댜ㅏ.객체 depth가 깊지 않은 경우: JSON.stringify() 사용객체 depth가 깊은 경우: lodash 라이브러리의 isEqual() 사용[ 얕은 복사 VS 깊은 복사 ]위에서 정리한 내용처럼 복사에도 문제가 발생하게 된다. 따라서 참조 자료형의 값의 경우 깊은 복사를 사용하면 된다.JSON.stringify()lodash 라이브러리의 deepCopy[ 함수 표현식, 함수 선언문 ]함수 선언문: 함수 선언은 함수를 만들고 이름을 지정하는 것이다.일반적인 함수 선언 방식으로 function 키워드와 식별자를 표기하여 사용한다.함수 표현식은 함수를 만들고; 변수에 할당하는 것이다.익명 함수(function 키워드는 사용했으나 식별자 X), 화살표 함수 사용 Section 05. OOP[ OOP ]OOP(Object-Oriented Programming, 객체 지향 프로그래밍)란 Java 및 C를 비롯한 많은 프로그래밍 언어의 기본이 되는 프로그래밍 패러다임이다. 완전 간단하게 말하자면 객체 지향 프로그래밍은 객체들의 모임이라고 할 수 있다.OOP 특징으로는 다음과 같다.추상화:불필요한 정보는 숨기고 중요한 정보 만을 표현함으로써 프로그램을 간단히 만드는 것.상속:새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있도록 해주는 것.기존 클래스: 부모 클래스, 상위 클래스새로운 클래스: 자식 클래스, 하위 클래스다형성: 하나의 틀을 가지고 여러 개의 다양한 형태를 만드는 것이다.overriding을 통하여 다형성 구현 일반적인 코드를 재사용하고 작성할 수 있다.캡슐화:클래스 안에 있는 Method, 변수 등을 하나로 묶어준다. [ class와 constructor ]class에서는 constructor라는 특별한 메서드를 제공한다. 이 constructor는 생성자로, 인스턴스화된 객체에서 다른 메서드를 호출하기 전에 수행해야 하는 사용자 지정 초기화를 할 수 있게 해준다.클래스를 new 키워드를 붙여 인스턴스 객체로 생성하면 넘겨 받은 인자 값과 함께 constructor가 가장 먼저 실행이 된다. 따라서 이 곳에 초기화를 해야 하는 작업을 수행한다.[ Super]자바스크립트에서 super는 다음과 같은 역할을 수행한다.자식 클래스 내에서 부모 클래스의 생성자를 호출할 때 사용한다.자식 클래스 내에서 부모 클래스의 메소드를 호출할 때 사용한다. Section 06. 비동기[ 동기와 비동기 ]동기(Synchronous)코드를 순차적으로 실행하는 것. 즉, 한 작업이 끝나기를 기다렸다가 끝나면 다음 작업을 수행한다.각 작업이 완료될 때까지 다음 작업이 실행되지 않는다.비동기(Asynchronous)작업이 종료되지 않아도 다음 작업을 진행할 수 있는 방식비동기적인 코드는 특정 작업을 기다리지 않고 다음 작업을 계속 수행한다. [ Callbacks, ES6 Promise, ES7 Async / Await ]callbacks콜백 함수는 특정 함수에 매개변수로 전달된 함수를 의미한다.콜백 함수는 함수를 전달 받은 함수 내부에서 호출된다.단, 콜백 지옥을 맛볼 수 있다.Promise자바스크립트 비동기 처리에 사용되는 객체이다.new 키워드와 생성자를 사용해서 만들며, 생성자의 매개변수로 실행 함수를 전달한다.new Promise(실행함수) 실행 함수의 1번째 매개변수 resolve는 비동기 작업 성공 값이다.실행 함수의 2번째 매개변수 reject는 작업 실패 값이다.Promise는 다음 중 하나의 대기 상태를 갖는다.대기, 이행, 거부단, 체인 지옥이 시작된다...Async / Await비동기 코드를 마치 동기 코드처럼 작성할 수 있도록 해준다.Promise에서 than 체인 형식으로 호출하는 것보다 가독성이 좋다.await는 async 함수에서만 사용 가능하다.동기식 코드에서 사용하는 try...catch 문을 사용할 수 있다. Section 07. Symbol, Iterator, Generator[ Symbol ]ES6에 새롭게 추가된 원시 타입으로, 유니크한 식별자를 만들기 위해서 사용.단, for...in과 getOwnPropertyNames에서 제외 된다.Symbol 사용 시 기본적으로 Property가 숨겨진다. (찾을 수 있는 방법 有)따라서 for...in과 getOwnPropertyNames에서 symbol로 만든 Property가 안보인다.[ Iterator, Generator ]Iterator대표적인 예시로 배열이 있다.반복 가능한 것을 Iterable하다고 한다. for…of를 이용할 수 있다.[Symbol.iterator()] 값을 가지고 있다.Generator사용자의 요구에 따라 일시적으로 정지할 수 있고, 다시 시작할 수 있는 특별한 기능을 가지고 있다.function다음에 Asterisk (애스터리스크)를 붙인 형태로 사용한다.function*yield 키워드를 이용한다: 제너레이터 함수의 실행을 일시적으로 정지시킴. Section 08. Design Pattern[ 디자인 패턴 ]디자인 패턴은 개발자가 응용 프로그래밍나 시스템을 디자인할 때 일반적인 문제를 히결하는 데 사용할 수 있는 공식화된 모범 사례이다.- 위키 피디아다음과 같은 장점이 있다.최고의 솔루션재사용성풍부한 표현력향상된 의사 소통필요없는 코드 리팩토링코드베이스 크기 감소[ 디자인 패턴 종류 ]Singleton Pattern: 클래스의 인스턴스화를 객체 1개로 제한하는 디자인 패턴Factory Pattern: 비슷한 객체를 반복적으로 쉽게 생성하게 해주는 디자인 패턴Mediator Pattern(중재자 패턴): 객체 그룹에 대한 중앙 권한을 제공해주는 디자인 패턴Observer Pattern: event-driven 시스템을 이용하는 디자인 패턴Module Pattern: 코드를 더 작고 재사용 가능한 조각으로 분할하게 해주는 디자인 패턴 미션완벽히 해결한 미션은 다음과 같습니다.음식 메뉴 앱음식 메뉴 앱 미션은 주어진 카테고리에 해당되는 메뉴를 출력하는 웹을 구현하는 것이었습니다. 저는 카페 메뉴를 주제로 해당 웹을 구현했습니다. 다만 출력할 아이템에 대한 DB가 없어서 직접 data.json을 작성하여 처리했습니다. 미션을 해결하면서 기능 구현에는 특별한 문제가 없었으나 기능 구현보다 데이터 파일 생성이 더 오래 걸린 미션이었습니다... (출력되는 메뉴 이미지는 스타벅스 이미지를 활용했습니다.) 가위 바위 보 앱플레이어와 컴퓨터가 가위 바위 보를 하는 게임을 구현하는 미션입니다. 총 10번의 기회가 주어지며 게임에 대한 스코어 제공 및 승패 결과를 제공해야 했습니다. UI를 어떻게 구현할까 고민하다가 이미지를 추가적으로 더 넣어 구성했습니다. 컴퓨터의 가위 바위 보 선택지는 Math.random()을 이용해 처리했으며, 기능 구현에는 특별한 문제는 없었습니다.회고자바스크립트 강의를 들으며 기초를 다지고 그 지식을 바탕으로 주어진 미션을 해결하는 한 주를 보냈습니다. 특히 웹 개발이 처음이라서 미션을 해결해 나가는 시간이 정말 흥미로웠습니다. 앞으로 워밍업 클럽 Study를 진행하며 제가 얼만큼 발전할 수 있는지 궁금해지기도 합니다. 남은 기간 최선을 다해서 임해보겠습니다!

프론트엔드워밍업클럽

BoBae Kim

[인프런 워밍업 클럽 1기] 1주차 발자국 👣

강의 요약 📝섹션1. 피그마 배리어블과 디자인 토큰피그마 배리어블과 디자인 토큰의 개념을 이해하고 필요성에 대해 배우는 시간이었다. 디자인 토큰 개념은 이해하고있었는데 디자인 토큰의 특징 중에 참조 기능이 있다는 것은 처음 알았다.  섹션2. 배리어블과 파운데이션 세팅하기색상 배리어블 구조를 이해하고 이름 규칙을 정해서 색상 배리어블을 직접 설정해보았다. 또 타이포그래피, 아이콘, 그림자, 그리드 기준점까지 디자인할 때 기본이 되는 부분들을 하나씩 차근차근 만들었다. 실무 프로젝트에서도 매번 시안 만들기에 바빠서 스타일 가이드를 제대로 작업하지않은 경우도 있었는데 이번 강의를 들으면서 아무리 바쁘더라도 기본을 잘 다져둬야 추후에 디자인의 일관성을 유지하면서 확장성있게 사용할 수 있다는 점을 확실하게 배웠다.  - 스타일 가이드 제작할 때 유용한 플러그인Apply variables : 적용하지않았거나 누락된 스타일의 베리어블을 찾아서 바꿔줌Typescales : 타이포그래피 스타일을 사이즈별로 생성해줌Styler : 설정한 스타일을 local style에 자동으로 등록해줌 Batch styler : 스타일을 수정하고 싶은 컴포넌트를 선택해서 변경 가능함Typorahy style guide : 타이포그래피 스타일 가이드 문서를 제작해줌 Frame all : 컴포넌트 각각의 프레임을 만들어줌- 유용한 단축키 정리control+shift+enter : 베리어블 추가control+ r : 선택된 레이어 이름 수정부모의 컴포넌트를 클릭하고 enter를 누르면 자식 컴포넌트만 선택됨  회고 ✨😆 Liked (좋았던 점) : 강의를 듣고 직접 만들어보면서 배리어블 개념, 용어, 피그마 단축키 등을 한번 더 정리해 볼 수 있는 시간을 가질 수 있어서 좋았다. 그리고 이번주에 진행되었던 특강 내용도 너무 좋았다!! 😅 Lacked (아쉬웠던 점, 부족한 점) : 스터디 첫 주였는데 계획했던것처럼 매일매일 강의를 듣지못했다.. 🧐 Learned (배운 점) : 이번주는 배리어블을 활용해서 스타일 가이드를 만드는 방법을 배웠다! 그동안 배리어블 개념에 대해서 대략적으로만 알고있어서 실무에서 활용하는게 쉽지않았는데 배리어블을 참조해서 새로운 배리어블을 만들고 활용하는 방법과 이름 정하는 규칙에 대한 구체적인 예시를 알려주셔서 실무에서 유용하게 적용해볼 수 있을 것 같다! 🤩 Longed for (앞으로 바라는 것) : 다음주 부터는 조금씩이라도 매일 공부하고 계획한대로 미션을 수행할 수 있도록 노력해보자!  

UX/UI워밍업클럽디자인

꾸이

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

직장과 사이드 프로젝트를 병행하던 중 디자인 시스템에 대한 심화적인 공부의 필요성을 느꼈다. 사수 없는 디자이너라 스스로 배우고 성장해야만 했는데, 해외 아티클, 유튜브 등을 열심히 찾아봤지만 "어디서부터 어디까지 실무에서 적용시켜야 할지 모르겠다"는 문제 때문에 어려움을 겪었다. 그러던중 인프런 워밍업 클럽 - 스터디 1기의 존재를 알게됐고, 좋은 기회로 보여 신청했다. 📖 강의 요약0. OT첫 프로그램은 OT였다. 줌으로 화상회의를 진행하는 동시에 피그잼에서 강사님과 의사소통했다. 덕분에 집중이 잘됐다. 스터디는 다같이 으쌰으쌰하는 분위기가 중요한데, 참여자 모두가 쉽게 사용할 수 있고 귀여운 의사소통이 가능한 툴이라 그랬던 것 같다.평일 저녁에 짬을 내서 참여할 가치가 있었다. 기존에 존재하는 강의를 바탕으로 스터디로 진행하다 보니 안내사항이 많았는데, OT에서 설명을 잘해주셔서 따라가면서 잘 이해할 수 있었다. 특히 피그잼에서 "내가 왜 이 스터디에 참여했는지" "무엇을 얻고 싶은지" 등을 스스로 생각하고 써나가는 시간이 있었는데 이 시간이 정말 좋았다. 다른 사람들이 어떤 각오로 참여하게 됐는지를 보면서 동감하고 신기해하기도 하면서 "다같이 30일동안 열심히 공부할 사람들이 여기 있구나!"라는걸 새삼 느끼며 설레는 마음으로 스터디를 시작했다. 1. 디자인 시스템과 디자인 토큰강의는 베리어블이 먼저지만, 정리 과정에서 순서를 수정했습니다초반 강의에서는 디자인 시스템과 디자인 토큰 등 강의에서 다루는 개념들을 먼저 정리하는 시간을 가졌다. 아는 내용과 모르는 내용이 섞여있었는데, 전자는 내가 이미 아는 개념들을 강사님 입장에서 설명해주시는 것을 들으면서 "아, 저렇게 설명할 수도 있는 부분이구나!"고 생각하며 복습했고, 모르는 부분은 아는 부분보다 열심히 메모하고, 따로 표시해두었다. 1) 디자인 시스템디자인 시스템은 일관성과 확장성을 가진 재사용 가능한 컴포넌트와 패턴, 가이드를 말한다.디자인 시스템의 구성 요소는 다음과 같다.디자인 원칙/철학 Design Principle스타일 가이드 Style Guide컴포넌트 라이브러리 Component Library패턴 라이브러리 Pattern Library문서화 Documentation시스템 관리 운영 System Governance이 중에서 내가 주로 사용했던 것은 스타일 가이드, 컴포넌트 라이브러리뿐이었어서 다른 부분들을 어떻게 실무에 적용할 수 있을지 고민했다. 디자인 시스템의 장점은 다음과 같다.디자인 일관성 유지브랜드 강화효율적인 개발시간 단축팀 간 협업 강화빠른 온보딩유지 보수 용이높은 품질의 경험 디자인시스템을 시작할 때는 다음 사항들을 주의해야 한다.비즈니스, 디자인, 개발의 이해에서부터 시작디자이너 혼자서 만드는 게 아니라 회사의 여러 구성원이 함께 만드는 것작은 단계에서부터 성공해나가야 함디자인시스템은 보통 '효율'을 위해 만드는 시스템이지만 제대로 만들려면 시간과 비용이 많이 든다. 따라서 초반에 어디까지 만들지 제대로 설정하는 게 중요하다. 그리고 사이드프로젝트를 할 때도 느꼈지만 만들다보면 또 수정할 일이 생기고, 여기서 막히고 저기서 충돌하기 때문에.. 작은 성취들을 소중히 여기는 태도가 꼭 필요하다. 2) 디자인 토큰디자인 토큰은 모든 UI 요소의 기본 구성 요소로 작고 반복할 수 있는 디자인 결정이다. 브래드 프로스트의 아토믹 디자인 개념에서는 '전자'단계에 속한다.전자 -> 원자 -> 분자 -> 유기체 -> 템플릿 -> 페이지 토큰과 관련된 브래드 프로스트의 새로운 아티클도 첨부한다. 다음에 시간될 때 차근차근 읽어보면 개념 이해에 더 도움이 될 듯 하다. 그렇다면 디자인 토큰은 왜 필요할까? 바로 확장이 쉽고 관리가 유연하다는 이유 때문이다.❓ 여기서 "json으로 내보내기 가능해서 여러가지 플랫폼으로 이동 가능하다"고 강사님이 말하셨는데 이유가 궁금해서 찾아봤다.json은 JavaScript Object Notation의 약어로, 데이터를 표현하는 데 사용되는 형식이다. 현재 데이터 교환의 범용 표준이며 프론트엔드와 서비스 측 개발, 시스템, 미들웨어, 데이터베이스를 포함해 프로그래밍의 모든 영역에 사용된다. (출처: 거의 모든 SW 개발의 필수⋯JSON 데이터 포맷의 이해 - ITWorld Korea)디자인 토큰 형식 모듈/4.파일 형식에 따르면 json이 채택된 이유는 다음과 같다.1. 많은 프로그래밍 언어의 표준 라이브러리에서 광범위하게 지원된다. 이것은 개발자의 진입 장벽을 낮출 것으로 예상된다. 2. 현재 인기있으며 광범위하게 사용되는 언어다. 많은 사람들이 익숙하기 때문에 학습 곡선을 낮출 것으로 예상된다.3. 이진법이 아닌 텍스트 기반이어서 기본 텍스트 편집기 이외 특수 소프트웨어 없이 디자인 토큰 파일을 편집할 수 있다. 3) 베리어블의 이름과 구조혼자 공부할 때 가장 어려웠던 부분인데 설명을 너무 잘해주셔서 열심히 들었다. 모든 스터디가 끝난 뒤 가장 먼저 복습하게 될 챕터가 아닐까 싶다. 베리어블의 구조는 다음과 같다.이름(Name), 값(Value), 유형(Type)설명(Description)그룹 베리어블의 계층은 다음과 같다. 기업마다 정의하는 용어가 다를 수 있지만 신경쓰지 말고, 계층마다 기업들이 어떤 목적을 가지고 역할을 분류했는지에 초점을 맞춰야 한다.Raw value: 본래의 값 #D6840BGlobal/primitive/core/base/foundation/root: 사용 맥락에 상관없이 디자인 언어의 기본 값 Orange-mediumAlias/semantic/applied/purpose: 특정 사용 맥락과 의도를 전달할 때 쓰이는 값 Brand-primaryComponent/overwrites/scoped: 컴포넌트와 관련된 모든 디자인 속성을 가진 값 Button-primary-background-color❓ raw value와 primitive는 뜻이 똑같은데 왜 다른 분류 용어로 사용하는지 궁금했다. 베리어블 이름의 구조는 Namespace + Object + Base + Modifier로 이루어져있다.Namespace>System은 다른 디자인 시스템과 구분하기 위한 접두어로, 주로 모든 베리어블/토큰 앞에 위치한다.Object>Component는 디자인 시스템 내에서 특정 컴포넌트의 스타일 및 레이아웃을 적용하고 싶을 때 사용된다.Base는 Category와 Property로 구성되는데, Category는 UI 기본 구성 요소를 공통된 유형으로 그룹화하며 Property는 각 카테고리 내에서 특성에 따라 세분화된 것들이다.Modifier는 하나의 디자인 요소를 여러 상황, 상태에 따라 변형할 수 있도록 한다. Variant와 State로 구성되는데, Variant는 시각적 위계질서와 기능을 표현한다. State는 인터랙션 상태와 크기를 표현한다. ❓ 토큰 앞에 $(달러) 기호를 붙이는 것도 json 기반이라 그런건지 궁금했다. 찾아본 결과는 다음과 같았다.디자인 토큰 형식 모듈에 따르면, 토큰 이름과의 충돌을 방지하기 위해 토큰 속성은 달러 기호($)로 접두사를 붙인다. 이 접두사를 사용하면 예약어 목록이 필요 없고 사양을 미래에 대비하는 데 도움이 된다.덧붙여 다른 변수명에서 잘 사용하지 않는 기호를 사용하여 다른 변수와의 충돌을 줄이기 위해 $를 사용한다는 내용은 이 블로그에 잘 설명되어 있다. 베리어블 구조, 이름을 지을 때 몇 가지 실무 팁도 알려주셨다.개발자와 디자이너 둘 사이의 공통된 이름 짓기미리 80% 정도는 계획을 하도록 한다 (엑셀 시트, 피그잼 추천)2~3개 정도의 레퍼런스에서부터 시작하기사이드프로젝트에서 파운데이션을 제작하던 중 어떻게 보면 벼락치기 개념으로 들은 강의였어서 조금만 더 빨리 들었다면 같이 엑셀로 계획하고 할 수 있었을텐데! 라고 후회했다 😇... 정말.. 정말 중요한 팁을 주셨다. 디자인시스템 관련한 레퍼런스는 사실 너무♾ 많고, 그중에서도 개발하려는 서비스의 특성/규모 등에 맞춰서 조절해야 하니 욕심부리지 말고 적당한 선에서 참고하며 시작해야 한다 ... 2. 스타일 파운데이션 설정색상 Color사이드프로젝트를 할 때 가장 많이 헤맸던 부분인데, 여러가지 레퍼런스를 참고해서 정리해주신 파일을 기반으로 만들어야 할 베리어블을 정리한 뒤 제작하니 시간도 절약하고 이후 개발자가 이해하기도 좋을 것 같았다. 고려사항은 다음과 같다.Color Scopingsematicbg: FrameIcon: Shapetext: Textborder: Stroke특정 베리어블을 publishing하고 싶지 않다면 베리어블 콜렉션/그룹 앞에 _ 작성개별 베리어블 edit color variable -> Hide from publishing 설정이런게 진짜 꿀팁이지 싶었던 부분. 이외에도 강사님이 제공해주시는 피그마 파일을 통해 컴포넌트 정리할 때의 팁을 알아볼 수 있는데, 공부에 많은 도움이 된다. 간격 Spacing, 둥근 모서리 Border Radius기본 단위(Base unit)은 1.5배수 랜더링 이슈로 주로 8pt 그리드를 사용하며, 일반적으로 더 작은 단위로 레이아웃을 정렬하고 싶은 경우 4pt 그리드를 사용한다. 간격 크기(Spacing Scale)도 마찬가지.간격의 사용(Spacing in UI)은 작은 UI 구성 요소 / 카드 UI 패딩, 간격 / 큰 규모의 UI, 레이아웃 등 간격이 사용되는 케이스에 따라 적용하는 간격의 범위를 말한다.❗ 아틀라시안 디자인 시스템에서는 small, medium, large로 나누어서 적용하고 있었다. (아래 사진)간격 베리어블은 다음과 같이 구성할 수 있다.ComponentSemantic : Padding Gap Border Radius Width/Height Border WidthPrimitive : UnitBase Grid Point : 4❗ 시맨틱을 적용한 사례가 궁금해서 찾아봤다. Polaris는 --p-space-card-padding, --p-space-table-cell-padding 같은 식으로 몇몇 컴포넌트의 Padding과 Width, Height까지 정의한다. 둥근 모서리 베리어블은 다음과 같이 구성할 수 있다.Primitive: UnitSemantic: Border Radius 타이포그래피 Typography타이포그래피는 강의 녹화 당시에 베리어블이 없었어서 스타일로 제작하셨으며(추후 추가 예정이시며, 나는 특강으로 들을 수 있다!), 스타일을 쉽게 제작할 수 있는 플러그인을 많이 알려주셔서 도움이 됐다. 아이콘 IconFeather Icons을 불러와서 등록하는 법을 배웠다. 기존에 있는 아이콘을 불러오는 과정에서 생길 수 있는 문제를 유용한 단축키를 소개하면서 해결해주셨다.fn shift enter : 바깥에 있는 프레임 선택 -> 크기 조절enter : child frame 선택ctrl shift g : frame 해제5월 4일에 진행한 특강에서 심화 수업을 들었는데, 이 부분은 정리가 더 필요해서 다음주 발자국으로 넘긴다. 높이 Elevation❗ Material Design 3에 의하면 높이는 z축에 있는 두 표면 사이의 거리다.높이와 그림자는 UI 요소간의 계층구조를 시각적으로 명확하게 하고, 요소들간의 상대적인 거리와 깊이를 나타내 현실감있는 경험을 제공하며, 상호작용을 시각적 피드백으로 표현해 사용자 경험을 향상시킨다. 높낮이의 표현방법은 3가지가 있다. (이미지 출처: Material Design 3)다른 톤으로 표현하기같은 톤인 경우 그림자 효과 주기스크림*을 사이로 구분하기*스크림: 모달 뒷배경에 주로 사용되는 그것을 말한다. Material Design 2에서는 다음과 같이 설명한다. 스크림은 표면의 콘텐츠를 덜 눈에 띄게 만들기 위해 머티리얼 표면에 적용할 수 있는 임시 처리이다. 이는 스크림을 받는 표면에서 벗어나 화면의 다른 부분으로 사용자의 주의를 유도하는 데 도움이 된다. 그리드 Grid, 기준점 Breakpoints그리드 시스템은 시각적 질서, 일관된 레이아웃, 유연함과 확장성, 디자인 효율성을 제공해준다. 반응형 그리드의 기본 용어는 다음과 같다.칼럼(Columns): 섹션거터(Gutters): 칼럼 간의 간격마진(Margins): 그리드 양상단의 여백 Fixed, Fluid, Hybrid 그리드 정의는 다음과 같다.고정형, 유동적 그리드 : 크기 확대됐을 때 고정/유동하이브리드: 다양한 그리드가 한 스크린 안에 있음 그리드는 개념적으로는 이해가 된 상태였는데 피그마에서 오토레이아웃을 적용할 때 헷갈리는 부분들이 있었다. 그런 점들을 잘 짚고 넘어갈 수 있었다. 테두리 간격 Border Width, 투명도 Opacity배리어블을 만든 후 넘버 스코핑에 신경쓰면 되는 부분들이다.  🎯 미션미션 1, 2, 3이번주의 미션은 다음과 같았다.미션1. 컬러 베리어블을 로컬베리어블에 등록하고 다른 디자이너, 개발자 누구나 볼 수 있도록 문서화한다.미션2. 타이포 그래피 스타일, 간격 베리어블을 등록하고 Feather icon을 등록한 후 면으로 모두 바꾼다.미션3. 그림자 효과, 반응형 기준점, 기타 베리어블 등록하기미션4. 스타일 파운데이션 최종적으로 다듬어서 일관되게 문서화해보기그중 미션 1, 2, 3은 시간이 조금 걸리긴 했지만 강의를 따라가면 충분히 해결할 수 있는 과제들이었다. 미션 4미션4는 현재 사이드프로젝트나 회사 업무에 적용한다고 생각했을 때, 어떻게 해야 개발자들이 잘 이해할 수 있을까? 불필요한 커뮤니케이션을 줄일 수 있도록 문서화하고 싶다! 는 생각을 가지고 작업했다. 작업과정은 다음과 같다.참고할 디자인 시스템 정하기: 볼드님의 파운데이션, Wanted Design Library, Polaris Styles 를 참고했다.베리어블 -> 문서화 플러그인 찾기 잘 만들어진 플러그인들이 많았지만 1. 컴포넌트 형식이고 2. 컴포넌트 내부 요소들이 잘 구성되어 있고 3. 오류가 없거나 적은 것을 찾기가 힘들었다.플러그인을 찾은 것들은 컴포넌트를 정리해서 묶었다.플러그인을 찾지 못한 것들은 타 디자인시스템들을 참조해서 새로 제작하거나, 기존에 강의를 따라가면서 제작했던 문서를 가지고와서 정리했다.이후 문서를 통일하고 정리했다. 이 과정에서 볼드님의 파운데이션이 큰 도움이 됐다. 🌼 회고잘 한 점: 직장과 사이드 프로젝트를 병행하면서 1주차를 무사히 끝냈다!아쉬운 점: 미션에 집중하다보니 발자국 작성에 시간을 많이 쓰지 못한 점이 아쉽다.보완할 점실전에서 어떻게 활용할 수 있을지 생각하며 강의 듣기매일매일 강의 들은 뒤 강의 메모 이외 간단한 느낀점 꾸준히 작성하여 이후 발자국 모으기 쉽게 만들기다음주 계획: 이번주만큼만 하기! 💨

UX/UI워밍업클럽피그마

김혅

[인프런 워밍업 스터디 1기 디자인] 1주차 발자국 🐾

OT부터 1주 차 스터디, 그리고 첫 온라인 중간 점검까지 마치고 남기는 첫 발자국!역시 나는 강제성(?)같은 동기가 부여되어야 하는 사람임을 다시 느꼈다. 🙄>짜여진 커리큘럼과 그에 맞는 미션이 설계되어 있어서 따라가기 너무 좋았고,강사님께서 노션과 강의 요약본까지 정리해두셔서 더 편리하게 할 수 있었다. 쵝오...👍강의는 무작정 "자, 일단 따라 해봅시다!"가 아닌 기초 개념부터 쌓아 올려가는 방식이라 너무 좋았고, 설명에 맞는시각적 예시까지 곁들여주셔서 따라가기 너무 좋았다. 유용한 사이트와 플러그인 정보도 유익한 건 덤~(WOW)~아직 아날로그 인간이라 강의를 손으로 필기하는데, 그중 몇 개를 아래에 간단하게 적어 회고를 해보고자 한다!Chapter 1.피그마 배리어블과 디자인 토큰디자인 시스템을 만들어야 하는 이유 ✧ 커뮤니케이션(공감대 형성)스타일, 배리어블? ✧ 기본 디자인 토근 관리를 위해서는 배리어블 ✧ 다수의 디자인 요소의 결합은 스타일 Chapter 2.배리어블과 파운데이션 세팅하기✦ 색상 베리어블 세팅 ✧ border의 경우 너무 두꺼우면 텍스트와 잘 부딪히니 색을 빼주어 구분을 해주자.  ✧ icon은 텍스트와 주로 같이 간다.✦ 그리드 ✧ 4-point grid는 작은 단위로 레이아웃 정렬에 용이하다.  ✧ gutter/columns의 개념 헷갈리지 않기. ✧ fluid의 경우 margin 값을 필수로 넣어주어야 한다. ✧ fixed와 fluid의 constraits 각각의 차이 기억하기.✦ 기타 베리어블 ✧ ex)stroke 배리어블 버튼이 안보일때 우 클릭&apply variable or shift+왼쪽 클릭 ✧ opacity의 경우 fill이 아닌 layer에서 적용시키기. 미션✦ 놓치는 부분이 없는지, 적용이 잘 되었는지 더블의 더블 체크 해주기.✦ 생각보다 어려워서 난항을 겪었던 미션 4 ▸ 참고한 템플릿은 크게 두 가지 범정부UIUX_디자인스타일가이드n컴포넌트 / Wanted Design Library ▸ 컬러 부분이 상당히 오래 걸렸는데, 맘에 드는 플러그인을 찾기 어려웠고 요소가 많은데 그 안에서도 최대한 구분이 되어 보이기를 바라며 구성하였다. -Theme의 경우 각 변수의 수가 똑같기 때문에 가로 정렬 -Sementic의 경우 각 변수의 차이가 약간 있고 내용이 많아 세로 정렬로 진행해 주었다.마치며, 2주 차 다짐📍아직까지는 따라가기 바쁘다, 복습은 필수.📍커리큘럼대로만 잘 따라가자, 부지런해져라(제발🥺) 

UX/UI워밍업클럽1기피그마

이양구

[인프런 워밍업 클럽 FE 0기] 미션8 - 디즈니 플러스 앱

🎞 Disney Plus APP GitHub 🎞 Disney Plus APP DemoRecord by ScreenToGif  개요인프런 워밍업 클럽 FE 0기의 여덟 번째 미션인 '디즈니 플러스 앱' 입니다. 따라하며 배우는 리액트 섹션 4~5(리액트로 Netflix 앱 만들기) 목표swiper 라이브러리 커스텀해보기react-oauth/google 로 구글 로그인 연동해보기 구현swiper 라이브러리 커스텀해보기// LoginPage import "swiper/css/effect-fade"; <Swiper modules={[Autoplay, EffectFade, Pagination, A11y]} autoplay={auto} effect={"fade"} pagination={{ clickable: true, }} loop={true} fadeEffect={{ crossFade: true }} slidesPerView={1} speed={2000} > {...} </Swiper> // Row.tsx import "swiper/css/mousewheel"; <Swiper modules={[Navigation, Pagination, Scrollbar, A11y, Mousewheel]} navigation pagination={{ clickable: true }} mousewheel speed={1000} spaceBetween={10} > {...} </Swiper> 2024년 3월 10일의 디즈니 플러스 메인 페이지를 그대로 옮겨보고자 swiper 라이브러리를 커스텀해봤다.로그인 페이지에서는 좌우로 넘기는 슬라이드가 아닌 fade-in-out의 슬라이드를 구현하기 위해 swiper에 EffectFade 모듈을 추가하고 fadeEffect 속성을 추가했다.이 fadeEffect가 제대로 작동하기 위해선 반드시 해당 이펙트의 css를 추가해야 한다.다른 모듈이나 컴포넌트를 추가할 때처럼 자동으로 추가되지 않으니 주의해야 한다. (이걸 몰라서 한참을 찾았다. 😥)Row 컴포넌트는 마우스 휠에 따라 움직이는 슬라이드를 만들기 위해 Mousewheel 모듈과 속성을 이용했다.이렇게 슬라이드 속성을 정한 뒤에 swiper가 렌더링하는 요소의 class를 찾아 CSS에서 원하는 디자인으로 변경하면 된다.이때 라이브러리의 CSS와 겹치는 속성이 있을 수 있기 떄문에 '!important'를 붙이는 게 좋다. react-oauth/google 로 구글 로그인 연동해보기// index.js <GoogleOAuthProvider clientId={process.env.REACT_APP_CLIENT_ID}> <BrowserRouter> <App /> </BrowserRouter> </GoogleOAuthProvider> // App.jsx const navigate = useNavigate(); const [isLogin, setIsLogin] = useState( localStorage.getItem("user") ? true : false ); useEffect(() => { isLogin ? navigate("/") : navigate("/login"); }, [isLogin]); <Routes> {isLogin ? ( <Route path="/" element={<Layout setIsLogin={setIsLogin} />}> <Route index element={<MainPage />} /> <Route path=":movieId" element={<DetailPage />} /> <Route path="search" element={<SearchPage />} /> </Route> ) : ( <Route path="login" element={<LoginPage setIsLogin={setIsLogin} />} /> )} </Routes> react-oauth/google는 구글 로그인을 지원하는 라이브러리로, 사전에 구글의 Cloud에서 API 등록을 하고 Client ID를 발급받아야 사용할 수 있다.먼저 프로젝트의 최상위에 GoogleOAuthProvider로 감싸준다.그리고 사용자의 로그인 여부에 따라 페이지를 이동시키기 위해 라우터를 설정한 App 컴포넌트에서 관련 코드를 작성했다.페이지가 렌더링 될 때 로컬 스토리지에 저장된 유저 정보를 받아오고 만약 없다면 로그인 페이지로 보내도록 했다. // loginPage const googleLogin = async (credentialResponse) => { localStorage.setItem( "user", JSON.stringify(jwtDecode(credentialResponse.credential)) ); setIsLogin(true); }; <GoogleLogin onSuccess={(credentialResponse) => googleLogin(credentialResponse)} /> GoogleLogin 컴포넌트는 react-oauth/google 라이브러리에서 지원하는 버튼 컴포넌트로 디자인 및 로그인 관련 함수가 내장되어 있다.onSuccess는 사용자의 로그인이 성공했을 때 실행되는 콜백 함수이며, 인자로 로그인한 유저의 정보를 담은 데이터를 갖는다.여기서 credential이라는 값은 유저의 정보를 담고 있는 토큰으로 암호화되어 있기 때문에 jwt-decode 라이브러리를 이용해 디코딩하여 사용해야 한다.여기서 받은 picture는 사용자의 프로필 이미지 링크를 포함하고 있어서 Nav 컴포넌트에서 사용해 로그인한 유저의 프로필 이미지로 변경했다. 회고'Netflix 앱 만들기'를 하면서 사용했던 기술이 대부분이라 오래 걸리지 않을 것 같았지만...라이브러리 알아보고 문서 읽고 실행해보고... 하는 데 너무 오래 걸린 것 같다.배너 하단의 카테고리 부분은 이전에 같은 과제를 하셨던 분의 깃허브를 참고했다. (https://github.com/kimneighbor/clone-disney-plus-app)로그인 페이지는 따라하기 싫어서 현재 디즈니 플러스 홈페이지를 보고 참고했다.그대로 하면 얼마 안 걸릴 거라 생각했는데 생각보다 라이브러리 커스텀에서 좀 애를 먹었다. 😅with_networks: "2739" 2739는 TMDB에서 디즈니 플러스 방송사(networks) 코드라서 axios의 instance 기본 값에 추가했다.몇몇 요청은 해당 파라미터가 통하지 않거나 오류를 보내기도 해서 완벽하진 않다.디즈니 플러스에서 API를 제공했다면 더 알맞게 페이지를 구현할 수 있었을 텐데 하는 아쉬움이 남는다.한편 영화 정보 API를 제공해주는 TMDB(The Movie Database) 같은 곳이 있어 감사하고 다행이라는 생각이 들었다.프론트엔드 공부하는데 API를 제공해주는 곳이 아예 없었다면 혹은 매번 일정 비용을 지불해야 했다면 얼마나 힘들었을까로그인도 사실 좀 더 좋은 라우팅 구조나 상태 관리 라이브러리를 공부하고 사용해보고 싶었지만...계속 욕심만 커지는 것 같아 최대한 간단하게 구현하려 했다.(사실 과제 밀려서 조바심에 아무것도 못 했다... 😂) 

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

수진

[인프런 워밍업 스터디 1기 디자인] 1주차(스타일 가이드 만들기) 발자국

월요일부터 본격적으로 시작한 인프런 워밍업 스터디!나는 피그마 베리어블을 활용한 디자인 시스템 구축하는 강의를 선택했다! 이 강의를 선택한 이유현재 다니고 있는 회사에는 디자인 시스템이 없다. 없는 상태에서 일을 하다 보니 페이지마다 디자인들이 일관성 없이 만들어진 것을 보고 얼른 디자인 시스템을 도입해야겠다는 생각이 들었다…하지만 나는 디자인 시스템을 처음부터 구축해본 적은 없어서 강의를 알아보던 중에 인프런에서 워밍업 스터디를 한다는 것을 보았다. 때 마침 베리어블을 활용하여 디자인 시스템 구축 방법을 볼드 강사님의 피드백을 받으면서 배울 수 있는 강의가 있어 당장 신청했다! 1주차 강의 후기1주차 강의는 스타일 가이드 만들기이다.월요일은 피그마 베리어블과 디자인 토큰 / 디자인 시스템 개념 이해하기라는 이론 강의였다. 디자인 토큰과 시스템의 개념을 알고 스타일 가이드를 만드니까 더 이해하기 쉬웠다.화요일부터 실습 강의가 들어가는데 동영상만 봤을 때는 음 이 정도면 쉬워서 미션도 금방 끝나겠네! 하면서 목요일부터 두 개씩 해야지! (멈춰 이 좌식아..!) 하고 집에서 쉬었는데 그런 생각은 하지 말았어야 했다..목요일 퇴근 후 직접 피그마를 켜서 따라해보니까 생각보다 오래 걸리고 결국 미션을 하나 밖에 못 했다..😭그래서 미션이 밀려서 금요일부터 토요일 새벽까지 미션3까지 하고 잤다ㅎ.. 😮‍💨근데 여러 인터넷 강의들을 들어봤지만 이번 인프런 워밍업 스터디는 확실히 다른 분들과 같이 공부하다 보니까 학원 다니는 느낌이 들어서 너무 좋았고 무엇보다 볼드 강사님이 내 미션을 보고 코멘트도 해주셔서 너무 좋았다!! 인프런에서 만나기 전에 인스타에 좋은 디자인 정보들을 올려주셔서 팔로우하면서 일 할 때 참고 많이 했었는데 이렇게 실시간으로 피드백을 받으니 너무너무 좋았다!! 2주차 강의 목표2주차 강의 때는 자만하지 말고 매일매일 미션을 해야겠다는 생각이 들었다. 그래서 2주차 강의 목표를 새워본다면매일 미션 완수하기출근하면서 강의듣기일단 이렇게 2개를 목표로 완주까지 달려볼 것이다!!  

UX/UI워밍업클럽디자인시스템볼드피그마워밍업스터디

젬졍

[인프런 워밍업 스터디 1기 디자인] 1주차 발자국🐾

일주일간의 학습에 대한 회고커리큘럼을 따라 매일 아침 강의를 듣고 첫 주를 보냈습니다. 1주 차의 솔직한 후기는 '복습할 시간이 부족해 완벽하게 하지 못하는 내가 밉다.' 였습니다😭. 그럼에도 불구하고 이번 주 강의를 수강하고 모든 미션을 완수할 수 있었던 것은 디스코드에서 열정적으로 지도해 주신 볼드 멘토님과 끝까지 미션을 수행하는 멘티들 덕분이었습니다. 늘어나는 스레드를 보며.. 매일 피그마를 열 수 있었습니다💪💪. 앞으로 더 분발해서 끝까지 완수할 수 있도록 노력하겠습니다!일주일 동안 잘한 것아침마다 디자인 공부한 것: 오전마다 디자인을 공부하는 습관을 기를 수 있어서 좋았습니다. 회사를 가기 전에도, 간 후에도 강의를 들은 나. 매우 칭찬해.포기하지 않은 것: 하마터면.. 1주 차에 하차할뻔 했다..아쉬웠던 점기존의 스타일 가이드라인에 의존하는 것: 이번 수강을 통해 새로운 디자인 시스템을 구축할 수 있도록 하는 것이 제 목표인데, 어렵다고 느끼는 부분은 어느새 멘토님의 가이드라인을 그저 따라 하려 하더라고요. 혼자서 고민해 보고 디자인 시스템을 만들어 나가는 시간을 가져야겠습니다.복습시간이 적었던 점보완하고 싶은 점커뮤니티를 적극적으로 이용하기: 친절왕 멘토님의 활동을 보며, 다음 주부터는 멘토님에게 많이 질문도 하고, 워밍업 스터디를 적극적으로 활용해야겠다는 생각을 했습니다.복습을 저녁으로 미루지 않는 삶 액션 플랜rem에 대해 좀 더 이해하기회사 네이밍 엑셀 시트 구성(잊어먹었다..)가이드라인-컬러 부분 가독성 높이기: 읽기 쉽고 이해가 쉽도록 수정해야겠습니다.다음 주에는실습을 많이 해보는 방향으로 고쳐나가기1주 차 복습 잊지 말기: 컴포넌트가 잘 구성되려면 파운데이션이 잘 갖추어져 있어야 한다!!다음주 업무량이 많은데…잘할 수 있겠죠?😱 힘내라 다음주의 나!

UX/UI워밍업클럽디자인시스템피그마

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 3 발자국

발자국3주 동안 진행된 스터디 클럽이 마무리되었습니다. 이번 스터디에서는 Next와 타입스크립트에 대해서 기초를 다지는 한 주를 보냈습니다. 이제 인프런 워밍업 클럽 스터디의 마지막 발자국을 남깁니다!요약Section 06-07. TDD 기본 및 간단한 앱 생성 및 배포대부분이 실습 위주였기에 코드가 궁금하다면 강의를 보자. 필요한 이론 개념만 요약하겠다.[ TDD(Test Driven Development) 란? ]TDD는 Test Driven Development의 약자로 테스트 주도 개발이라는 의미를 가지고 있다. 강의에서는 다음과 같이 설명한다.“실제 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 것”테스트 코드를 작성한 후 그 테스트 코드를 Pass 할 수 있는 실제 코드를 작성한다.원하고자 하는 기능의 테스트 코드 작성 ⇒ 테스트 실행 FAIL ⇒ 테스트 코드에 맞는 실제 코드 작성 ⇒ 테스트 실행 PASSTDD는 테스트 코드를 작성한 뒤에 실제 코드를 작성한다. 단, 설계 단계에서 프로그래밍의 목적, 테스트 케이스를 작성해야 한다.요구 사항 접수요구 사항 분석 및 설계 ⇒ 목적 및 테스트 케이스 결정테스트 코드 작성FAIL (오류, 수정)이 난 코드를 테스트 케이스에 추가 후 이를 바탕으로 재 설계테스트가 통과 (PASS)된 코드만 개발 단계에서 실제 코드로 작성⇒ 반복적으로 코드의 테스트를 진행함으로서 오류 개발을 낮추고 소스 코드를 깔끔히 관리하는 것. 따라서 다음과 같은 장점이 있다.디버깅 시간 단축재 설계 시간 단축오류 발생 확률 저하추가 구현 용이테스트 기간 단축이렇게 보면 엄청나게 좋아 보이지만 모든 개발자들이 TDD 방식을 사용하지는 않는다. 아래 예시에서 첫 번째가 큰 듯 하다.익숙한 기존 방식을 버리지 못함생산성 저하 [ React Testing Library ] React Testing Library는 사용자가 컴포넌트를 사용하는 것처럼 테스팅하는 React의 테스트 라이브러리이다.React Testing Library는 React 구성 요소 작업을 위한 API를 추가하여 DOM Testing Library 위에 구축된다.DOM Testing Library란 DOM 노드를 테스트하기 위한 매우 가벼운 솔루션이다.Create React App으로 생성된 프로젝트는 React Testing Library를 지원하기 때문에 따로 설치할 필요가 없다.행위 주도 테스트(Behavior Driven Test)이다.EX) 사용자가 어떠한 행위로 이벤트가 발생되었을 때 프로그램이 어떻게 반응하는지~  [ Jest ]Jest는 현: Meta / 전: Facebook에서 만든 테스팅 프레임워크이다. 최소한의 설정으로 동작하며 Test case를 만들어서 어플리케이션 코드가 잘 돌아가는지 확인해준다Jest는 테스트 실행 환경을 제공한다.DOM이 없다(참고로 DOM 없이 React 테스트 X) ⇒ 따라서 React Testing Library와 함께 사Jest를 사용하려면 설치를 해야한다.라이브러리 설치: npm install jest —save-devTest 스크립트 변경: “test” : “jest” OR “jest —watch All”테스트를 작성할 폴더 및 파일 기본 구조 생성 Section 08. Next.js와 TypeScript[ NextJS ]Next.js란 SSR(Server-Side-Rendering)을 쉽게 구현할 수 있게 도와 주는 React 프레임워크이다.일반적으로 리액트는 SPA(Single-Page Application)를 이용해서 CSR(Client-Side-Rendering)을 하기 때문에 좋은 점도 많지만, 검색엔진 최적화(SEO)에 관한 단점이 있다. [ CSR과 SSR ]💡 사전 지식: 검색 엔진에 도움을 주는 것은 HTML의 시맨틱 태그들이다! 1. CSR (Client-Side-Rendering)React에서는 CSR 방식 기본적으로 사용CSR 초기 접속 시 렌더링 동작 방식:클라이언트가 서버에 페이지 내놔 요청서버는 빈 페이지를 클라이언트에게 전달 ⇒ 실제로 개발자 모드로 가면 HTML에 뼈대만 있는 것을 볼 수 있다.클라이언트는 JS 파일을 보고 렌더링 ⇒ 즉, 빈 페이지를 클라이언트에서 처리한다. ⇒ 서버에 대한 의존도가 별로 없다.결론: 검색 엔진에 영향을 주는 HTML이 빈 페이지니까 검색 엔진에 노출될 일이 거의 없다. [ SSR ]Next.js에서 사용하는 방식React에서도 이 방식을 사용할 수 있으나 구현이 어렵기 때문에 React로 굳이?라는 느낌.SSR초기 접속 시 렌더링 동작 방식:클라이언트가 서버에 페이지 내놔 요청서버는 미리 구성된 정적 파일을 클라이언트에게 전달. (정적 파일: HTML, CSS …)클라이언트는 전달 받은 스크립트를 실행하여 화면을 브라우저에 그림결론: 빈 페이지가 아닌 화면을 보여주기 때문에 SEO에 장점이 있다.Next.js 설치 방법 (필자가 npx만 사용해서 npx만 기록)npx create-next-app@latestnpx create-next-app@latest —typescript  [ create-next-app 기본 구조 ]Pages이 폴더 안에 페이지들을 생성만약 about이라는 페이지를 만드려면 pages폴더 안에 about.tsx를 생성해주면 된다.index.tsx가 처음 “/” 페이지로 지정된다._app.tsx는 공통되는 레이아웃을 작성한다.모든 페이지에 공통으로 들어가는 걸 넣어주려면 여기에 넣어주면 된다.url을 통해 특정 페이지에 진입하기 전 통과하는 인터셉터 페이지다. public이미지 같은 정적(static) 에셋들을 보관         styles(강의에서는 있는데 내 폴더에는 없다..) 스타일링을 처리해주는 폴더 모듈(module) css는 컴포넌트 종속적으로 스타일링하기 위한 것이며, 확장자 앞에 module을 붙여줘야한다. next.config.js Next.js는 웹 팩을 기본 번들러로 사용한다. 그래서 웹 팩에 관한 설정들을 이 파일에서 해줄 수 있다.  [ Pre-rendering ]서버에서 각 페이지의 HTML 파일을 미리 생성하는 것으로, 모든 페이지가 pre-render된다. 이렇게 하기 때문에 SEO 검색 엔진 최적화가 좋아진다.            [ Data Fetching ]Next.js에서는 데이터를 여러 방법으로 가져온다. 상황에 맞는 것을 알아서 잘 사용하자.보통 React에서는 데이터를 가져올 때 useEffect 안에서 처리한다. 하지만 Next.js에서는 다른 방법을 사용해서 가져온다. (물론 Next에서도 useEffect를 이용해 가져올 수도 있다.)getStaticProps: Static Generation으로 빌드할 때 데이터를 불러온다. (미리 한 번에 만들어 줌)getStaticPaths: Static Generation으로 데이터에 기반하여 pre-render시 특정한 동적 라우팅 구현getServerSideProps: Server Side Renderin으로 요청이 있을 때 데이터를 불러온다. [ TypeScript ]타입스크립트는 자바스크립트에 타입을 부여한 언어이다. 즉, 자바스크립트의 확장된 언어이다. 타입 스크립트는 자바스크립트와 달리 브라우저에서 실행하려면 파일을 한 번 변환해주어야 한다. 이 변환 과정을 컴파일(compile)이라고 한다.타입스크립트의 특징을 정리해보자.자바스크립트의 타입 확장 버전즉, 동적 언어: 자바스크립트 / 정적 언어: 타입스크립트이다.개발 환경에서 에러를 잡는 걸 도와준다.type annotations을 사용해서 코드를 분석할 수 있다.오직 개발 환경에서만 활성화 된다.타입 스크립트와 성능 향상은 관계없다.즉, 타입스크립트가 막 자바스크립트보다 성능이 뛰어나다!!!! 가 아니다. 자바스크립트는 굉장히 자유도가 높다. 하지만 이는 규모 큰 프로젝트를 진행한다면 오히려 독이 될 수 있다. (지옥의 타입 에러가 시작된다고 한다.) 뭐 이와 같은 이유로 타입스크립트 사용을 권장을 한다. 물론 필수 X타입스크립트는 자바스크립트를 단순화하여 더 쉽게 읽고 디버그할 수 있도록 한다.코드를 더 쉽게 읽고 이해할 수 있다.오픈 소스이다.정적 검사와 같은 자바스크립트 IDE 및 사례를 위한 매우 생산적이 개발 도구를 제공한다.자바스크립트보다 더 개선된 코드를 작성할 수 있다.ES6의 모든 이점과 더 많은 생산성을 제공한다.고통스러운 버그에서 구출해준다. [ TypeScript Type ]타입이란 컴파일러에게 "야! 나 이 타입 쓸거다?"라고 선전포고하는 것이다. 즉, 내가 어떠한 value를 사용할 것인지 추론이 가능하도록 표기하는 것. 이는 컴파일러에게도 좋겠지만 코드를 읽는 개발자도 편하다.Primitive/Object types의 경우 다음과 같다. (이건 너무 기초에 기초니까 정리 PASS)Primitive: string, number, boolean, null, undefined, symbol Object : function, array, classes, object 타입 스크립트에서는 기본적인 타입 및 특별한 타입을 제공한다.Any잘 알지 못하는 타입의 경우 사용서드 파티 데이터 로딩 시.. 도대체 뭔 데이터가 올지 모를 때 사용하면 된다.\물론 이런 "뭔 타입 올지 머르는데...?"와 같은 확실치 않은 것은 최대한 안 쓰는 게 좋다.Union또는 이다. OR이니까 | 사용한다.let code: string | number; 이렇게 하면 code의 값은 string 또는 number라는 뜻.Tuple배열에 타입 지정하는 버전~let ex: [number, string] = [1, "hello"];Enumenumerated type을 의미하며, 값들의 집합을 명시하고 이를 사용하도록 만든다.별도의 값을 설정하지 않으면 기본적으로 0 스타트이다.Void반환될 때 반환되는 데이터가 없을 경우 쓴다.참고로 함수들에서 return에 반환할 데이터 명시 안 해도 기본적으로 undefined가 반환 된다.이렇게 반환되는 값이 없어서 undefined가 반환되는 경우 void 쓰면 된다.Never아에 완전히 영원히 값이 반환할 일이 없는 경우.. 기본적으로 함수가 undefined를 반환하는데 그 조차도 하지 않는 경우에 쓴다.오류 리턴이나 영원히 끝나지 않을 무한 루프에서 쓴다.  [ annotation, type, interface ]annotation: 개발자가 타입을 타입스크립트에게 말해주는법const str: string = "Hello, World!"; const num: number = 1;type: 이 키워드를 사용해서 내가 타입 정의가 가능하다.type Person = { name: string, age: number }interface: type과 비슷하게 정의 가능~interface Person = { name: string, age: number }다만 interface는 부가적인 기능이 많다고 한다. (나중에 찾아봐야겠다.) [ Type assertion ]타입스크립트에서는 시스템이 추론 및 분석한 타입 내용을 우리가 원하는 대로 얼마든지 바꿀 수 있다. 이때 "타입 표명(type assertion)"이라 불리는 메커니즘이 사용된다.var foo = {}; foo.bar = 123; // 오류: 속성 bar가 존재하지 않음. foo.bas = "hello"; // 오류: 속성 bas가 존재하지 않음.컴파일러는 foo type이 빈 {}로 인식한다. 따라서 존재하지 않은 bar와 bas에 접근하려고 하는 것으로 보이기 때문에 당연히 오류를 낸다. 하지만 type assertion을 사용하면 이런 상황을 피할 수 있다.interface Foo { bar: number; bas: string; } var foo = {} as Foo; foo.bar = 123; foo.bas = "hello";저기 서 사용된 as가 type assertion이다.완전 간단하게 "컴파일러야. { } (왼쪽에 명시된 얘)는 Foo(오른쪽)와 같으니까 의심하지 말고 Foo(오른) 처럼 사용해라"라는 뜻이다. [ Next.js 13 ]12에서 13으로 넘어가면서 Next.js가 많이 바뀌었다고 한다! 위에서 설명한 것은 12니까 이 강의가 굉장히 중요해 보였다. (현재 14.1까지 나와따)다음 추가된 사항이고... 대부분 실습 위주 강의라서 간단하게 정리만 했다.App Routerpage 파일이 해당 경로의 페이지 컴포넌트 처리된다.Layout기본 레이아웃 정의 가능.공통된 레이아웃을 적도 children을 감싸는 형식으로 하면 된다.Server/Client ComponentNext에서는 기본이 Server Component이다.State, Hook, 이벤트 처리 및 브라우저 api 사용 => 이 경우 Client Component를 사용해야한다.코드 작성 전 맨 첫 줄에 "use client" 명시해주면 된다. Section 09. 리액트 Version 18새로 추가된 내용Automatic batchingSuspense on the server Transition등등...  [ Automatic batching ]배칭은 업데이트 대상이 되는 상태 값들을 하나의 그룹으로 묶어서 한 번의 리렌더링에 업데이트가 모두 진행될 수 있게 해주는 것이다. 하나의 함수 내부에서 여러 개의 state를 조작했을 경우 리렌더링이 그 state의 수 만큼 실행되는 것이 아니라 딱 1번만 최종 실행된다는 것이다. 그리고 제목에서 보이듯이 자동처리다. 개발자가 딱히 배칭을 위해 설정할 것은 없다.더 나은 성능을 위한 더 적은 리렌더링 가능이벤트 핸들러 밖에서도 작동필요할 때 제외 가능   [ Suspense on the server ]서버 사이드 렌더링서버에서 전체 앱에 대한 데이터 가져옴서버에서 전체 앱을 HTML로 렌더링하고 응답으로 보냄클라이언트에서 전체 앱에 대한 자바스크립트 코드 로드클라이언트에서 자바스크립트 논리를 전체 앱에 대해 서버 생성 HTML에 연결(hydration) [ Transition ]리액트에서 어떠한 업데이트가 Urgent하며 어떠한 것이 그러하지 않은지 알려준다. Section 10. 리덕스리덕스는 자바스크립트의 애플리케이션위한 상태 관리 라이브러리이다.CreateStore()앱의 전체 상태 트리를 보유하는 Redux 저장소를 만든다.앱에는 하나의 스토어만 있어야 한다.getState()애플리케이션의 현재 상태 트리를 반환한다.subscribe(listener)listener 함수 등록Action이 dispatch될 때마다 리스너 함수가 호출된다.그런 다음 getState()를 호출하여 콜백 내부의 현재 상태 트리를 읽을 수 있다. [ Provider ]<Provider> 구성 요소는 Redux Stroe 저장도에 액세스해야 하는 모든 중첩 구성 요소에서 Redux Store 저장소를 사용할 수 있도록 한다.React Redux 앱의 모든 Reqact 구성 요소는 저장소에 연결할 수 있으므로 대부분의 응용 프로그램은 전체 앱의 구성 요소 트리가 내부에 있는 최상위 수준에서 <Provider>를 렌더링한다.그런 다음 Hooks 및 연결 API는 React의 컨텍스트 메커니즘을 통해 제공도니 저장소 인스턴스에 액세스할 수 있다. [ useSelector, useDispatch ]리덕스 HOOKuseSelector스토어의 값을 가져올 수 있다.useDispatchstore에 있는 dispatch 함수에 접근. [ 리덕스 미들웨어 ]Redux 미들웨어는 액션을 전달하고(dispatch) 리듀서에 도달하는 순간 사이에 사전에 지정된 작업을 실행할 수 있게 해주는 중간자이다.💡 로깅, 충돌 보고, 비동기 API 통신, 라우팅 등을 위해 미들웨어를 사용한다!미들웨어 생성에 관한 것은 강의에서 실습으로 소개하니 궁금하면 강의를 보자. [ 커링 ]자바스크립트 고급 기술이다. (다른 언어에도 존재.)f(a, b, c)처럼 단일 호출로 처리하는 함수를 f(a)(b)(c)와 같이 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합될 수 있게 변환하는 것이다. [ Thunk ]리덕스를 사용하는 앱에서 비동기 작업을 할 때 많이 사용하는 방법이다. "thunk"라는 단어는 "일부 지연된 작업을 수행하는 코드 조각"을 의미하는 프로그래밍 용어이다. Redux 스토어의 dispatch 및 getState 메서드와 상호 작용할 수 있는 내부 로직이 있는 함수를 작성할 수 있다. [ Redux Toolkit ]Redux 툴킷은 Redux 로직을 작성하기 위한 공식 권장 접근 방식이다.Redux 코어를 둘러싸고 있으며 Redux 앱을 빌드하는 데 필수적이라고 생각하는 패키지와 기능이 포함되어 있다.Redux 툴킷은 Redux 작업을 단순화하고 일반적인 실수를 방지하고 Redux 애플리케이션을 더 쉽게 작성할 수 있다.Redux 툴킷에는 Redux Thunk가 기본으로 들어가있다. 사용 순서:configureStore을 사용하여 Redux Store 만들기React 컴포넌트에 Redux Stroe 제공 순서주위에 React-Redux <Provider>로 컴포넌트를 감싸준다.Redux Stroe를 <Provider store={store}>로 전달한다.creatSlice로 Redux 슬라이스 리듀서 생성React 컴포넌트에서 React-Redux useSelector/useDispatch Hook 사용미션과제 총 합본 https://www.inflearn.com/blogs/7021React 미션 02. 디즈니+ 클론과제 중에 가장 어려웠던 부분은 구글 연동이었습니다. 처음으로 구글 연동을 시도하면서 계속해서 오류가 발생했고, 한 번은 무한 로그인에 걸려 프로그램이 멈춘 적도 있었습니다. 이때는 정말 심장이 철렁거렸습니다. 그러나 마음을 비우고 처음부터 차근차근 시도하니 로그인 연동에 성공했습니다.또 다른 어려움은 마우스를 대면 비디오가 나오는 부분이었습니다. 이미지와 비디오를 겹쳐놓고 마우스가 hover될 때 비디오만 보여주는 부분인데, CSS의 position 이해가 부족한 것인지 배치가 제대로 되지 않아 계속 시도해야 했습니다. position에 대한 부분은 추가적인 학습이 필요하다고 느꼈습니다.React 미션 03. 포켓몬 도감포켓몬 과제는 난이도가 상이었고 디즈니와 다르게 참고할 코드조차 없는 어려운 과제였습니다. 이것은 정말 자기 스스로 머리를 쪼개가며 해결 해야하는 과제로 보였기에 가장 마지막에 해결을 하겠다 생각했습니다. 포켓몬 도감를 시작할 때, 이제야 웹을 공부를 하는 제가 이 과제를 과연 완성을 할 수 있을까? 했는데, 걱정과 다르게 디즈니보다 훨씬 쉬었습니다...! 코드를 작성하면서 렌더링이 안 일어나는 이상한 상황을 겪었지만(map key 값이 고유하지 못해서 발생한 문제) 금방 해결하고 완성을 했습니다!! 그 밖에는 문제된 일은 없습니다. 제가 스스로 작성한 코드가 작동하는 것을 보니 정말 뿌듯하네요. 그리고 예시와 다르게 UI를 상당히 많이 바꿨습니다...! 미션을 하면서 가장 즐거웠던 과제였습니다👍 React 미션 04. Next, TypeScript을 이용한 퀴즈 앱이번 프로젝트에서는 라우팅을 처리하기 위해 사용한 useRouter에서 문제가 발생했습니다. 문제를 해결하려고 찾아보니, next/router 대신에 next/navigation을 사용해야 한다는 것을 알게 되었습니다. 그것을 마지막으로 문제 없이 잘 과제를 끝 맞추었습니다.회고워밍업 스터디를 처음 시작할 때에는 HTML/CSS, JS의 기초만 약간 알고 있었고, 부트캠프나 프로젝트 경험이 없었습니다. 또한, 외적인 사정과 긴 강의 시간, 다양한 미션으로 인해 시간적으로도 부족함을 느꼈습니다. 하지만 저 자신의 발전을 위해서 새벽 3~4시까지 시간을 투자해나가며 수업과 미션을 해결해나갔습니다.또한, 저는 코틀린을 사용한 경험이 있는데, 타입 스크립트가 코틀린과 유사하다는 느낌을 받아서 타입 관련 공부가 수월했습니다. 하지만 타입스크립트의 심화 부분과 Next.js, 리덕스 등에 대해서는 추가적인 공부가 필요하다고 생각하고 있습니다.3주간의 스터디는 성장감을 느끼게 해주었습니다. 그렇기에 이미 끝났다는 사실이 아쉽기도 합니다. 이 소중한 경험을 제공해 준 인프런과 스터디를 이끌어주신 강사님에게 깊은 감사의 인사를 전합니다.앞으로도 계속해서 성장하고 발전하기 위해 노력할 것이며, 새로운 도전들을 마주하면서 더욱 성장해 나가고 싶습니다. 감사합니다! 🌱

프론트엔드워밍업클럽FE

이양구

[인프런 워밍업 클럽 FE 0기] 미션7 - 예산 계산기 앱

💸 Budget Calculator APP GitHub 💸 Budget Calculator APP DemoRecord by ScreenToGif  개요인프런 워밍업 클럽 FE 0기의 일곱 번째 미션인 '예산 계산기 앱' 입니다. 따라하며 배우는 리액트 섹션 0~3(To-Do 앱) 목표의존성 배열(Dependency Array) 을 이용해 함수 실행하기state 를 전역 변수처럼(?) 사용해보기 구현구조|-- App | |-- Form | |-- Lists | | |-- List  의존성 배열(Dependency Array) 을 이용해 함수 실행하기// App.jsx const [budgetList, setBudgetList] = useState( JSON.parse(localStorage.getItem("budgetList")) || [] ); useEffect(() => { localStorage.setItem("budgetList", JSON.stringify(budgetList)); }, [budgetList]); const totalCost = useCallback(() => { return budgetList.reduce((acc, cur) => acc + cur.cost, 0); }, [budgetList]); 최상위 컴포넌트인 <App> 컴포넌트에서 만든 'budgetList'이라는 state를 useEffect와 useCallback의 의존성 배열에 추가했다.useEffect에서는 해당 state가 변경되면 로컬 스토리지의 budgetList를 최근의 리스트로 변경한다.이렇게 하면 일일이 setBudgetList가 호출되는 곳마다 함수를 사용하지 않아도 된다.다음은 예산의 총 금액을 반환하는 함수가 리스트가 변경될 때마다 실행되도록 useCallback으로 감싸고 의존성 배열에 state를 추가했다.// Form.jsx const budgetNameRef = useRef(); const [budgetName, setBudgetName] = useState(""); const [budgetCost, setBudgetCost] = useState(0); useEffect(() => { if (isEdit) { setBudgetName(budget.name); setBudgetCost(budget.cost); budgetNameRef.current.focus(); } }, [isEdit]); <Form> 컴포넌트에서는 useEffect에 'isEdit'이라는 state를 의존성 배열에 추가했다.사용자가 예산을 수정하기 위해 list의 Edit 버튼을 클릭하면 해당 budget의 name과 cost를 최근 state로 불러오고, useRef를 이용해 name을 입력하는 <input> 요소에 focus 상태가 되도록 했다.state 를 전역 변수처럼(?) 사용해보기// App.jsx const [currentBudget, setCurrentBudget] = useState({ isEdit: false, budget: {}, }); // List.jsx const handleEdit = () => { setCurrentBudget({ isEdit: true, budget: list, }); setHandleStatus({ type: "edit", message: "Editing..." }); }; // Form.jsx const handleBudgetSubmit = (e) => { const newBudget = { id: Date.now(), name: budgetName, cost: budgetCost, }; // isEdit의 값에 따라 새로 추가할지 수정할지 결정 if (isEdit) { setBudgetList((prevBudgetList) => { const newBudgetLists = [...prevBudgetList]; const index = newBudgetLists.findIndex(({ id }) => id === budget.id); newBudgetLists[index] = newBudget; return newBudgetLists; }); setCurrentBudget({ isEdit: false, budget: {} }); setHandleStatus({ type: "submit", message: "Edit Success!" }); } else { setBudgetList((prevBudgetLists) => [...prevBudgetLists, newBudget]); setHandleStatus({ type: "submit", message: "Submit Success!" }); } // submit 종료 시 input의 데이터를 초깃값으로 설정 setBudgetName(""); setBudgetCost(0); }; 배웠던 To Do 앱은 List의 Edit 버튼을 클릭했을 때 해당 List의 요소를 input 요소로 변경시키고 수정을 했다.하지만 과제는 클릭을 했을 때 List의 요소를 변경시키는 게 아니라 Form의 input에 해당 예산의 데이터를 전달해야 했다.그래서 마치 전역 변수처럼 사용할 'currentBudget'이라는 state를 생성하고 'isEdit'이라는 boolean 값과 수정할 예산의 데이터를 담을 'budget'이라는 값을 설정했다.'isEdit'의 상태 값이 true일 때 수정하기와 삭제하기 <button> 요소를 disabled로 변경한다.또한 submit 함수는 새로운 입력 값을 budgetList에 추가하지 않고 해당 예산의 index를 찾아 수정하고 리스트를 변경한다.이렇게 하니 onSubmit과 onEdit 처럼 비슷한 기능을 하는 함수를 여러 개 만들지 않아도 되었다. ⚠ setTimeout 렌더링const { type, message } = handleStatus; const handleStyle = useCallback(() => { if (type === "edit") { return "text-gray-500 block"; } else if (type === "none") { return "hidden"; } else { // 2초 뒤에 실행 --> App - Form - Status 1번 더 렌더링 setTimeout(() => { setHandleStatus({ type: "none", message: "" }); }, 2000); if (type === "submit") { return "text-green-400 block"; } else { return "text-red-400 block"; } } }, [type]); 추가, 삭제, 수정의 완료 및 진행 중 상태를 보여주는 <Status> 컴포넌트를 만들었다.App에서 만든 'handleStatus'라는 state를 전달하고 메세지가 나타난 뒤에 사라지게 만들고 싶어서 setTimeout() 메서드를 이용해 2초 뒤에 상태를 초기화했다.하지만 이 상태가 App과 Form 컴포넌트에서 참고하다 보니 나타나고 사라질 때마다 렌더링이 발생했다.CSS의 opacity로 처리하기엔 state의 값을 변경해야 했기에 알맞는 방법은 아니라 생각했다.뭔가 <Status> 컴포넌트 내부에서만 렌더링이 일어나게 하고 싶었는데 아직 다른 방법을 찾지 못했다.😢😢😢 회고다른 컴포넌트의 클릭 이벤트로 변경된 state를 이용하는 부분이 생각보다 오래 걸렸다.처음엔 콜백 함수처럼 App 컴포넌트에서 함수 만들고 prop으로 넘겨봤지만 List와 Form은 종속적인 관계가 아니라 힘들었다. 😢그래서 생각해낸 게 state를 이용해서 상태의 변경을 이벤트처럼 사용하는 것이었다.pub-sub 혹은 observer 패턴 같다는 생각도 했지만, 이렇게 최상위에서 선언한 state가 이곳저곳 돌아다니는 게 좋은 방법은 아닐 것 같다는 생각이 들었다.규모가 커지면 렌더링 관리도 힘들고 props를 쫓아다녀야 하기 때문이다.이래서 상태 관리 라이브러리가 나왔나 보다. 🤔 

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

도롱이

[인프런 워밍업 클럽_0기] 2주차, 두 번째 발자국 #2

2주차, 두 번째 발자국2주차는 계속 되는 야근으로 인해 시간에 쫓기듯이 공부하고, 과제했던 주였다. 속도가 급하면 체하기 마련! 그래서 오타 등의 실수도 많이해서 삽질로 많은 시간을 보내기도 했다.이전 발자국에서도 남겼지만 강의 별 요약본은 notion에 있다.https://abalone-copper-ebe.notion.site/d2e9b3e27b3348abbde60994cf627ebd?pvs=4 Day 7. 스프링 컨테이너의 의미와 사용 방법스프링 컨테이너의 역할을 정확히알게 되었다.스프링 컨테이너 : 서로 필요한 관계(의존 관계)에 있는 스프링 빈을 연결해주는 역할스프링 컨테이너의 동작 과정을 알게 되었다.스프링이 서버를 시작한다 > 스프링 컨테이너가 시작된다 > 기본적으로 설정된 스프링 빈들이 등록된다 > 개발자가 설정한 스프링 빈이 등록된다 > 필요한 의존성이 자동으로 설정된다.스프링에서 등록한 스프링 빈을 어떤식으로 땡겨와야하는지 알게 되었다.등록된 스프링 빈을 사용하려면 해당 클래스 파일을 스프링 빈에 등록해야 땡겨올 수 있다!Interface를 이용하여 코드 수정 시 수정하는 부분을 최소화 할 수 있다.다른 클래스에서 Interface를 상속받게하고 생성자에서 교체하고 싶은 구현체를 변경만해주면 되기 때문!하지만 위의 방법도 어찌저찌 됐든 생성자를 수정해야하기 때문에 수정은 불가피하다! 이런 걸 해결할 수 있는 어노테이션이 @Primary 와 @Qualifier를 사용하면 구현체 주입 우선순위를 설정해줄 수 있다.참고로 Primary와 Qualifier 중 우선순위가 더 높은 건 Qualifier이다.  과제https://devhan.tistory.com/323기존에 작성했던 코드를 Controller, Service, Repository 3단계로 분리하는 과제였다. 다른 건 다 괜찮았는데 Repository가 Interface로 변경되고 MemoryRepository와 MySQLRepository로 구현체를 나뉘어서 개발하는 부분에 시간을 너무 많이 쏟았던 기억이 난다.그래도 개발하면서 기존에 작성했던 코드를 리팩토링 하는 과정도 거칠 수 있어서 더 재밌게 코딩할 수 있었던 거 같다. Day 8. Spring Data JPA를 사용한 데이터베이스 조작8일차에는 String으로 작성했던 쿼리 방식의 단점을 알아보고 변경하는 시간이었다.Java의 객체와 Database의 테이블의 패러다임이 다르다는걸 정확하게 알게되었다.또한 Java의 상속을 Database로 표현하기 어려운 부분이 존재한다는걸 알게되었다.JPA는 단순한 규칙이라는걸 알게되었다.JPA의 전반적인 설정 방법과 사용 방법들을 알게되었다.람다식이 우르르 나와서 해당 관련 공부를 또 뼈저리게 느꼈다. 과제https://devhan.tistory.com/324이번 과제도 기존에 작성했던 코드 중 문자열로 작성된 쿼리를 JPA로 변경하는 과제였다.warehousingDate 필드가 제대로 맵핑되지 않는 문제때문에 골머리를 앓았다. 찾아보니 스프링에서는 카멜케이스로 작성된 필드는 DB 컬럼에서는 '_'로 단어를 구분한다고 한다. ex) warehousingDate -> warehousing_date이 에러는 ddl-auto를 create로 만들어주고 처음부터 다시 매핑해서 해결되었다.그 외에는 딱히 어려운 점은 없었다! Day 9. 트랜잭션과 영속성 컨텍스트트랜잭션의 이론에 대해서 알게 되었다. 트랜잭션이 뭘 하는지는 대략적으로 알았는데 딱 정의할 수는 없었다. 트랜잭션 -> 쪼갤 수 없는 업무의 최소 단위@Transactional의 사용 범위와 readOnly 옵션에 대해 알게 되었다.Select 쿼리에서는 readOnly 옵션을 사용하는게 성능상 더 좋다영속성 컨텍스트에 대해 알게 되었다.테이블과 매핑된 엔티티 객체를 관리하고 보관스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨남트랜잭션을 종료하면 영속성 컨텍스트가 종료됨영속성 컨텍스트의 4가지 장점변경 감지(Dirty Check) : 영속성 컨텍스트 안에서 불러와진 객체는 명시적으로 save 하지 않더라도, 기존 정보와의 변경을 감지해 자동으로 저장된다.쓰기 지연 : DB의 INSERT, UPDATE, DELETE SQL을 바로바로 날리는게 아니라 트랜잭션이 commit될 때 한번에 모아서 한 번만 날린다.1차 캐싱 : 아이디를 기준으로 객체를 기억하고, 해당 객체가 DB에서 다시 불려와질 때 변경된 정보가 없다면 굳이 DB를 통하지 않고 영속성 컨텍스트에서 해당 정보를 돌려준다.캐싱된 객체는 완전히 동일하다 -> 객체의 인스턴스 주소까지 완전 동일 과제이 날부터 미니 프로젝트가 시작되었다.첫 날이라 유의미한 코딩을 한 건 아니었고 프로젝트 생성부터 설정까지 완료하였다.그리고 앞으로 어떤식으로 개발할지 전체적인 틀을 그렸던 것 같다! Day 10. 조금 더 복잡한 기능을 API로 구성하기책 생성, 대출, 반납 기능을 개발하면서 전체적인 개념을 다시 잡기도하고 좀 더 객체지향적으로 코딩하는 방법을 알았던 날이다.되게 좋았던 건 얼마 전에 객체지향의 사실과 오해라는 책을 읽었었는데 사실 책에서는 예시 코드가 나오지 않아 약간 실무에서는 어떤식으로 접근해야할까에 대한 의문이 좀 남아있었다. 책을 읽어도 약간 반만 알겠는 느낌..? 근데 이 강의에서 딱 객체지향적으로 코딩을 해볼 수 있어서 그래도 느낌을 좀 알 것 같았다. 평소 회사에서 전혀 객체지향적으로 개발하지 않아 domain에 비즈니스 로직을 직접 넣어도 되는지 조차 몰랐었는데 이번 강의에서 그 부분에 대한 갈증을 조금 해소할 수 있어서 아주 마음에 들었다. 과제https://devhan.tistory.com/326어느정도 개발이 끝났던 시기였던 거 같다. 과제를 하면서 Team과 Employee의 연관관계를 담은 테이블을 강의처럼 따로 만들어야할지 말지 고민이 많았었고 또, Team의 ID를 Long 타입의 id로 하느냐, String 타입의 name으로 하느냐의 고민도 많았다..! Long 타입의 id로 하면 나중에 Employee를 조회할 때마다 Team의 객체를 가져와서 name을 또 Response 객체에 저장해줘야할 것 같은 번거로움 때문에 그냥 String name을 primary key로 지정했다. 코드에 대한 많은 생각을 할 수 있어서 좋은 시간이었던 거 같다.   

백엔드워밍업클럽백엔드스터티

이양구

[인프런 워밍업 클럽 FE 0기] 미션4-2 - GitHubFinder 앱

🔍 github-finder-app GitHub 🔍 github-finder-app 개요인프런 워밍업 클럽 FE 0기의 네 번째 미션인 'GitHubFinder 앱' 입니다.따라하며 배우는 자바스크립트 섹션 5(OOP), 섹션 6(비동기) 목표Fetch API 를 이용해 깃허브 유저 목록 불러오기Closure 를 이용해 Debounce Function 만들기 구현Fetch API 를 이용해 깃허브 유저 목록 불러오기async function loadUser(input) { prevInputValue = input; try { // const response = await fetch('./src/javascript/user.json'); const response = await fetch(`${url}/${input}`); if (!response.ok) { throw new Error('Failed to fetch user json'); } const json = await response.json(); setUserAvatar(json); setUserInfo(json); await loadUserRepos(json); } catch (error) { console.error(error); } }fetch() 메서드의 응답은 HTTP 응답 전체를 나타내는 'response' 객체를 반환한다.response의 ok 속성은 응답의 성공 여부를 불리언 값으로 가지고 있다.따라서 응답이 성공이 아닐 경우 오류 객체(new Error())를 반환하고 catch 문으로 Promise의 오류를 처리한다.응답에 성공한 response 객체를 JSON으로 사용하기 위해선 json() 메서드를 이용해 파싱해야 한다. Closure 를 이용해 Debounce Function 만들기// debounce debounceInput.addEventListener('input', debounce(loadUser, 1000)); // debounceInput.addEventListener('input', e => callback(e)); function debounce(callback, delay = 0) { // timer는 부모 함수에서 선언된 지역 변수 let timer = null; return (arg) => { // 여기서 arg는 input event if (timer) { // 이미 타이머가 있는데 또 실행되면 타이머 삭제 clearTimeout(timer); } // 변수 timer는 부모 함수에서 선언되었지만 내부 함수에서 사용(클로저) timer = setTimeout(() => { callback(arg.target.value); }, delay); }; }<input> 요소의 'input' 이벤트는 요소의 value가 변경될 때마다 발생한다.만약 사용자가 입력할 때마다 서버에 데이터를 요청한다면 서버의 부하가 커지기 때문에 좋은 방법은 아니다.이럴 때 사용자의 입력이 끝난 뒤 마지막 value를 이용해 서버로 요청하는 게 효율적인 방법이라 할 수 있다.함수의 실행 요청이 반복될 때 마지막 요청만으로 실행하는 걸 '디바운싱(debouncing)'이라고 부른다.debounce 함수는 인자로 실행할 함수를 받고 자식 함수를 반환한다.부모 함수인 debounce 함수에서 선언한 변수(timer)를 자식 함수에서 사용할 수 있는 클로저(Closure)를 이용해 자식 함수의 setTimeout() 메서드의 반환 값인 'timeoutID'를 할당한다.변수 'timer'에 할당한 timeoutID를 이용해 setTimeout() 메서드의 지연 시간(delay)이 종료되기 전에 요청이 들어왔다면 이전에 생성한 타이머를 clearTimeout() 메서드를 이용해 종료하고 다시 타이머를 할당한다. 이렇게 delay로 설정한 시간 이내에 사용자의 입력이 없을 경우 API 요청 함수를 실행하게 된다. 반복적인 함수의 실행을 다루는 방법으로 디바운싱(debouncing)와 쓰로틀링(throttling)이 있다.여러 변수를 고려해 'lodash' 라이브러리의 debounce를 많이 사용한다. 회고이번 미션은 debounce가 반환하는 자식 함수의 인자(argument)가 어떤 타입인지 알기 때문에 callback 함수에 전달하는 인자를 수정해서 미숙한 debounce 함수라고 볼 수 있다.늘 라이브러리를 통해 사용하던 함수를 만들려고 하니 모르는 것도 많고, 고려해야 할 부분이 많다는 걸 알게 됐다.자바스크립트의 기초를 잘 알아야 이런 라이브러리 메서드의 원리를 이해하기도 쉽고, 커스텀하기에 수월한 것 같다.(외의로 GitHub의 API 요청이 API key 없이도 되어서 신기했고, 그 덕에 조금은 수월했다. 아주 조금... 😵) DemoRecord by ScreenToGif

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

jikwan12

[ 인프런 워밍업 클럽 FE 0기 ] 1주차 발자국

2024 새로운 도전을 하기 위해 여러 사이트를 돌아다니던 중 인프런 워밍업 클럽을 발견하게 되었습니다. 마침 저는 취업 준비를 앞두고 있고 자바스크립트 기초 지식을 단단하게 다져 취업을 준비해야겠다는 생각이 들었고 이러한 좋은 기회를 놓칠 수 없어 바로 신청하게 되었습니다.강의 요약01. 자바스크립트 기초[ console 객체 ]JavaScript에서 제공하는 내장 객체 중 하나이다.이 객체를 사용하면 개발자는 브라우저의 콘솔이나 터미널에 다양한 정보를 출력하고 디버깅할 수 있다.다양한 메서드를 제공하여 개발자가 원하는 정보를 출력하거나 디버깅할 때 유용하다.console 객체 일부 메서드log(): 콘솔에 일반적인 로그 메시지를 출력error(): 콘솔에 에러 메시지를 출력warn(): 콘솔에 경고 메시지를 출력 table(): 테이블 형태로 데이터를 출력time()과 timeEnd(): 특정 코드 블록의 실행 시간을 측정  [ let, var, const]let:블록 범위(block-scoped) 변수를 선언변수를 선언한 블록 내에서만 접근 가능변수의 값은 재할당이 가능같은 이름의 변수를 중복해서 선언할 수 없음var:함수 범위(function-scoped) 변수를 선언변수를 선언한 함수 내에서만 접근 가능변수의 값은 재할당이 가능같은 이름의 변수를 중복해서 선언할 수 있음호이스팅(hoisting)이 발생하여 변수 선언이 해당 스코프의 최상단으로 끌어올려짐const:블록 범위(block-scoped) 상수를 선언변수를 선언하고 초기값을 할당한 후, 재할당이 불가능변수의 값이 변하지 않아야 할 때 사용같은 이름의 변수를 중복해서 선언할 수 없음 [ 호이스팅 ]JavaScript에서 변수 선언과 함수 선언을 해당 스코프의 최상단으로 끌어올리는 동작변수 호이스팅의 예시console.log(x); // undefined var x = 5; console.log(x); // 5위 코드에서 var x = 5; 문장 이전에 console.log(x);를 호출하고 있다. 하지만 결과는 undefined가 출력된다. 이는 변수 x의 선언이 호이스팅에 의해 해당 스코프의 최상단으로 끌어올려진 후, 초기값이 할당되기 전까지 undefined로 초기화되기 때문이다. 함수 호이스팅의 예시sayHello(); // "Hello!" function sayHello() { console.log("Hello!"); }위 코드에서 sayHello() 함수를 호출하기 전에 함수를 선언하고 있다. 이는 함수 선언이 호이스팅에 의해 해당 스코프의 최상단으로 끌어올려진 후, 호출 위치와 상관없이 함수를 사용할 수 있게 된다. [ 타입, 타입 변환 ]자바스크립트의 타입은 다음과 같음원시 타입: Boolean, String, Number, null, undefined, Symbol참조 타입: Object, Array  원시타입은 고정된 크기로 Call Stack 메모리에 저장되며 실제 데이터가 변수에 할당된다.참조타입은 데이터 크기가 정해지지 않고 Call Stack 메모리에 저장되며 데이터의 값이 Heap에 저장되며 메모리의 주소 값이 할당된다. 타입 변환 유형명시적 데이터 변환: 직접 함수를 통한 변환자동 데이터 변환: 자바스크립트 자체에 의해 자동으로 변환 [ 연산 및 Math Object ]Math object에서 제공하는 다양한 메서드들을 이용해 다양한 연산을 할 수 있다.Math 일부 메서드Math.abs(x):주어진 숫자의 절댓값을 반환합니다.예: Math.abs(-5)는 5를 반환합니다.Math.ceil(x):주어진 숫자보다 크거나 같은 정수 중 가장 작은 수를 반환합니다.예: Math.ceil(4.2)는 5를 반환합니다.Math.floor(x):주어진 숫자보다 작거나 같은 정수 중 가장 큰 수를 반환합니다.예: Math.floor(4.8)는 4를 반환합니다.[ Template Literals ]Template literal은 JavaScript에서 문자열을 작성하는 방법으로, 백틱(``)을 사용한다. 이를 통해 변수나 표현식을 쉽게 삽입하고 멀티라인 문자열을 작성할 수 있으며, 특수 문자 처리에 용이하다. ${}를 활용하여 문자열에 변수를 할당할 수 있다.[ Loops ]for: 코드 블록을 여러 번 반복for/in: 객체 속성을 따라 반복while: 지정된 조건이 true 인 동안 코드 블록을 반복do/while: 조건이 true인지 검사 전에, 코드 블록을 한 번 실행시킨다. 그 이후 while 반복문 실행02. Window 객체 및 DOM[ window 객체 ]window 객체는 웹 브라우저 창을 나타내는 전역 객체입니다.JavaScript에서 모든 전역 변수와 함수는 window 객체의 프로퍼티 또는 메서드로 접근할 수 있습니다. 예를 들어, window.alert()와 window.innerWidth와 같이 사용할 수 있습니다.브라우저 창의 크기, URL 정보, 타이머, 팝업 창 등 다양한 기능을 제공합니다.window 객체는 생략 가능하므로, alert()와 innerWidth와 같이 사용하는 것도 가능합니다.[ DOM ]DOM은 HTML, XML 또는 XHTML 문서의 구조를 표현하는 객체 지향적인 표현 방식입니다.웹 페이지의 요소(element)들을 트리 구조로 표현하며, 각 요소는 노드(node)라고 불리는 객체로 표현됩니다.DOM을 통해 JavaScript는 문서의 구조, 스타일, 내용 등을 동적으로 조작할 수 있습니다.DOM은 HTML 요소에 접근하고 조작하기 위한 다양한 메서드와 속성을 제공합니다. 예를 들어, getElementById(), querySelector(), innerHTML 등을 사용하여 요소를 선택하거나 내용을 변경할 수 있습니다.DOM은 웹 페이지의 상호작용과 동적인 변경을 가능하게 해주는 핵심적인 요소로, JavaScript에서 웹 페이지와의 상호작용을 구현하는 데 사용됩니다.03. Event[ Event ]JavaScript에서 이벤트는 웹 페이지나 애플리케이션에서 발생하는 사용자의 동작이나 시스템 상태 변화를 감지하고, 이에 대한 응답을 처리하는 메커니즘입니다. 이벤트는 HTML 요소나 JavaScript 객체에서 발생할 수 있으며, 특정 동작이나 상태 변화에 대응하여 코드를 실행할 수 있도록 도와줍니다.[ Event Bubbling과 Event Capturing ]이벤트 버블링(Event Bubbling)과 이벤트 캡처링(Event Capturing)은 HTML 요소 간에 중첩된 구조에서 이벤트가 전파되는 방식을 설명하는 개념입니다.이벤트 버블링 (Event Bubbling):이벤트 버블링은 이벤트가 발생한 요소에서 시작하여 상위 요소로 전파되는 현상을 의미합니다.예를 들어, <div> 요소 안에 <p> 요소가 있고, <p> 요소를 클릭할 때 해당 이벤트가 발생하면, 이벤트는 <p> 요소에서 시작하여 <div> 요소, 그리고 상위 요소들로 전파됩니다.이벤트 버블링은 부모 요소로 이벤트가 전파되므로, 상위 요소에서도 동일한 이벤트를 처리할 수 있습니다.이벤트 리스너를 상위 요소에 등록하면 하위 요소에서 발생한 이벤트도 감지할 수 있습니다.이벤트 캡처링 (Event Capturing):이벤트 캡처링은 이벤트가 발생한 요소에서 시작하여 상위 요소로 전파되는 현상과 반대로, 상위 요소에서 시작하여 이벤트가 발생한 요소까지 전파되는 현상을 의미합니다.이벤트 캡처링은 이벤트가 발생한 요소의 최상위 부모 요소부터 시작하여 하위 요소로 전파됩니다.이벤트 캡처링은 이벤트 리스너를 상위 요소에 등록하고, 하위 요소에서 발생한 이벤트를 상위 요소까지 전파하여 처리할 수 있습니다. [ Event Delegation ]이벤트 위임(Event Delegation)은 상위 요소에 이벤트 리스너를 등록하여 하위 요소들의 이벤트를 처리하는 방식 04. 자바스크립트 중급[ this ]Method의 this: 해당 객체를 가리킨다.함수에서 this: window 객체를 가리킨다.constructor의 this: 빈 객체를 가리킨다. [ bind, call, apply]call():함수를 호출하는 함수.첫 번째 인자 값으로 어떠한 것을 전달해 주면 호출되는 함수의 this가 인자 값으로 지정apply(): call()과 유사하나 인수 부분에 배열을 넣어줘야함.bind(): 해당 함수가 지정한 인자 값을 가리키도록 하지만 call(), apply()와 다르게 직접 함수 실행 X [ 삼항 연산자 ]? 앞의 조건을 기준으로 조건이 참이면 : 앞의 있는 부분을 반환하고 거짓이면 뒷부분 반환 [ Event Loop]이벤트 루프(Event Loop)는 JavaScript에서 비동기 작업을 처리하는 동작 메커니즘입니다. 이벤트 루프는 단일 스레드 환경에서 비동기 작업을 효율적으로 처리하기 위해 사용됩니다.[ Closure ]다른 함수 내부에 정의된 함수가 있는 경우, 외부 함수가 실행을 완료하고 해당 변수가 해당 함수의 외부에서 더 이상 엑세스할 수 없는 경우에도, 해당 내부 함수는 외부 함수의 변수 및 액세스가 가능하다. 이 기능을 Closure라고 부른다.[ 구조 분해 할당 ]배열이나 객체의 속성을 분해하여 사용할 수 있는 형태로 만드는 것[ Map, Filter, Reduce ]Map, Filter, Reduce은 배열 메서드의 대표적인 예시이다.map(): 배열 내의 모든 요소 각각에 대하여 동작을 수행하고 나온 결과를 새로운 배열로 만들어 반환한다.filter(): 기존 배열의 필터를 통과하는 요소만을 새로운 배열로 반환한다.reduce(): 배열의 각 요소에 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결괏값을 반환한다.[ 얕은 복사 VS 깊은 복사 ]깊은 복사(Deep Copy): 원본 객체의 모든 내용을 복사하여 새로운 객체를 생성합니다. 얕은 복사(Shallow Copy): 원본 객체의 참조만을 복사하여 동일한 객체를 가리키는 새로운 객체를 생성합니다.[ 함수 표현식, 함수 선언문 ]함수 선언문: 함수 선언은 함수를 만들고 이름을 지정하는 것이다.일반적인 함수 선언 방식으로 function 키워드와 식별자를 표기하여 사용한다.함수 표현식은 함수를 만들고; 변수에 할당하는 것이다.익명 함수(function 키워드는 사용했으나 식별자 X), 화살표 함수 사용05. OOP객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그래밍 패러다임 중 하나로, 현실 세계의 개념과 개체들을 프로그램의 구조로 모델링하는 방식입니다. OOP는 코드의 재사용성, 유지보수성, 확장성 등을 향상시킬 수 있는 다양한 개념과 기법을 제공합니다.OOP의 주요 개념은 다음과 같습니다:클래스(Class):클래스는 객체를 생성하기 위한 설계도 또는 템플릿으로, 속성(멤버 변수)과 동작(메서드)을 포함합니다.예를 들어, '사람' 클래스는 '이름'과 '나이'라는 속성을 가지고 '인사하기'라는 동작을 수행할 수 있습니다.객체(Object):클래스의 인스턴스로, 실제로 메모리에 할당된 개체입니다.객체는 클래스에서 정의한 속성과 동작을 가지며, 각각의 객체는 독립적인 상태를 유지합니다.'사람' 클래스의 객체로는 '철수'나 '영희' 등이 있을 수 있습니다.상속(Inheritance):상속은 클래스 간의 계층 구조를 구성하여 코드의 재사용성을 높이는 개념입니다.부모 클래스(상위 클래스)의 속성과 동작을 자식 클래스(하위 클래스)가 물려받아 사용할 수 있습니다.상속을 통해 일반적인 기능을 가진 부모 클래스를 정의하고, 이를 기반으로 특화된 자식 클래스를 만들 수 있습니다.다형성(Polymorphism):다형성은 동일한 메서드를 다양한 방식으로 호출할 수 있는 개념입니다.하나의 메서드가 다른 클래스의 객체에 따라 다른 동작을 수행할 수 있습니다.다형성은 상속과 함께 사용되어 코드의 유연성과 확장성을 높여줍니다.캡슐화(Encapsulation):캡슐화는 관련된 속성과 동작을 하나의 단위로 묶는 개념입니다.클래스는 내부의 속성과 동작을 외부로부터 숨기고, 외부에서는 제공된 인터페이스를 통해 클래스와 상호작용합니다.캡슐화는 데이터의 은닉과 코드의 모듈화를 가능하게 합니다.06. 비동기[ 동기 비동기 ]동기(Synchronous)는 작업을 순차적으로 실행하고, 이전 작업이 완료될 때까지 다음 작업을 실행하지 않는 방식입니다. 작업이 순서대로 진행되기 때문에 실행 순서가 보장되며, 결과를 예측하기 쉽습니다. 하지만 작업이 완료될 때까지 대기해야 하므로 다른 작업을 처리하는 동안 시간이 지체될 수 있습니다.비동기(Asynchronous)는 작업을 동시에 실행하고, 이전 작업의 완료 여부와 상관없이 다음 작업을 실행하는 방식입니다. 작업이 백그라운드에서 동시에 처리되기 때문에 실행 순서가 보장되지 않을 수 있습니다. 비동기 방식은 작업이 완료되기를 기다리지 않고 다른 작업을 처리할 수 있으므로 시간을 효율적으로 활용할 수 있습니다.07. Iterator, Generator[ Symbol ]Symbol(심볼)은 ECMAScript 6에서 추가된 원시 데이터 타입입니다. 심볼은 고유하고 변경 불가능한 값으로, 주로 객체의 속성 키로 사용됩니다. 심볼은 Symbol() 함수를 통해 생성되며, 생성된 심볼은 다른 심볼과 절대로 동일하지 않습니다.심볼은 유일성과 불변성을 보장하기 때문에 객체의 속성 키로 사용하면 충돌을 방지하고 예상치 못한 동작을 방지할 수 있습니다. 또한, 심볼은 접근할 수 없는 외부에서 속성을 덮어쓸 위험을 줄여줍니다. 예를 들어, 두 개의 객체가 동일한 심볼을 속성 키로 사용하더라도 실제로는 서로 다른 속성을 가지게 됩니다.[ Iterator ]Iterator(이터레이터)는 JavaScript의 내장 프로토콜 중 하나로, 반복 가능한 객체(Iterable)에서 요소를 차례대로 가져오는 방법을 제공하는 인터페이스입니다. 이터레이터는 next() 메서드를 사용하여 다음 요소를 반환하고, { value, done } 형태의 객체로 값을 전달합니다. value에는 다음 요소의 값이 들어있고, done은 이터레이터가 더 이상 요소를 가지고 있지 않을 때 true가 됩니다. Symbol.iterator 메서드를 사용하여 이터레이터를 반환하는 것이 일반적입니다.[ Generator ]Generator(제너레이터)는 이터레이터를 생성하는 함수입니다. 제너레이터 함수는 function* 키워드로 정의되며, 함수 내부에서 yield 키워드를 사용하여 값을 반환하고 일시적으로 실행을 중지하며, next() 메서드를 호출함으로써 다시 시작할 수 있습니다. 제너레이터 함수를 호출하면 제너레이터 객체가 반환되며, 이 객체는 이터레이터 프로토콜을 따르기 때문에 next() 메서드를 사용하여 값을 가져올 수 있습니다. 08. Design Pattern디자인 패턴의 장점재사용성과 유지보수성 향상코드 가독성과 이해도 향상소프트웨어의 확장성과 유연성설계의 일관성과 표준화문제 해결 과정의 가속화Singleton Pattern: 특정 클래스의 인스턴스를 전역에서 하나만 생성하고 접근할 수 있도록 하는 디자인 패턴입니다.Factory Pattern: 객체를 생성하는 인터페이스를 정의하고, 이를 서브 클래스에서 구현하여 객체 생성을 캡슐화하는 디자인 패턴입니다.Mediator Pattern: 객체들 간의 상호작용을 중재하는 중재자 객체를 도입하여 결합도를 낮추고, 객체 간의 직접적인 통신을 제어하는 디자인 패턴입니다.Observer Pattern: 한 객체의 상태 변화에 따라 다른 객체들에게 자동으로 변화를 알리고, 그에 따른 처리를 할 수 있도록 하는 디자인 패턴입니다.Module Pattern: 모듈화된 코드를 구성하여 캡슐화하고, 필요한 부분만 노출시키며 코드의 재사용성과 유지보수성을 향상시키는 디자인 패턴입니다. 느낀점 및 각오자바스크립트의 중요성에 대하여 다시 한 번 크게 느낄 수 있었던 1주차였습니다. 자바스크립트 지식을 탄탄히 쌓고 배운 것들을 항상 이해하고 프로젝트에 적용까지 하며 기초를 상시 이해하며 면접준비까지 탄탄하게 해야겠다는 생각이 들었습니다. 남은 기간 동안에도 과제 수행을 열심히하며 저의 성장을 위해 최선을 다해보겠습니다! 감사합니다.

웹 개발FE워밍업클럽