블로그
전체 9#카테고리
- 웹 개발
#태그
- 인프런
- 워밍업클럽
- FE
- 1기
- 발자국
- 과제
2024. 05. 18.
0
인프런 워밍업 클럽 스터디 1기 FE - 3주차 발자국
짧지만 알찼던 3주간의 인프런 워밍업클럽 스터디 1기가 끝났다. 강의는 전부 수강완료했고, 과제는 1~10번까지 수행했다. 좋았던 점작년에 부트캠프를 참여하면서 자바스크립트를 공부한지 꽤 시간이 지났는데, 이후로는 주로 React.js나 타입스크립트, Next.js에 관심을 가지느라 오랜만에 다시 복습하게 되었다. 스터디에 참여하지 않았다면 진득히 다시 공부하기 어려웠을 것 같다. 그래도 스터디 이전에 모던자바스크립트 딥다이브 책을 읽어봤던 것이 강의를 이해하는 데에 큰 도움이 되어서 효과적으로 공부가 된 것 같다.스터디에서 과제의 완성 코드를 알려주지 않은 것이 제일 좋았다. 정답이 있는 코드가 없다는 말처럼 정답은 없고 영상만 보고 직접 고민해보고 기능을 구현했던 것이 너무 재밌었다. 정답 코드가 있었더라면 더 고민해보지 않았을 수도 있었을 것이다. (난 멍청이야..하면서) 다른 러너분들의 블로그에서 어떻게 구현했는지 살펴보며 깨달은 것들도 많았다. (다들 너무 멋져요)아쉬웠던 점강의를 수강하느라 목표였던 과제 모두 뿌시기는 성공하지 못했다. 총 14개의 과제 중에 자바스트립트 과제 7개, React.js 과제 3개를 만들어 10개를 수행했다. 막판 과제였던 4개의 리덕스와 Next.js 과제는 하지 못했는데, 그래도 열심히 했기 때문에 후회는 없다! 스터디는 끝이 났지만 5월이 다 끝나기 전에 나머지 과제도 마저 완성해보려 한다.강의를 듣고 스스로 고민하며 과제를 해본 것은 좋았지만, 그만큼 혼자 고민하는 것이 힘들기도 했다. 내 코드를 보고 다같이 씹고 뜯어줄 장이 필요했던 것 같다. 다음 기회에 용기를 내어서 같이 서로 코드를 구경하고 얘기해 줄 수 있는 환경을 만들어보거나 뛰어들어야겠다고 생각했다.보완할 점어떤 프로젝트를 만들고 싶다는 생각만 하고 행동하는 데에 시동이 오래 걸렸었다. 이번 스터디가 워밍업인 만큼, 행동에 옮기는데 많이 데워진 것 같다. 비슷한 스터디를 운영하거나 혼자서라도 계속 해보려한다. 보완할 점은 과제에 집중하느라 조금 설렁하게 들었던 강의 몇개를 다시 들어보고 내 것으로 만들고 싶다. 수행했던 과제들을 리팩토링까진 아니어도 다른 방식으로 구현할 수 있을지 생각해보는 시간도 가지고 싶다. 시간상 리액트 과제를 전부 JS로 했었는데, TS로 마이그레이션 해봐야겠다.
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
발자국
2024. 05. 16.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(10번 과제)
[10번 과제(Day11) - 포켓몬 도감 앱]따라하며 배우는 리액트 A-Z학습 범위: Section 6 ~ 7https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/pokedex-app과제 이미지알게된 것 (String, Array 타입에서의 includes 메서드)String메인페이지에서 검색어를 입력할 때, 검색어가 포함된 객체들로 이루어진 배열을 따로 searchResults 라는 상태로 저장해주었다. 이 searchResults 상태를 연관검색어로 노출시키기 위함이었다.pokemonList 배열에서 검색어(searchInput)가 포함된 name을 가진 객체만 모아서(배열을 필터링해) 반환해주는 filter, includes 메서드를 사용했다. 여기서 사용한 includes 메서드의 pokemon.name 는 String 타입이다.따라서 'h' 라는 검색어를 입력했을때, 객체의 name 문자열 중에 'h'가 부분으로 포함된 객체들도 가져올 수 있다. // Main Page // 포켓몬 이름(string)에 검색input이 포함된 것만 필터해서 반환 const matched = pokemonList.filter( (pokemon) => pokemon.name.includes(searchInput) // true인 객체들만 반환 ); // 검색input값이 있을 때에만 검색 결과 배열에 저장 if (searchInput) { setSearchResults(matched); } // String.prototype.includes const sentence = 'The quick brown fox jumps over the lazy dog.'; console.log(sentence.includes('quick')); // true console.log(sentence.includes('h')); // true console.log(sentence.includes('Quick')); // false, 대소문자 구분Array연관 검색어 배열에서 특정 검색어를 클릭 했을 때, 검색 input에는 선택된 특정 검색어를 value로 가지고, 연관 검색어 요소를 사라지게하는 기능을 구현하고자했다.선택된 특정 검색어가 searchInput가 되었을 때, 연관 검색어 배열에도 동일한 검색어를 가진다. (검색어 입력 시 필터링되게 했음으로)검색 input의 현재 value(searchInput)와 연관 검색어 목록이 정확히 동일하다면 연관 검색어를 보여주는 요소를 사라지게 하면 되었다. 연관 검색어 배열(searchResults)의 객체를 name 키만 가진 문자열 배열로 만들어 준 후(map 메서드), Array의 includes 메서드를 사용했다.따라서 'pikachu' 라는 검색어를 클릭했을때, 배열의 요소 중에 정확히 'pikachu'가 있다면 true를 반환한다.// SearchBar // 검색input 값이 검색 이름(array)에 포함된 경우 true일 때 (정확히 같아야 함) if (searchResults.map((result) => result.name).includes(searchInput)) { setSearchShow(false); // 연관 검색 숨기기 } // Array.prototype.includes const fruits = ['apple', 'banana', 'mango']; console.log(fruits.includes('banana')); // true console.log(fruits.includes('ba')); // false 정리하자면,타입 차이 Array.prototype.includes는 배열의 요소를 찾기 위해 사용된다.String.prototype.includes는 문자열 내의 부분 문자열을 찾기 위해 사용된다.비교 방식배열에서는 엄격한 동등성(===) 비교를 사용한다.문자열에서는 대소문자를 구분하는 포함 여부를 확인한다.
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제
2024. 05. 16.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(9번 과제)
[9번 과제(Day10) - 디즈니 플러스 앱]따라하며 배우는 리액트 A-Z학습 범위: Section 4 ~ 5https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/disney-plus-app과제 이미지- 구글 로그인, swiper, 모달- 유튜브 플레이, 검색, 상세페이지, 로그아웃고민한 것MovieModal mount될 때에는 애니메이션이 되고, unmount될 때에는 애니메이션 없이 툭 사라져버린다.내가 원하는 것은 모달이 꺼질때에도 애니메이션으로 사라지게 한 후, unmount되게 하는 것기존 코드// Row 컴포넌트 modalOpen && 이전 코드에서는 modalOpen 상태가 참일 때만 MovieModal이 렌더링되었지만, 변경된 코드에서는 MovieModal 컴포넌트 내부에서 직접적으로 modalOpen 상태를 조작할 수 있도록 했다.변경 코드 // Row 컴포넌트 // MovieModal 컴포넌트 const MovieModal = ({ ... modalOpen, setModalOpen, }) => { const ref = useRef(); const [showModal, setShowModal] = useState(false); const [animation, setAnimation] = useState(""); useOnClickOutside(ref, () => { // 2. 닫기 이벤트 setModalOpen(false); }); useEffect(() => { if (!modalOpen) { // 4. 사라지는 애니메이션으로 설정 setAnimation("animate-fade-down animate-reverse"); } else { setShowModal(true); setTimeout(() => { // 1. 나타나는 애니메이션으로 설정 setAnimation("animate-fade-up"); }, 10); } }, [modalOpen]); return ( showModal && ( { // 3. 사라지는 애니메이션 끝이나면 showModal false if (!modalOpen) setShowModal(false); }} > ) ) };MovieModal 컴포넌트 내부에서는 modalOpen 상태에 따라 모달의 나타남과 사라짐을 제어하는 useEffect와 useState를 사용했다.modalOpen 상태가 변경될 때마다 useEffect가 실행되어 애니메이션 클래스를 설정하고, 애니메이션 효과를 주는 CSS 클래스를 적용시킨다.onAnimationEnd 이벤트 핸들러를 사용하여 애니메이션 종료 후에 showModal 상태를 변경하여 모달이 화면에서 완전히 사라지도록 처리했다. 추가한 것tailwind css + 스크롤바 숨기는 플러그인, 애니메이션 플러그인/** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{js,jsx,ts,tsx}"], theme: { extend: {}, }, plugins: [ require("tailwind-scrollbar-hide"), require("tailwindcss-animated"), ], };회원만 접근 가능한 parent 컴포넌트 생성const UserGuard = () => { const navigate = useNavigate(); useEffect(() => { const profilePictureUrl = localStorage.getItem("profilePictureUrl"); // 로그인 시 저장한 구글 유저 프로필이미지가 없다면 LandingPage로 이동 if (!profilePictureUrl) { navigate("/"); } }, [navigate]); return ; }; export default UserGuard; function App() { return ( }> } /> 👇 }> } /> } /> } /> ); } export default App;로그인 상태일 때 랜딩 페이지 접근 불가const LandingPage = () => { const navigate = useNavigate(); useEffect(() => { const profilePictureUrl = localStorage.getItem("profilePictureUrl"); // 로그인 시 저장한 구글 유저 프로필이미지가 있다면 MainPage로 이동 if (profilePictureUrl) { navigate("/main"); } }, [navigate]); return (...) };
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제
2024. 05. 12.
0
인프런 워밍업 클럽 스터디 1기 FE - 2주차 발자국
The four Ls 🍀좋았던 것(Liked)성공적으로 진행된 부분이나 긍정적인 경험스터디 과제로 책 리스트 나열, 깃헙 파인더, 비밀번호 생성기, 타이핑 테스트 앱을 바닐라JS로 만들었고, 예산 계산기 앱을 React.js로 만들었다. 모든 과제를 클리어해보는 것이 목표 중 하나인데 이번 주에 총 5개의 과제를 완성시켜서 뿌듯했다. 배운 것(Learned)새로운 지식, 기술 또는 교훈이전에도 항상 헷갈리고 어떻게 사용해야할지 가늠이 되지않았던 최적화 부분을 여러번 학습했다.섹션3의 React.memo 를 이용한 렌더링 최적화,useCallback 을 이용한 함수 최적화,useMemo를 이용한 결과 값 최적화그 중에서 useCallback과 useMemo의 차이점은 알지만 활용하는 부분이 어렵다고 느껴졌는데, 이번 강의를 통해서 useCallback을 이해하며 과제에 적용해보았다. 부모 컴포넌트가 리렌더링될 때마다 함수가 재생성되면, 해당 함수가 자식 컴포넌트의 props로 전달되면서 자식 컴포넌트도 다시 리렌더링될 수 있다.따라서 useCallback을 사용하면 함수의 재생성을 방지하여 이러한 문제를 해결할 수 있고, 이를 통해 자식 컴포넌트의 불필요한 리렌더링을 최적화할 수 있다.부족했던 것(Lacked)부족한 정보, 기술 등 파악하고 개선할 수 있는 방안과제를 하느라 React.js강의의 Todo앱 class 컴포넌트에서 함수 컴포넌트로 변경하는 것과 드래그앤드랍 기능 부분을 실습해보지 못했는데, 추후에 실습해보려고 한다. (+ Hooks와 불변성 개념 복습해보기) 눈으로 봤을 때보다 직접 작성해보면서 느껴보는 것이 개인적으로 기억에 잘 남을 것 같다. 과제 기록을 하면서 그냥 GIF 이미지와 깃헙 링크만 올렸었는데, 작업하면서 생각했던 것들을 추가 작성해두었다. 큰 작업은 아니지만 어떤 점을 신경쓰면서 임했는지 다시 보면 좋을 듯 하다.바라는 것(Longed for)미래에 개선되었으면 하는 부분이나 바라는 상황앞으로 남은 강의도 집중해서 듣고, 남은 과제도 차근차근 해보도록 하겠다! 특히 경험해보지 않은 TDD 실습과 도커에 신경쓰며 들어보려고 한다. 화이팅!
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
발자국
2024. 05. 12.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(8번 과제)
[8번 과제(Day9) - 예산 계산기 앱]따라하며 배우는 리액트 A-Z학습 범위: Section 1 ~ 3https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/budget-calculator-app과제 이미지localStorage로 예산 리스트 데이터를 저장할 수 있도록 했다.useEffect의 의존성배열에 listData를 넣어서 리스트가 변경(추가,수정,삭제)될 때마다 localStorage.setItem으로 저장할 수 있게 했다.useMemo를 활용해 listData가 변경될 때만 result (총 지출금액)값을 다시 계산하도록 하였다.App 최상위 컴포넌트의 state현재 데이터, 데이터 리스트(array), 수정 모드(boolean), 알림(array)useCallback를 활용해 자식 컴포넌트의 props로 설정한 함수들의 불필요한 함수 재생성을 방지하고 자식 컴포넌트의 리렌더링을 최적화했다. Form의 handleSubmit, ListGroup의 handleEditMode, handleDelete함수 빠른 스타일링을 위해 tailwind css를 사용했다.
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제
2024. 05. 10.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(7번 과제)
[7번 과제(Day7) - 타이핑 테스트 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 9https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/typing-test-app과제 이미지자바스크립트 과제 중에 제일 어려웠다. CPM, WPM 계산이 잘 맞는지 모르겠고.. 이 로직이 맞나? 자신이 없다.타이머 기능 먼저 작업하고 그다음에 타이핑, 상태 순서대로 했는데 아직도 먼저 고민해보고 코드를 적는 연습이 부족한 듯 하다. 마음이 급해서 ㅎㅎ 대략 정해놓고 바로 작업하는 편인데 로직을 한번 먼저 메모장 켜놓고 큰 그림과 작은 목표들을 메모하는 습관을 길러야겠다.뭐든 함수에 몽땅 넣어버린 것 같다. 액션, 계산, 데이터를 분리해보는 걸 이 코드로 시도해봐야겠다!
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제
2024. 05. 07.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(4번, 5번, 6번 과제)
[4번 과제(Day5) - 책 리스트 나열 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 5 ~ 6https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/book-list-app과제 이미지input 전체에 값의 유무에 따라 submit 버튼 활성화를 설정해줘서 정확한 제출 요청이 되도록 작업했다.setTimeout으로 추가, 삭제 알림이 3초 뒤에 사라지게 했다.리스트 그룹에 이벤트리스너를 설정해줘서 이벤트타겟의 태그가 버튼이라면 삭제버튼을 가진 부모요소를 삭제하도록 이벤트 위임으로 작업했다.[5번 과제(Day5) - Github Finder 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 5 ~ 6https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/github-finder-app과제 이미지import { Octokit } from "https://esm.sh/@octokit/core";위 스크립트를 import를 작동시키기위해서 html에 작성한 script태그에 type을 module로 설정하였다.유저의 프로필 정보는 고정적이라 값만 제외하고 퍼블리싱했고, 레포지토리 리스트는 script에서 innerHTML으로 한번에 삽입했다. li 태그를 계속 create하는 것보다 효율적이라고 생각했다.!username && alert("유저 이름을 입력해주세요."); // 변경 전 if (!username) return alert("유저 이름을 입력해주세요."); // 변경 후둘 다 username가 비어있거나 존재하지않을 때에만 조건이 참이 된다.변경 전 usename이 빈 칸일 경우 알림창이 뜨도록 조건식을 작성했는데, 알림창을 한번 나타나게하면 조건식이 끝나도 함수를 이어서 실행시켰다.내가 원하는 건 조건이 참이면 함수를 중지하는 로직을 원하기때문에 return문이 들어갈 수 있도록 조건식을 조건문으로 변경하였다.식과 문을 잘 구별해서 쓰자.[6번 과제(Day6) - 비밀번호 생성 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 7 ~ 8https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/password-generator-app과제 이미지비밀번호를 생성하는 generator 객체를 활용해보았다.generator 안에 아래 작성된 최소, 최대 길이에 맞게 참이 될때만 실행하도록 while 조건문을 설정했다.navigator.clipboard로 복사하기 기능을 구현했다.generator를 이번 강의에서 처음 배우고 사용해봤는데 목적에 맞게 가독성이 좋아보여서 흥미로웠다. 하지만 generator로 구현하는 것과 일반 함수로 구현하는 것의 차이를 아직은 잘 모르겠다.
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제
2024. 05. 05.
0
인프런 워밍업 클럽 스터디 1기 FE - 1주차 발자국
The four Fs 🍀FACTS (사실, 객관)이번 일주일 동안 있었던 일, 내가 한 일인프런 워밍업 클럽 스터디 1기를 시작했다. 1:1 멘토링권과 인프콘 초대권이 너무나 탐났기에 우수러너를 목표로 JavaScript 강의를 시작했다.스터디를 시작하면서 Firebase, React.js로 채팅앱 만들기 강의도 듣고 있다. 강의의 기술스택을 활용하여 React Query와 함께 해결할 새로운 개인 프로젝트를 생각해두고 있다.스터디 과제로 음식메뉴, 가위바위보, 퀴즈 앱을 바닐라JS로 만들었다.프론트엔드 개발직무로 이력서를 꾸준히 지원하고 있는데, 아직 연락은 없었다..😢FEELINGS (느낌, 주관)나의 감정적인 반응, 느낌, 어려움생각했던 것보다 스터디에 쏟는 시간이 길어서 2주차 때에는 시간관리에 더 신경써야겠다고 느꼈다.올해 초에 모던자바스크립트 딥다이브 책으로 한번 1독을 해서 그런지 호이스팅, 스코프, 프로토타입 섹션은 힘들지않게 이해했다. (과거의 나.. 칭찬해..)과제로 DOM 메서드 사용하며 작업했는데 거의 1년만에 사용하다보니 낯설었고, 기능을 만들 때 배열이나 객체의 어떤 프로토타입 메서드를 사용하는게 나을지 고민하는 것이 재밌었다. + 코딩테스트 문제를 푸는 기분도 들었다. FINDINGS (배운 것)그 상황으로부터 내가 배운 것, 얻은 것, 가장 인상 깊었던 배움기억에 남는 배움으로는 this와 this를 바인딩하는 bind, call, apply 메서드, 이벤트 위임이었다. 특히 이벤트 위임은 과제를 하면서 바로 바로 적용시켰기 때문에 앞으로도 잘 활용할 것 같다.복습하고 싶은 배움으로는 Design Pattern, Intersection observer, 커링이었다. 특히 Intersection observer로 lazy loading을 구현할 수 있다는 걸 이번에 알았기 때문에 더 기억에 남을 것 같다. 커링은 문법으로는 봤었지만 어떤 용어로 부르는지 몰라서 궁금증이 해소되었다.과제를 통해 DOM Node를 직접 변수로 설정하고 값을 바꾸고 업데이트하는 작업을 했는데, 첫 설계의 중요성을 알게되었다. 마음이 급해 기능을 위한 코드를 작성하다가 요소의 위치를 다시 설정해야하는 순간이 있었다. 기능도 중요하지만, 기능을 적용시킬 요소들을 어떻게 배치하고 설계해야할지 처음부터 잘 고민을 해야겠다고 느꼈다.FUTURE (미래)현재 나의 상태와 배운 것을 미래에는 어떻게 적용할 지이번 주가 끝나면 다시 React.js를 공부하게 될텐데, 이번 기회에 모국어(JavaScript)를 복습하게 되어서 좋았다. 이번 주에 배웠던 부분을 곰곰이 복기해보면서 아직 끝내지 못한 나머지 과제들에 녹여보도록 하겠다.2주차에는 강의를 빠르게 보고, 과제를 하며 고민하는 데에 시간을 더 써보는 연습을 해야겠다. 화이팅!
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
발자국
2024. 05. 01.
0
인프런 워밍업 클럽 스터디 1기 FE 과제(1번, 2번, 3번 과제)
[1번 과제(Day2) - 음식 메뉴 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 1 ~ 3https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/food-menu-app과제 이미지데이터를 json파일로 만들어놓고 처음 로드할 때, 불러와서 작업했다.강의에서 배운 이벤트위임을 활용해서 버튼 그룹에 이벤트리스너를 설정해주고 이벤트타겟의 태그가 버튼일 때에만 메뉴를 필터링할 수 있는 함수를 실행하게 했다.[2번 과제(Day3) - 가위 바위 보 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 4(1~8)https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/rock-scissors-paper-app과제 이미지남은 횟수가 끝나면 결과를 알려주는 부분을 잊고 완성했다가 다시 이어서 작업했다.다시 도전하기를 누를때 화면을 초기화하는 함수를 만들었다.[3번 과제(Day4) - 퀴즈 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 4(9~17)https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/js-quiz-app과제 이미지1번 처럼 데이터를 json파일로 만들어놓고 처음 로드할 때, fetch로 불러와서 작업했는데 데이터 객체 안에 문제와 옵션들, 그리고 answer(정답) 키값을 넣었었다. 하지만 브라우저 네트워크에 답까지 노출이 되는 게 문제라고 생각됐다.그래서 answer(정답) 키값을 없애고, 문제와 옵션들만 데이터로 구성하고 script 안에서 정답 유무를 가릴 수 있게 바꿨다. 풀이는 문제를 배열로 해체하고 ×를 *으로, ÷를 /으로 바꾼 후(-,+는 그대로) eval()함수를 쓰지않고 new Function() 새로운 함수를 생성해서 풀이하게 했다.
웹 개발
・
인프런
・
워밍업클럽
・
FE
・
1기
・
과제