2junsu의 등록된 링크

 2junsu로 등록된 티스토리 포스트 수는 72건입니다.

[취업] LG전자 취준 후기 [내부링크]

이번에는 LG전자 취업 준비 후기를 작성해보겠습니다! 채용 프로세스 저는 HE사업본부 SW직무에 지원했고, 채용 과정은 아래와 같습니다. 서류 전형 -> 인적성 검사 -> 코딩테스트 -> 1차면접 -> 2차면접 특이한 점은 서류 전형에서 합격을 받아도 이후 인적성 검사와 코딩테스트 결과를 합쳐서 다시 한 번 서류를 검토한다는 거예요. 그래서 저도 서류 전형 합격 소식을 2번 받았었네요! 서류 전형 자소서 문항은 총 3개였습니다. LG전자 지원동기 직무관련 향후 계획 프로젝트 경험 저는 LG전자 외에도 LG그룹 내 여러 계열사들에 지원했었는데요, LG그룹은 대체로 문항 수가 적고, 무난한 질문들이 많았습니다. 지원동기는 LG전자가 현재 나아가고자 하는 방향과 저의 경험을 연관지어 작성했습니다. 직무관련 향..

[취업] 농협정보시스템 취준 후기 [내부링크]

농협정보시스템에 지원했다가 면접에서 떨어진 후기를 작성해볼게요ㅋ 채용 프로세스 채용 과정은 3가지로 구성되어 있습니다. 서류 전형 및 1차 인적성 -> 코딩 테스트 및 필기 시험 -> 원데이 면접 특이한 점은 인적성을 2번 본다는 점이었네요! 서류 전형 자소서 자소서 문항은 총 4개였습니다. 성격의 장단점 IT 보유 역량 성공 및 실패 경험 지원 동기 및 입사 후 포부 다른 기업들과 마찬가지로 무난무난한 질문들이었고, 특히 4번 문항에서는 농협정보시스템이 개발한 서비스를 언급하면서 내가 회사에 기여하고 싶은 부분과 연관지어 작성했습니다. 4개의 문항 모두 500자 이내로 작성해야 해서 글자수를 줄이는 게 일이었던 기억이 있네요. 자소서를 써보기 전에는 글자수가 적은 게 좋은 건줄 알았는데, 정확히 반대였..

[취업] 뷰웍스 최종 합격 후기 [내부링크]

뷰웍스 취업을 준비하시는 분들을 위한 간단한 합격 후기를 작성해보겠습니다! 채용 프로세스 채용 과정은 3가지로 구성되어 있습니다. 서류 전형 -> 역량 테스트 -> 원데이 면접 서류 전형 우선 저는 1지망에 SW개발, 2지망에 개발QA에 지원했습니다. 다른 기업들과 다르게 뷰웍스의 자소서는 간단했습니다. 자신의 역량을 20,000자 이내로 작성하는 문항만이 있었습니다. 사실 다른 기업 자소서에 썼던 가치관과 필살기 경험들을 복붙하는 느낌으로 작성해서 그리 오랜 시간이 걸리지 않았던 것으로 기억해요ㅋㅋ 저는 3,300자 정도 작성했었네요! 그래서 큰 기대를 하지 않았었는데, 서류 합격을 하게 되어 기뻤습니다ㅎㅎ (발표일이 아마 금요일이어서 다른 기업들 광탈했던 걸 이거로 위로 삼았던 기억ㅋ) 역량 테스트 ..

[취업] 하나은행 디지털 최종 합격 후기 [내부링크]

정말 운이 좋게도 첫 취준에 최종 합격 소식을 받게 되었습니다!! 하나은행 입행을 목표로 하시는 미래의 후배 분들을 위해 솔직한 후기를 남기고자 합니다! 채용 프로세스 채용 과정은 크게 4가지로 구성되어 있습니다. 서류 전형 -> 코딩 테스트 -> 실무진 면접 -> 최종 면접 서류 전형 저는 주로 면접왕 이형 유튜브를 참고하면서 작성했습니다. 필살기 경험들에 대해서 본인이 어떤 액션을 취했고, 이를 통해 배운 점과 이러한 역량을 당행에 어떻게 기여할지에 대해 작성했습니다. 또한, 하나은행 내에 시행되고 있는 여러 제도들을 알아보면서 입행 후에 어떻게 성장할 것인지를 생각해 봤습니다. 사실 전 자소서 첨삭을 따로 받지 않았는데, 지금 생각해 보면 무슨 생각으로 그랬는지... 용감했던 것 같네요 면접왕 이형..

[SQL] 주요 문법 1 (feat.Oracle) [내부링크]

프로그래머스에서 SQL 문제를 몇 개 풀어보면서 되새겨본 주요 문법을 정리하고자 한다. 이번 글에서는 아래 5가지 문법에 대해 알아보자! LIKE TO_CHAR NOT IS NULL ROWNUM LIKE 부분적으로 일치하는 컬럼을 찾을 때 사용된다. 크게 2가지로 구성된다. _ : 글자 수를 정해준다. % : 글자 수를 정해주지 않는다. 몇 가지 예시를 살펴보자. -- '인천'으로 시작하는 주소 SELECT ADDRESS FROM FOOD_FACTORY WHERE ADDRESS LIKE '인천%' -- '송도동'으로 끝나는 주소 SELECT ADDRESS FROM FOOD_FACTORY WHERE ADDRESS LIKE '%송도동' -- '서울'을 포함하는 주소 SELECT ADDRESS FROM FO..

[SQL] JOIN ~ ON과 WHERE의 차이 [내부링크]

우선, 내가 SQL문을 작성하는 환경은 Oracle이다. 따라서 조인의 종류를 명시하지 않고 그냥 JOIN이라고 작성하면 INNER JOIN을 의미한다. 하나 이상의 테이블이 있으면 이를 조인해서 사용한다. 이때 ON에 조건을 작성한다. 프로그래머스의 과일로 만든 아이스크림 고르기 문제를 통해 되새겼다. 결론적으로 아이스크림의 맛을 조회해야 한다. 이때 조건에서 확인해야 하는 필드는 총주문량, 주성분인데 이 두 필드는 각각 다른 테이블에 존재하므로 두 테이블을 조인해야한다. 두 테이블에서 겹치는 필드는 FLAVOR이므로 ON에는 두 테이블의 FLAVOR가 같다는 조건을 설정해야 한다. 이외 나머지 조건을 적용하면 아래와 같다. SELECT F.FLAVOR FROM FIRST_HALF F JOIN ICEC..

[SQL] ORDER BY [내부링크]

SQL에서 손을 놓은지 2년이 넘어버려서 정말 다 까먹었다.. 프로그래머스 SQL 문제들을 풀면서 다시 감을 잡고 있다. ORDER BY 순서를 정렬하는 키워드이다. default 값은 ASC(오름차순)이라서 명시하지 않아도 된다. 내림차순은 DESC를 명시해야 한다. 프로그래머스의 인기있는 아이스크림 문제를 풀며 되새겨본 개념이다. 결론적으로 FIRST_HALF 테이블에서 아이스크림의 맛 FLAVOR를 조회한다. 이때 총주문량을 기준으로 내림차순 정렬하고 총주문량이 같다면 출하 번호를 기준으로 오름차순 정렬하므로 SQL문은 아래와 같다. SELECT FLAVOR FROM FIRST_HALF ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC;

[CSS] hover 시 숨겨진 메뉴 보이게 하기 (feat. styled-components) [내부링크]

이 글을 통해서 아래 메뉴를 구현할 수 있다. hover 시에는 컴포넌트가 보이도록, 벗어나면 다시 사라지도록 구현해야 한다. 우선 뼈대를 구성할 건데 styled-components를 사용하여 스타일링했다. 일정 커뮤니티 const MenuUl = styled.ul` list-style: none; display: flex; align-items: center; gap: 48px; position: relative; & span { cursor: pointer; } `; ul의 기본 스타일을 없애고, 메뉴 사이에 gap을 줬다. SubHeader는 각 메뉴에 마우스를 호버 하면 나타나는 서브 메뉴이다. 간단하게 아래와 같이 작성했다. const SubHeader = ({ tab }) => { const..

[Jest] png 파일 import error 해결하는 법 ( ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){PNG ) [내부링크]

테스트 코드를 작성 후 테스트 하던 중 위와 같은 에러를 겪었다. jest는 js나 jsx 이외의 확장자를 가진 파일을 불러올 수 없다. 따라서 png 파일 또한 불러올 수 없다. 이와 관련해서 많이 찾아보고 많은 방법을 시도해 봤다. 실제 이미지를 불러오지 않고 mocking file을 불러오도록 fileMock.js 파일을 생성해 봤고 identity-obj-proxy라는 라이브러리도 설치해 봤는데, 해결되지 않았다. 내 에러를 해결해 준 것은 jest-transform-stub이라는 라이브러리였다! jest는 기본적으로 non JavaScript asset을 다룰 수 없는데, 이 라이브러리를 설치하면 이로 인해 발생하는 에러를 피할 수 있을 것이다. 문서에 위와 같이 적혀 있는데, 내 에러를 해결해..

[Jest] 내가 겪었던 svg 파일과 관련된 error들 [내부링크]

이번에 사이드 프로젝트를 진행하면서 jest와 react-testing-library를 사용하여 테스트 코드를 작성하는 연습을 해보고 있다. 그중에서 svg 파일과 관련해서 내가 겪었던 에러들을 정리하고자 한다. 첫 번째 에러 이 에러는 jest와 관련된 것은 아니다. 그러나 Vite 기반의 React로 개발을 진행하고 있다면 알고 있어야 한다. svg와 관련한 첫 번째 에러는 vite 환경에서 svg를 사용하기 위한 설정을 하지 않아서 발생했었다. 이때는 vite-plugin-svgr이라는 라이브러리를 설치하여 해결했었다. // vite.config.js ... import svgr from "vite-plugin-svgr"; ... export default ({ mode }) => { ... ret..

[CSS] checkbox input 커스텀 하기 [내부링크]

사이드 프로젝트를 하다가 아래처럼 예쁜 체크박스를 구현할 일이 생겼다. 사실 예전에 React-Native에서도 비슷하게 체크박스 커스텀을 했었는데, 그 당시에는 button으로 구현했었다. CheckBox 컴포넌트가 있던데 왜 안 썼을까.. 그래서 이번에는 다른 방법으로 구현해보고자 했다. 우선 기본 틀을 잡았다. 기본 아이디어는 다음과 같다. input을 숨기고, label로 input 값을 컨트롤한다. 이때 전체를 label로 감싸서 텍스트 클릭으로도 컨트롤 할 수 있도록 한다. input 값의 변화에 따라 div 스타일이 달라진다. style 파일에는 기본적인 스타일링과 특히 input이 체크되었을 때와 아닐 때의 div 스타일을 정의한다. 이렇게 하면 아래와 같이 예쁜 커스텀 체크박스가 완성된다!

[ESLint] import 순서 자동 정렬하기 [내부링크]

올 상반기에 인턴으로 근무하면서 사내 코드 컨벤션에 의거하여 import 순서에 대해서 처음으로 신경 써봤다. 그러나 일일이 수작업으로 진행했던지라 가끔씩 지켜지지 않을 때도 있었고, 이런 경우 코드 리뷰 과정에서 수정하곤 했다. 이 부분에서 불편함을 느꼈기에 이번 사이드 프로젝트에서는 import 순서를 자동으로 정렬해 주는 Lint 설정을 직접 적용해 보자고 마음먹었다. 우선 eslint-plugin-import라는 라이브러리를 설치해야 한다. 이를 설치함으로써 import/export 구문에 대한 Lint를 지원한다. 문서를 확인해 보니 .eslintrc 파일에 추가 설정을 하라고 한다. extends: - eslint:recommended - plugin:import/recommended # al..

[ESLint] CR과 LF의 차이 | error Delete prettier/prettier in lint [내부링크]

lint 검사를 돌리던 중 아래 에러가 발생했다. 처음 보는 에러에 CR은 또 뭔지.. 바로 검색해봤다. 위는 요약하자면 Windows 환경에서 발생하는 에러이며, Windows와 Prettier의 줄 바꿈 방식이 달라서 발생한다. 원래 평소에는 Mac 환경에서 개발했었는데, 이번에는 집에 데스크탑이 있어서 Windows 환경에서 개발 중이었다. (최근에 최신형 맥북으로 업그레이드해서 다시 맥으로 개발할 예정 ㅎㅎ..) 두 OS는 각각 새로운 줄 바꿈을 하는 방식이 다르다. 줄 바꿈 방식에는 2가지가 있는데 아래와 같다. LF: Line Feed(\n) CR: Carriage Return(\r) 이는 과거에 타자기를 사용하던 시절에 줄바꿈을 위해 사용하던 방식이라고 한다. LF는 현재 커서의 위치를 유지..

[React] Element, Component, Instance의 차이 [내부링크]

이전 글에서 함수 컴포넌트는 인스턴스를 갖지 않기 때문에 ref가 존재하지 않는다고 잠깐 언급하였다. 이를 보고 인스턴스가 무엇인지, 그리고 컴포넌트와의 차이는 무엇인지가 궁금해져서 더 알아보았다. 또한 엘리먼트와도 함께 비교해보았다. Element 엘리먼트는 UI를 나타내기 위한 가장 작은 단위이다. 보통 일반 자바스크립트 객체(plain JavaScript object)로 표현되는데, 이는 type과 props 필드로 구성되며 아래와 같이 나타낸다. { type: "button", props: { className: "btn-style" } } 위 엘리먼트는 React의 JSX 문법을 통해 아래와 같이 표현된다. const element = Click; Component 컴포넌트는 특정 기능을 수행하..

[React] 함수 컴포넌트에 ref를 넘겨주고 싶다면? forwardRef()! [내부링크]

최근 합류한 사이드 프로젝트의 코드를 테스트하던 중 아래와 같은 Warning을 발견했다. Warning: Function components cannot be given refs. Did you mean to use React.forwardRef()? 함수 컴포넌트에는 ref가 존재하지 않는데, forwardRef()를 쓰려고 했던 것이 아니냐는 Warning이었다. 해당 부분 코드를 확인해보니 자식 컴포넌트에 쓰이는 ref를 부모 컴포넌트에서 관리하고 있었다. 대략적인 코드를 보자. // CalendarContainer.jsx (부모 컴포넌트) const CalendarContainer = ({ type }) => { const calendarRef = useRef(null); ... return (..

[Vite] vite.config.js에서 환경 변수 불러오기 [내부링크]

얼마 전에 사이드 프로젝트 팀에 중간 합류했다. 기존에는 로컬 서버를 띄워놓고 테스트를 해왔는데, 며칠 전에 서버 개발자 분께서 서버를 배포하셔서 이제 배포된 서버에서 테스트 할 수 있게 되었다. 코드를 살펴보니 이전 프론트 개발자 분께서 CORS 에러에 대해 proxy 설정으로 대응해놓으셨다. "/back": { target: "http://localhost:8000", changeOrigin: true, rewrite: (path) => path.replace(/^\/back/, ""), }, 이제 실서버 주소를 적어야 하는데, 노출 방지를 위해 .env 파일에 환경변수를 등록해놓고 이를 불러와서 아래와 같이 쓰고자 했다. "/back": { target: import.meta.env.VITE_API..

[JavaScript] 2차원 배열 중복 제거하기 [내부링크]

1차원 배열 내에서 중복된 원소를 제거하고 싶다면 Set을 사용하여 쉽게 구현할 수 있었다. const arr = [1, 1, 2]; const set = new Set(arr); const uniqueArr = [...set]; console.log(uniqueArr); // [1, 2] 그러나 2차원 배열에 적용해 본 결과, 의도한 대로 동작하지 않았다. const arr = [ [1, 2, 3], [1, 2, 3], [1, 3, 4], ]; const set = new Set(arr); const uniqueArr = [...set]; console.log(uniqueArr); // [ [ 1, 2, 3 ], [ 1, 2, 3 ], [ 1, 3, 4 ] ] -> 중복 제거 X 이때는 아래와 같이 배..

[JavaScript] 마우스로 버튼을 클릭할 때와 키보드로 버튼을 클릭할 때를 구분하는 방법 [내부링크]

같은 버튼을 클릭해도 마우스로 클릭할 때와 키보드로 클릭할 때 다르게 동작하도록 구현할 필요가 생겼다. 원래는 키보드를 눌렀을 때 useState()를 통해 boolean state로 관리하려고 했지만, 의도한 대로 동작하지 않았다. 이를 event 객체의 detail을 사용하여 해결했다. event.detail이란? event.detail은 특정 이벤트 내에서 마우스로 버튼을 누른 횟수를 나타낸다. 버튼이 한 번 눌렸다면 1, 더블 클릭을 했다면 2, 그 이상 다중 클릭을 했다면 해당 숫자만큼 표시된다. 아래 각 경우에 해당하는 예시를 보자. 위에서 언급했듯이 특정 이벤트 내에서 마우스로 버튼을 누른 횟수를 나타내기 때문에, 만약 키보드 동작으로 버튼을 클릭한다면 event.detail 값은 0이 나..

[JavaScript] forEach와 map의 차이 [내부링크]

forEach와 map 메서드는 둘다 배열 전체를 탐색한다는 공통점이 있다. 둘의 명백한 차이는 아래와 같다. let arr = [1, 2, 3]; let forEachArr = arr.forEach((d) => { return d * 2; }); let mapArr = arr.map((d) => d * 2); console.log(forEachArr); // undefined console.log(mapArr); // [2, 4, 6] 즉, forEach는 배열을 단순히 탐색하기만 하고, map은 배열을 탐색하여 새로운 배열을 반환한다. 따라서 forEach는 새 배열을 반환하지 않고, 단순히 각 요소에 대해 action을 수행하는 경우에 사용하면 좋고, map은 배열을 변환하고 그 결과를 수집하려는..

[JavaScript] 2차원 배열에서 includes 사용하기 (flat() 메서드) [내부링크]

백준 문제를 풀던 중, 2차원 문자 배열에서 특정 문자가 포함되어 있는지 판별해야 했다. 그러나 2차원 배열에서 includes를 사용하게 되면 아래와 같은 문제가 발생한다. const arr = [ ["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ]; console.log(arr.includes("a")); // false 이는 includes 메서드에서 "a"와 2차원 배열 내의 각 row와 비교하기 때문이다. "a"와 ["a", "b", "c"]와 같은 1차원 배열은 당연히 같지 않으므로 false가 출력되게 된다. 이를 해결하기 위해서는 배열의 flat() 메서드를 사용하면 된다. flat()은 다차원 배열의 원소를 1차원 배열로 만들어주는 기능을 한다...

[JavaScript] 함수 선언문과 함수 표현식 [내부링크]

함수 선언문 function a() {} // 함수 호출 시 a(); 함수 이름 지정 필수 호이스팅 되므로 함수 선언 전에 호출 가능 함수 선언문의 경우, 함수를 호출할 때 함수명을 사용하는 것처럼 보인다. 그러나 함수 이름은 함수 몸체 내에서만 참조할 수 있다. 그러면 어떻게 함수 이름을 사용하여 호출할 수 있을까? 사실은 함수 이름을 사용하여 호출하는 것이 아니다. 함수는 함수 이름으로 호출하는 것이 아닌, 함수 객체를 가리키는 식별자로 호출한다. 함수 선언문을 사용하면 자바스크립트 엔진이 암묵적으로 함수명과 동일한 이름의 식별자를 생성하고, 여기에 함수 객체를 할당한다. 따라서 위의 코드에서는 함수명 a로 함수를 호출하는 것이 아니라 a라는 식별자로 함수를 호출하는 것이다. 함수 표현식 var te..

[Git] rebase란? [내부링크]

git rebase는 말그대로 base를 다시(re) 설정하는 것이다. merge와 코드 결과는 같은데, 커밋 히스토리를 단순화하기 위해 사용한다. 예를 들어, master 브랜치에서 experiment 브랜치가 분기되어 나왔다고 했을 때, 아래와 같이 master와 experiment 브랜치 각각 작업한 내용(C3, C4)이 있을 것이다. merge를 사용한다면? 이때, merge를 사용해 합치게 되면 커밋 히스토리는 아래와 같다. git checkout master git merge experiment 즉, C3과 C4의 작업 내용이 합쳐져서 C5에 반영되었다. rebase를 사용한다면? 그러나 rebase를 사용하게 되면, C4에서 변경된 내용(experiment에서 작업한 내용)을 임시 저장하는 ..

[React] useEffect 최초 렌더링 무시하기 [내부링크]

useEffect에 deps 배열에 특정 값을 넣으면, 다음의 2가지 경우에 useEffect 내의 콜백 함수가 실행된다. 컴포넌트가 마운트 될 때 deps 배열 내의 값이 변경될 때 그러나 1의 경우에는 콜백 함수를 실행하지 않고, 2의 경우에만 콜백 함수를 실행해야 할 때도 있을 것이다. 그럴 때는 아래와 같이 isMounted라는 state를 선언하여 활용하면 된다. const [isMounted, setIsMounted] = useState(false); useEffect(() => { if (isMounted) { ~~ } else { setIsMounted(true); ~~ } }, [something]); 최초에는 isMounted가 false이므로 useEffect 내의 콜백함수 중 els..

[React] BrowserRouter와 HashRouter의 차이(Browser Router를 사용할 때 새로고침 시 404 에러가 발생하는 이유) [내부링크]

React를 사용해 개발하면서 라우팅 기능을 구현할 때 대부분 react-router-dom을 사용할 것이다. react-router-dom에는 수많은 라우터 중에 HashRouter와 BrowserRouter가 존재한다. 둘 중에서 대부분 BrowserRouter를 사용하여 라우팅을 구현할 것이다. BrowserRouter와 HashRouter를 비교하는 글들이 많은데, 각각의 특징을 간단히 적자면 아래와 같다. Hash Router 주소에 Hash(#)가 붙는다. Hash(#) 때문에 검색 엔진이 읽지 못한다. (SEO 최적화 X) 별도의 서버 설정을 안 해도 새로고침 시에 에러가 발생하지 않는다. Browser Router History API를 사용한다. 별도의 서버 설정을 하지 않으면 URL에 ..

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (4) - Firebase로 프로젝트 배포하기 [내부링크]

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (3) - Firestore를 사용하여 데이터 다루기 [Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (2) - Firebase를 사용하여 이메일 로그인 구 [Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (1) - Firebase와 React 연동하기 앞으로 4편에 2junsu.tistory.com 이전 글에 이어서 이번 글에서는 지금까지 만든 프로그램을 직접 배포하는 방법에 대해 다룬다. 우선, 콘솔에 들어가서 Hosting을 클릭한 후 시작하기를 누른다. 아래 명령어를 입력한다. npm i -g firebase-tools firebase login fire..

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (3) - Firestore를 사용하여 데이터 다루기 [내부링크]

이번 글에서는 Firebase에서 제공하는 DB인 Firestore를 사용하여 간단한 데이터를 저장하고 불러오고 삭제하는 것을 다룬다. Firestore 기본 설정 우선, 콘솔에서 Firestore Database를 클릭하여 데이터베이스를 만든다. 프로덕션 모드에서 시작을 선택하고 다음을 누른다. 위치는 한국이므로 asia-northeast3 (Seoul)을 선택하여 만들기를 완료한다. 다 만들고 나면 에러를 방지하기 위해 규칙 탭으로 이동하여 아래와 같이 코드를 수정한다. allow read, write: if true; // false를 true로 변경 이제 모든 준비가 끝났다. Firestore에 데이터를 저장하는 것부터 구현해보자! 데이터 추가 및 수정하기 우선, Firestore를 사용하기 위해..

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (2) - Firebase를 사용하여 이메일 로그인 구현하기 [내부링크]

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (1) - Firebase와 React 연동하기 앞으로 4편에 걸쳐서 파이어베이스와 리액트를 사용하여 아주아주 간단한 프로그램을 만들어보는 글을 작성할 예정이다. 이번 글에서는 파이어베이스와 리액트를 연동하는 것에 대해 다루겠다 2junsu.tistory.com 이전 글에 이어서 이번 글에서는 이메일을 사용한 회원가입 및 로그인 기능을 구현해보자. 공식문서 링크는 여기 기본 설정 우선 전에 만들었던 test 프로젝트를 눌러서 콘솔로 이동한 후에 Authentication을 클릭하고, 이메일/비밀번호를 클릭한다. 그리고 이메일/비밀번호 사용 설정에 체크한 후 저장을 누른다. 이제 이메일로 회원가입/로그인을 구현하기 위한 준비는..

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (1) - Firebase와 React 연동하기 [내부링크]

앞으로 4편에 걸쳐서 파이어베이스와 리액트를 사용하여 아주아주 간단한 프로그램을 만들어보는 글을 작성할 예정이다. 이번 글에서는 파이어베이스와 리액트를 연동하는 것에 대해 다루겠다. 우선 리액트 프로젝트를 만들어 준다. npx create-react-app test 그리고 파이어베이스에 접속하여 로그인 후에 콘솔로 이동하여 "프로젝트 추가"를 누른다. 프로젝트 이름을 입력하고 넘어간다. 그 다음으로는 Google 애널리틱스 사용 설정이 나오는데, 나는 그냥 설정에 체크하고 넘어갔다. Google 애널리틱스 사용 설정을 했다면 Google 애널리틱스 구성이 나오는데, Default Account for Firebase를 선택한 후 넘어간다. "프로젝트 만들기"를 누르고 프로젝트 생성을 완료한다. 그러면 아..

[Firebase] Firestore 에러 (FirebaseError: Missing or insufficient permissions) [내부링크]

Firestore에서 데이터를 불러오려고 하는데 아래와 같은 에러가 발생했다. 이를 해결하는 방법은 우선 해당 Firebase Console로 이동한다. 그리고 아래와 같이 Firestore Database를 클릭한다. 아래와 같이 규칙 탭에 들어간다. 아래 코드에서 false를 true로 바꿔주면 에러가 해결된다!

[Git] Git 단축키 설정하기 (alias) [내부링크]

git config --global alias.변경_후_명령어 변경_전_명령어 // example git config --global alias.st status // 위처럼 설정하면 git status를 git st로 써도 됨 commit, pull, push 등등 원하는 명령어를 단축키로 설정하면 매우 편리하다! 부작용 : 내 pc에서 git st로 설정해서 쓰다가 설정 안 돼있는 다른 pc에서 git st라고 쳐놓고 왜 안 되지..? 라고 생각했던 경험 있음

[Firebase] API KEY 에러 (auth/api-key-not-valid.-please-pass-a-valid-api-key.) [내부링크]

React에서 Firebase를 연결해 로그인 기능을 구현하던 중, API KEY가 유효하지 않다는 에러가 발생했다. auth/api-key-not-valid.-please-pass-a-valid-api-key. .env 파일을 생성하여 아래와 같이 관련된 값들을 저장한 후에 firebase-config 파일에서 불러다 쓰고 있었다. REACT_APP_FIREBASE_API_KEY = ... REACT_APP_FIREBASE_AUTH_DOMAIN = ... REACT_APP_FIREBASE_PROJECT_ID = ... REACT_APP_FIREBASE_STORAGE_BUCKET = ... REACT_APP_FIREBASE_MESSAGING_SENDER_ID = ... REACT_APP_FIREBASE_..

[React] API KEY 숨기기 [내부링크]

API KEY는 개인 정보이다. 따라서 깃허브에 프로젝트 코드를 올릴 때는 이를 숨기고 올려야 한다. 이때 .env 파일을 생성하여 API KEY를 환경 변수로 설정해놓고 필요한 곳에서 불러다 쓰면 된다. 먼저 .env 파일을 만들자. 여기서 주의할 점은 .env 파일은 최상단 경로에 위치해야 한다! 그리고 아래와 같이 환경 변수를 선언한다. // .env REACT_APP_API_KEY = api key 입력 이때 환경 변수명은 꼭 REACT_APP_으로 시작해야한다. 또한 따옴표로 문자열을 감싸지 않아야 한다. 이와 관련된 내가 겪은 에러는 여기를 참고하면 된다. 이제 필요한 곳에서 환경 변수를 불러다 쓰면 되는데 아래와 같이 사용한다. const API_KEY = process.env.REACT_A..

[styled-components] 전역 스타일 적용하기 (createGlobalStyle) [내부링크]

개발을 하다 보면 프로젝트 전체에 기본적으로 적용하고 싶은 스타일이 있을 것이다. 예를 들어 나의 경우에는 button 태그를 스타일링 할 때 아예 처음부터 커스텀하고 싶어서 all: unset;을 주고 시작한다. 이때 all: unset;을 button 태그마다 모두 써줘야한다. 또한, hover 시에 포인터 커서가 되도록 모든 button에 설정해야 한다. 이런 귀찮음을 방지하기 위해서 전역 스타일 적용이 필요한데, styled-components에서는 createGlobalStyle를 사용하면 된다. 우선 전역 스타일을 작성할 파일 하나를 만든다. 나의 경우, src\style\global\ 경로에 파일을 만들었다. createGlobalStyle은 일반적으로 styled-components를 사용..

[TypeScript] localStorage에서 데이터를 불러올 때 타입 에러 해결하는 법 (Argument of type 'string | null' is not assignable to parameter of type 'string'. Type 'null' is not assignable to type 'string'.) [내부링크]

JSON.parse(localStorage.getItem("treasureList")); 위와 같이 localStorage에서 데이터를 불러온 후 파싱해주는 과정에서 아래와 같은 에러가 발생했다. string | null 타입은 string 타입에 할당할 수 없다는 뜻이다. localStorage는 string이나 null 타입을 반환하는데, JSON.parse는 string을 필요로 하기 때문에 발생하는 에러이다. 따라서 JSON.parse 안의 값이 항상 string이 되도록 수정해줘야 한다. JSON.parse(localStorage.getItem("treasureList") || "{}") 이렇게 localStorage에서 불러온 값이 null이라면 "{}"라는 string 값으로 대신하면서 에러..

[JavaScript] 숫자 자체를 문자열로 변환할 때 주의할 점 [내부링크]

자바스크립트를 사용하다 보면 예상한 대로 동작하지 않는 경우가 있다. 아래의 경우도 그렇다. 변수에 숫자를 저장한 후에 문자열로 변환하면 정상적으로 동작하지만, 숫자 자체를 문자열로 변환하면 에러가 발생한다. 이는 코드를 실행할 때 "123." 이라는 것이 나오게 되면 숫자 뒤의 점을 소수점으로 인식하여 그 뒤에 숫자가 나올 것으로 예상하기 때문이다. 숫자가 나와야 하는데 toString()이 나오게 되니까 에러가 발생하는 것이다. 이를 해결하기 위해서는 다음과 같은 방법이 있다. 우선 괄호를 사용하는 방법이다. 괄호로 숫자를 감싸주면 그 안에 있는 것만 숫자로 인식하므로 뒤의 점이 소수점으로 인식되지 않는다. 또다른 방법으로는 점을 2개 붙여주는 것이다. 아래의 예시를 보자. 위의 예시에서 3.은 그냥..

[Axios] Axios interceptor와 react-spinners를 사용하여 로딩 중 상태 구현하기 [내부링크]

Axios에는 인터셉터라는 것이 존재한다. 이는 서버에 요청이 전달되기 전과 서버로부터 응답을 받을 때 가로채서 특정 동작을 수행하도록 하기 위해 존재한다. 인터셉터와 react-spinners 라이브러리를 사용하여 api 요청을 할 때 로딩 중인 상태를 알 수 있도록 로딩바를 구현해보자. 아래 나올 코드는 이전 글과 이어지는 코드이다. [Axios] Axios 인스턴스 생성하기 지금까지 axios를 사용할 때는 아래와 같이 사용했다. const url = "https://jsonplaceholder.typicode.com/"; const getInfo = () => { axios .get(url + "posts") .then((res) => { console.log(res); }) .catch((e) ..

[Axios] Axios 인스턴스 생성하기 [내부링크]

지금까지 axios를 사용할 때는 아래와 같이 사용했다. const url = "https://jsonplaceholder.typicode.com/"; const getInfo = () => { axios .get(url + "posts") .then((res) => { console.log(res); }) .catch((e) => { console.error(e); }); }; 또다른 방법으로는 인스턴스를 생성하여 사용하는 방법이 있는데, 이를 사용하면 사용자 정의 구성을 사용할 수 있다. 또한, axios를 모듈화함으로써 재사용성을 높일 수 있다. 이때 재사용성을 높이기 위해 커스텀 훅을 만들어 사용하겠다. // useAxios.js export const useAxios = () => { const..

[CSS] transition을 사용하여 커서를 올려놓았을 때 색상 서서히 변경하기 [내부링크]

웹 페이지를 보다 보면 커서를 올려놓았을 때 해당 색상이 바로 변하는 것이 아니라 서서히 변하는 것을 볼 수 있다. 예를 들면 애플 홈페이지의 header navigation 부분이 있다. Apple (대한민국) Apple이 제시하는 혁신적인 세상을 만나고, iPhone, iPad, Apple Watch, Mac, Apple TV 등을 구입하는 것은 물론, Apple 액세서리, 엔터테인먼트, 전문가 기기 지원에 대해서도 살펴볼 수 있습니다. www.apple.com 이를 구현하기 위해서는 css의 transition 속성을 사용하면 되는데, 자세한 것은 아래 문서를 참고하길 바란다. CSS 트랜지션 사용하기 - CSS: Cascading Style Sheets | MDN CSS 트랜지션은 CSS 속성..

[JavaScript] 2차원 배열 깊은 복사하기 [내부링크]

1차원 배열의 경우는 스프레드 연산자를 통해서 아래와 같이 배열을 새로 복사할 수 있었다. let arr=[1,2,3]; let arr2=[...arr]; arr2.push(4); arr2[1]=10; // 두 배열이 다르게 출력됨 console.log(arr); // [ 1, 2, 3 ] console.log(arr2); // [ 1, 10, 3, 4 ] 스프레드 연산자를 통한 복사는 사실 얕은 복사이다. 얕은 복사는 한 단계까지만 복사한다. 항상 배열이나 객체가 생성이 되기 때문에 그 자체는 다른 것으로 평가되지만, 그 내부에 중첩되어있는 요소들은 같은 것으로 평가된다. 따라서 2차원 배열의 경우에는 의도한 대로 복사되지 않는 것을 확인할 수 있다. 2차원 배열을 깊은 복사하고 싶다면 아래와 같이 각..

[JavaScript] 백준 문제를 풀기 위한 입출력 설정 방법 (fs 모듈) [내부링크]

2023년의 첫 번째 글 !! 프로그래머스의 경우, 입출력을 상관하지 않고 함수만 작성해주면 되었지만 백준에서는 입출력을 직접 해줘야한다. 프론트엔드 직군을 준비하면서 자바스크립트로 코딩테스트를 준비한다면 백준에서 node.js를 선택해야하는데, 이때 입력값을 받는 과정이 꽤 복잡하다. 2가지 방법이 있는데 fs 모듈을 사용하는 방법과 readline을 사용하는 방법이다. readline은 시간초과가 날 때가 있다고 하니 이 글에서는 fs 모듈을 사용하는 방법에 대해 작성한다. 우선, 예제 입력으로는 아래 입력을 사용하겠다. 참고로 백준 1260번 문제이다. https://www.acmicpc.net/problem/1260 example.txt 파일을 생성하여 아래 입력값을 붙여준다. 4 5 1 1 2 ..

[JavaScript] Array.from()을 사용하여 2차원 배열 만들기 [내부링크]

자바스크립트에는 딱 2차원 배열이라는 개념이 없다. 즉, let arr = [][]; 와 같은 선언이 불가능하다. 그래서 배열 안에 배열을 중첩하는 식으로 2차원 배열을 비슷하게 만들어줘야 한다. 이때 Array.from() 이라는 메서드를 사용한다. 이 메서드는 문자열, set, map, 배열 등의 각 요소를 얕게 복사하여 새로운 배열을 만들어주는 역할을 한다. 예를 들면 아래와 같이 동작한다. console.log(Array.from('apple')); // [ 'a', 'p', 'p', 'l', 'e' ] console.log(Array.from(new Set(['foo', 2]))); // [ 'foo', 2 ] from의 두 번째 인자에는 콜백 함수를 옵션으로 넣을 수 있다. 이 콜백 함수는 각..

[JavaScript] JS에서 아스키코드 변환하기 [내부링크]

JS에서는 charCodeAt과 fromCharCode 함수를 사용하여 아스키 코드를 변환한다. charCodeAt(idx) 해당 인덱스의 문자열을 아스키 코드 번호로 변환해준다. let str = "Hello World!"; // 1번 인덱스값인 e의 아스키 코드 번호 101이 출력된다. console.log(str.charCodeAt(1)); // 101 fromCharCode(num) 아스키 코드 번호 num에 해당하는 문자열을 나타낸다. console.log(String.fromCharCode(101)); // e console.log(String.fromCharCode(72, 101, 108, 108, 111)); // Hello

[JavaScript] 자바스크립트에서 replaceAll 함수 대체하기 (Feat.정규식) [내부링크]

JS에서 문자열의 값을 대체하는 방법은 replace를 사용하는 것이다. 그러나 replace는 처음 발견한 문자에 대해서만 적용된다. 예를 들면 아래와 같다. let str = "Hello World!"; str = str.replace("l", "r"); console.log(str); // Herlo World! (첫 번째 l만 r로 대체된다!) 이를 해결하기 위해 replaceAll 함수가 있다면 정말 좋겠지만, JS에는 존재하지 않는다. 따라서 직접 유사하게 만들어야 하는데 정규식을 사용하여 문자열 전체에 대해 대체 작업을 수행하도록 하면 된다. let str = "Hello World!"; str = str.replace(/l/g, "r"); console.log(str); // Herro W..

[JavaScript] 배열 내에 요소들 중복 제거하기 [내부링크]

배열 내의 중복된 값을 제거하기 위해서는 Set 객체를 활용하면 된다. Set은 ES6에서 등장한 새로운 데이터 object이다. Set은 Unique한 값만 저장할 수 있기 때문에 아래와 같이 활용하면 된다. let arr = [1,2,2,3,3,3,4,4,5,5,5]; let setObj = new Set(arr); // Set 객체를 생성하여 arr를 넣어주면 유일한 값을 가지는 객체가 된다. let uniqueArr = [...setObj]; // 이 Set 객체 내의 값을 배열에 복사해주면 유일한 값을 가지는 배열이 만들어진다. console.log(uniqueArr); // [1,2,3,4,5]

[JavaScript] splice 함수에 대하여 [내부링크]

splice 함수에 대해 그때그때 찾아보기만 하다가 잘 기억하지 못 하게 되면서 아예 직접 정리를 하기로 결심했다. splice 함수 배열의 기존 요소를 삭제하거나 추가하여 배열의 내용을 변경할 때 사용한다. splice의 형태는 아래와 같다. array.splice(start, deleteCount,item1, item2, ...); start는 배열의 변경을 시작할 인덱스이다. 배열의 길이보다 크거나 같은 값이라면 그냥 무시된다. start가 음수라면 배열의 끝에서부터 요소를 센다. 예를 들어 -1이라면, 배열의 가장 끝 요소를 가리킨다. 만약 음수일 때, 절대값이 배열의 길이보다 크다면 0으로 설정된다. deleteCount는 배열에서 제거할 요소의 수이다. 이를 생략하거나 start부터 배열 끝까..

[JavaScript] Array의 요소를 swap해보자 [내부링크]

배열에서 두 요소를 서로 바꾸고 싶을 경우 직접 구현을 해야한다. 가장 기본적인 방법은 tmp 변수를 사용하는 것인데 아래와 같다. const arr=[1,2,3,4,5]; let tmp=arr[1]; arr[1]=arr[2]; arr[2]=tmp; console.log(arr); // [1,3,2,4,5] 만약 두 요소만이 아닌 좀 더 자유도가 높게 위치를 변경하고 싶다면 구조 분해 할당을 사용하면 된다. 구조 분해 할당은 배열이나 객체의 속성을 해체해서 그 값을 개별 변수에 담을 수 있게 하는 Javascript의 표현식이다. 구조 분해 할당을 사용하면 아래와 같이 쓸 수 있다. const arr=[1,2,3,4,5]; [arr[1], arr[2]] = [arr[2], arr[1]]; console...

[JavaScript] 배열 정렬하기 [내부링크]

JS에서 배열을 오름차순 정렬을 하기 위해서는 sort() 함수를 쓰면 된다. 그러나 아래와 같은 문제가 발생한다. const arr=[1, 10, 3, 2]; arr.sort(); console.log(arr); // [ 1, 10, 2, 3 ] 우리가 원하는 결과는 [1, 2, 3, 10] 인데 이상한 결과가 출력된다. 이 문제를 해결하기 위해서는 sort() 안에 compareFunction을 사용해야한다. compareFunction은 정렬 순서를 정의하는 함수이다. 이를 사용하지 않게 되면, 배열 내의 원소들이 문자열로 취급되기 때문에 유니코드 값 순서대로 정렬된다. 따라서 위와 같은 결과가 발생한 것이다. compareFunction은 2개의 배열 원소를 파라미터로 입력 받는다. 예를 들어, ..

[JavaScript] 문자열 뒤집기 [내부링크]

맨날 C++로 알고리즘 문제를 풀다가 요즘 JS로 문제를 풀고 있다. JS의 함수를 사용하여 문자열 뒤집기를 알아보자. "Hello World!" 라는 문자열이 있다고 하자. 우선 reverse() 함수를 사용하면 되는데 이를 사용하기 위해서는 문자열을 배열 형태로 만들어야 한다. 따라서 문자 하나씩 배열에 넣기 위해 split() 함수를 사용한다. const str = "Hello World!"; str.split(''); /* [ 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' ] */ 그 후에 reverse() 함수를 써주게 되면 아래와 같다. str.split('').reverse(); /* [ '!', 'd', 'l', 'r', 'o', ..

[React] useReducer에 대하여 [내부링크]

useReducer는 reducer를 사용하여 다양한 상태를 다른 값으로 업데이트할 때 사용하는 Hook이다. 여기서 reducer란, 현재 상태 state와 업데이트를 위해 필요한 정보가 담겨있는 Action 값을 파라미터로 받아서 state를 변경하는 함수이다. Redux에서도 사용하는 개념이니 아래 글을 참고해도 좋을 것 같다. [Redux] Vanilla Redux의 기본 개념 Redux는 Javascript의 상태 관리 라이브러리이다. 보통 React와 함께 많이 사용되지만, Augular, jQuery, vanilla JavaScript 등 여러 framework에서 사용이 가능하다. Redux에 기본적인 개념 및 용어를 알아보자. npm i 2junsu.tistory.com 참고로 Redux..

[React Native] RN에서 axios로 formData 전송하기 [내부링크]

formData는 우리가 HTML에서 form 태그를 사용하여 input 값을 서버에 전송하는 것 대신, 자바스크립트 단에서 폼 데이터를 다루는 객체이다. 주로 일반 데이터 말고 이미지 파일을 서버에 전송해야 할 때 formData를 사용하게 된다. RN으로 앱을 개발하던 중 리뷰 작성을 구현하기 위해 이미지 업로드 기능이 필요했다. 이때 formData를 사용했다. formData에 데이터를 저장하는 방법은 아래와 같이 append를 사용하면 된다. const formData = new FormData(); formData.append('rate', rating); formData.append('contents', message); formData.append('matchingId', matchingI..

[Recoil] 리코일의 기본 개념 (3) - selector [내부링크]

이번 글에서는 리코일의 selector에 대해 알아보도록 하겠다. selector selector는 리코일에서 관리하는 상태의 특정 부분만 선택할 때 사용한다. selector를 사용하는 이유는 최소한의 상태 집합만 atoms에 저장하고, 다른 모든 파생되는 데이터는 selectors에 명시한 함수를 통해 효율적으로 계산함으로써 쓸모없는 상태의 보존을 방지하기 위함이다. 아래에 나올 코드에 대해 미리 말하자면, tempFahrenheit만을 atom에 저장하고, 이로부터 파생되는 tempCelcius는 굳이 보존하지 않기 위해 selector를 사용했다. selector는 key와 get 함수를 필수로 받아야한다. 또한 set 함수도 선택적으로 받을 수 있는데, get 함수만 사용하게 되면 selecto..

[Recoil] 리코일의 기본 개념 (2) - useRecoilValue, useSetRecoilState [내부링크]

저번 글에 이어 리코일의 또 다른 개념에 대해 알아보도록 하겠다. [Recoil] 리코일의 기본 개념 (1) - RecoilRoot, atom, useRecoilState 리코일은 리액트를 위한 상태관리 라이브러리이다. CMC 11기 활동을 하며 리코일을 처음 도입해봤는데 기본 개념에 대해 기술하고자 한다. RecoilRoot 리코일의 모든 요소는 아래와 같이 RecoilRoot 내 2junsu.tistory.com 저번 글에서는 상태를 불러오고 변경하기 위해 useRecoilState를 사용했다. 이번에는 상태를 불러오기만을 위한 개념, 상태를 변경하기만을 위한 개념에 대해 알아보도록 하겠다. useRecoilValue useRecoilValue는 컴포넌트에서 업데이트 함수는 필요 없고 상태 값만 필요..

[Recoil] 리코일의 기본 개념 (1) - RecoilRoot, atom, useRecoilState, useResetRecoilState [내부링크]

리코일은 리액트를 위한 상태관리 라이브러리이다. CMC 11기 활동을 하며 리코일을 처음 도입해봤는데 기본 개념에 대해 기술하고자 한다. RecoilRoot 리코일의 모든 요소는 아래와 같이 RecoilRoot 내에서 써야한다. Test 컴포넌트 내에 recoil을 사용할 것이다. //App.jsx import React from "react"; import Test from "./Test"; import { RecoilRoot } from "recoil"; const App = () => { return ( ); }; export default App; atom 리코일은 기본적으로 atom을 사용하여 상태를 정의한다. 리덕스의 initialState와 비슷한 개념이라고 생각하면 된다. atom을 만들 ..

[React] textarea의 높이를 가변적으로 설정하기 [내부링크]

라이징 테스트에서 원티드를 클론코딩하던 도중 이력서 작성 페이지에서 이슈가 발생했다. 실제 원티드에서는 textarea에 내용을 입력하면 라인수에 따라 textarea 영역이 늘어난다. 즉 아래 요소들이 아래로 밀린다. 그러나 나의 경우, textarea의 height는 고정돼있고 스크롤에 의해 글 내용이 보여졌다. 이를 해결하기 위해 useRef 훅과 onKeyUp, onKeyDown을 사용했다. const ref = useRef(); ... { autoResizeTextarea(ref); }} onKeyUp={() => { autoResizeTextarea(ref); }} className="detail" name="detail" placeholder="세부사항" onChange={handleInpu..

[CSS] Modal을 화면 중앙에 배치하기 [내부링크]

개발을 하다 보면 모달창을 자주 사용하게 된다. 모달창은 보통 화면에 한가운데에 위치하게 되는데 이를 라이징 테스트에서 원티드를 클론코딩하며 내가 겪었던 과정과 함께 기술하겠다. 원티드에서는 대표적으로 로그인 및 회원가입에서 모달이 필요한데, 우선 가장 쉽게 떠올렸던 방법은 모달의 width와 height를 고정값으로 정했다. width: 500px; height: 500px; top: calc(50% - 250px); left: calc(50% - 250px); 위와 같이 화면 중앙에 모달을 배치했었다. 그러나 모달마다 크기가 다르기 때문에 이는 분명한 한계점이 있다. 그래서 생각한 방법은 width는 고정값을 주고, height를 다르게 받았다. left: `calc(50% - ${width / 2}..

[JavaScript] axios 통신 시 에러가 발생했을 때 상황에 따른 메시지 출력하는 방법 [내부링크]

오늘의집 클론코딩을 진행하면서 axios로 api 통신을 하면서 에러가 발생했을 때, 지금까지는 catch문 안에 console.log(e)로만 출력을 했었다. 그치만 에러가 발생하는 경우는 여러가지가 있다. 예를 들어, 상품에 대한 리뷰를 작성할 때는 상품을 구매하지 않았는데 리뷰를 작성하려 할 때, 또는 이미 리뷰를 작성한 상품에 대해 또 리뷰를 작성하려고 할 때 에러가 발생한다. 이렇게 상황에 따른 에러 메시지를 출력할 때는 아래와 같이 작성하면 된다. axios.post(~) .then(~) .catch((e) => { alert(e.response.data.message); //메시지를 지정해 준 경우 }

[React] 특정 영역을 제외한 영역 클릭 이벤트 구현하기 [내부링크]

Airbnb 클론 코딩을 진행하면서 로그인 드롭다운 메뉴를 구현하다가 해당 메뉴 밖의 어느 부분을 클릭하더라도 드롭다운 메뉴가 닫히도록 구현해보기로 다짐했다. useRef와 EventListener를 사용하여 구현했다. 기본적인 원리는 다음과 같다. 에서 "특정 영역"에 ref를 부여한다. 현재 페이지에서 클릭할 때마다 이벤트가 감지되도록 구현하고, 그때마다 close 함수를 호출한다. close 함수에서는 ref 영역(특정 영역)이 이벤트가 감지된 영역을 포함하는 지를 확인한다. 포함하지 않는다면 ref 영역(특정 영역) 외부를 클릭한 것이므로 이때 메뉴가 닫히도록 구현한다. 1. 에서 "특정 영역"에 ref를 부여한다. 나의 경우, 위에 두 영역을 "특정 영역"으로 설정해서 useRef를 2개 설정했..

[JavaScript] 단축 평가와 옵셔널 체이닝 연산자 [내부링크]

단축 평가 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다. 논리합( || )과 논리곱( && ) 연산자 표현식은 언제나 2개의 피연산자 중 어느 한쪽으로 평가된다. 아래 예시를 통해 확인해보자. 'Apple' && 'Banana' // Banana 출력 'Apple' || 'Banana' // Apple 출력 이처럼 두 결과가 다른 것을 알 수 있는데 이유는 간단하다. 논리곱 연산자는 2개의 피연산자 모두 true여야 true를 반환하므로 2개의 피연산자를 모두 확인하여 마지막으로 확인한 피연산자의 값을 반환하는 것이고, 논리합 연산자는 2개의 피연산자 중 하나만 true이면 true를 반환하므로 이미 'Apple'이 true이므로 뒤는 평가하지 않고 바로 첫..

[JavaScript] 표현식이란? [내부링크]

표현식 표현식이란 값으로 평가될 수 있는 것을 말하는데, 쉽게 구분하는 방법은 변수에 할당해보면 된다. 표현식은 값으로 평가되기 때문에 변수에 할당이 가능하다. var x; //표현식 x -> var a = var x;는 사용할 수 없으므로 x = 1 + 2; // 표현식 o -> x = 1 + 2;로 이미 변수에 할당되어 있으므로 또한 크롬 개발자 도구에서도 쉽게 확인할 수 있는데, 개발자 도구에서 표현식을 실행하면 값이 출력되고, 표현식이 아닌 것을 실행하면 undefined를 출력한다.

[React] 라이프사이클 메서드에 대하여 [내부링크]

모든 리액트 컴포넌트에는 라이프사이클(수명 주기)이 존재한다. 크게 3가지로 분류할 수 있는데, 마운트, 업데이트, 언마운트가 그 3가지이다. 마운트는 컴포넌트가 생성되고 DOM이 업데이트되어 웹 브라우저 상에 나타나는 것이다. 업데이트는 말 그대로 컴포넌트를 업데이트하는 것이다. 언마운트는 마운트의 반대 개념으로, 컴포넌트를 DOM에서 제거하는 것이다. 총 9가지가 있는데 참고로 이는 클래스형 컴포넌트에서만 사용이 가능하다. 함수 컴포넌트에서는 Hooks를 사용한다. 오늘은 클래스형 컴포넌트에서 쓰이는 라이프사이클 메서드 9가지를 알아보자. 1. render() 최종적으로 작업한 UI를 렌더링하는, 즉 리액트 요소를 반환하는 메서드이다. 따라서 라이프사이클 메서드 중 유일하게 필수 메서드이다. rend..

[Redux Toolkit] Redux를 좀 더 간편하게, Redux Toolkit (2) - createReducer [내부링크]

이전 글에 이어서 이번에는 createReducer에 대해 작성하겠다. 이전 글에서 다뤘던 createAction은 Redux의 action을 간편하게 만들 수 있는 것이었다면, createReducer도 마찬가지로 reducer를 간편하게 만들 수 있는 방법이다. createReducer TodoList 코드를 기준으로 보면 기존의 reducer를 생성하는 방법은 아래와 같다. const reducer = (state = [], action) => { switch (action.type) { case addTodo.type: return [...state, { text: action.payload, id: Date.now() }] case deleteTodo.type: return state.filte..

styled-components의 ThemeProvider [내부링크]

오늘의집 클론코딩 프로젝트를 진행하는 도중에 mainColor를 전역 변수로 사용해야함을 느꼈다. 이전에 React Native 프로젝트에서는 Context API를 사용하여 전역 변수를 사용했고, 이번에는 Redux를 사용하여 상태 관리를 하기로 했기 때문에 처음에는 Redux에 전역 변수를 저장해야겠다고 생각했다. 그래서 Redux 내에 initialState에 변수를 선언해놓고 이것을 각 페이지에서 useSelector로 불러온 후, 해당 변수를 styled-components에 props로 전달해주었다. 페이지가 많아지다보니 이러한 작업이 번거롭다고 생각했고, 더 좋은 방법을 찾아보던 중에 styled-components에서 ThemeProvider라는 기능을 제공하고 있다는 것을 알게 되었다. ..

[JavaScript] Hoisting에 대하여 [내부링크]

Hoisting이란? Javascript에는 Hoisting이라는 개념이 존재한다. 사전적인 의미는 '끌어올리다'라는 뜻을 가지고 있고, 의미 그대로 변수와 함수의 선언을 자동으로 파일의 가장 상단으로 끌어올려서 처리하는 것을 말한다. 예를 들면 아래와 같다. Test(); //함수가 선언되기 이전에 참조했는데 정상 작동함 function Test() { console.log("Hi"); } for (var i=0;i

[TypeScript] 클래스의 접근 제한자 [내부링크]

Typescript에서의 클래스에는 C++, 자바처럼 다른 객체지향 언어와 마찬가지로 접근 제한자가 존재한다. public 해당 클래스의 내부와 자식 클래스 및 클래스 인스턴스에서도 모두 접근 가능하다. class Car { name: string = "car"; //name 앞에 public을 명시하지 않아도 default가 public임 color: string; constructor(color: string) { this.color = color; } } class BMW extends Car { constructor(color: string) { super(color); //파생 클래스는 무조건 super를 써야함 } showName() { console.log(this.name); //publi..

[TypeScript] 함수 [내부링크]

interface에 관한 글을 쓰면서 함수에 대한 코드를 잠깐 언급했었는데 이번 글에서도 다뤄보고자 한다. 이미 우리가 알고 있는 함수 그대로이다. Typescript에서는 함수에도 타입을 선언할 수 있다. 리턴값이 없다면 타입은 void가 된다. function test(name: string, age: number): string { if (age === undefined) return `name : ${name}`; else return `name: ${name}, age: ${age}`; } console.log(test('jun')); //error console.log(test('jun', 25)); // name: jun, age: 25 위의 함수는 name과 age 두 개의 변수를 받고 리..

[Redux Toolkit] Redux를 좀 더 간편하게, Redux Toolkit (1) - createAction [내부링크]

이 글은 Redux의 기본 개념에 대해 알고 있다고 가정하고 진행한다. Redux에 대해 잘 모른다면 아래 글을 참고하면 좋을 듯! [Redux] Vanilla Redux의 기본 개념 Redux는 Javascript의 상태 관리 라이브러리이다. 보통 React와 함께 많이 사용되지만, Augular, jQuery, vanilla JavaScript 등 여러 framework에서 사용이 가능하다. Redux에 기본적인 개념 및 용어를 알아보자... 2junsu.tistory.com 또한 이전 글에서 다뤘던 TodoList 코드를 가지고 진행되니 React Redux (1), (2) 먼저 보고 오길 바란다. [React Redux] React에서 Redux를 사용해보자(1) 이 글은 Redux의 기본 개념에..

[React Redux] React에서 Redux를 사용해보자(2) [내부링크]

이 글은 아래 글의 후속편이니 아래 글부터 보고 오는 것을 추천한다. [React Redux] React에서 Redux를 사용해보자(1) 이 글은 Redux의 기본 개념에 대해 알고 있다고 가정하고 진행한다. 개념을 잘 모른다면 아래 포스팅을 참고하면 좋을 듯! [Redux] Vanilla Redux의 기본 개념 Redux는 Javascript의 상태 관리 라이브러리이 2junsu.tistory.com 이제 추가 기능을 구현했으니 삭제 기능을 구현해보자. 삭제 기능에서 해야할 것은 특정 할 일에 붙어있는 삭제 버튼을 누르면 해당 할 일을 삭제하는 것이다. 따라서 특정 할 일에 대한 id가 필요하다. 그 후 할 일들이 저장된 배열을 돌면서 해당 id를 가지는 할 일을 제외한 나머지를 새로운 배열에 넣은 후..

[React Redux] React에서 Redux를 사용해보자(1) [내부링크]

이 글은 Redux의 기본 개념에 대해 알고 있다고 가정하고 진행한다. 개념을 잘 모른다면 아래 포스팅을 참고하면 좋을 듯! [Redux] Vanilla Redux의 기본 개념 Redux는 Javascript의 상태 관리 라이브러리이다. 보통 React와 함께 많이 사용되지만, Augular, jQuery, vanilla JavaScript 등 여러 framework에서 사용이 가능하다. Redux에 기본적인 개념 및 용어를 알아보자.. 2junsu.tistory.com 할 일을 추가하고 삭제할 수 있는 간단한 Todo List를 구현하면서 React에서 Redux를 사용하는 법을 알아보자. 이 글에서는 '추가' 기능을 구현한다. 또한 Redux에 익숙해지기 위한 글이므로 Local Storage는 사용..

[TypeScript] 리터럴, 유니온, 교차 타입이란? [내부링크]

리터럴 타입 리터럴 타입은 정해진 값을 가지는 타입이다. JS에서 var, let을 사용하면 값의 변경이 가능하지만 const를 사용하면 값의 변경이 불가능하다. 이러한 특성을 가지는 타입을 리터럴 타입이라고 한다. 아래와 같이 type을 선언해주면 정해진 값 내에서만 선택이 가능하다. type Job = "student" | "teacher" | "developer"; interface Person { name: string; job: Job; } const jun: Person = { name: 'jun', job: 'developer', // student, teacher, developer 중에서만 선택 가능 } //숫자형에도 동일하게 적용 가능 type num = 1 | 2 | 3; interf..

[TypeScript] interface란? [내부링크]

상호 간에 정의한 약속 혹은 규칙을 의미하며, 객체의 모양을 명시적으로 나타내기 위해 사용한다. let user:object; user={ name:'aa', age:30 } console.log(user.age); //error 위와 같이 사용하게 되면 property가 존재하지 않는다면서 에러가 발생한다. 따라서 아래와 같이 interface를 사용하여 객체의 모양을 나타내야 한다. interface User { name:string; age:number; } let user:User; user={ name:'aa', age:30 } console.log(user.age); interface 내에서 정의해준 것을 모두 선언해주지 않으면 에러가 발생한다. Optional Property interfac..

[TypeScript] 기본 자료형 [내부링크]

기본적으로 Javascript+타입으로 쓰인다. 아래와 같이 Typescript에서는 변수의 자료형을 함께 선언해주고, 선언된 자료형과 다른 타입의 값이 들어오면 에러 표시가 난다. //javascript let user; user=3; //typescript let user: string; user=3; //error Typescript는 기본적으로 아래의 Javascript의 기본 자료형을 포함한다. number string boolean null (null이라는 값이 할당된 상태 -> object type) undefined (변수가 선언된 후 아무 값도 할당되지 않은 상태 -> undefined type) symbol(ES6에서 추가됨) Array : Object 그리고 추가적으로 몇 가지 타입이..

[Redux] Vanilla Redux의 기본 개념 [내부링크]

Redux는 Javascript의 상태 관리 라이브러리이다. 보통 React와 함께 많이 사용되지만, Augular, jQuery, vanilla JavaScript 등 여러 framework에서 사용이 가능하다. Redux에 기본적인 개념 및 용어를 알아보자. npm install redux yarn add redux 1. Store Store는 state가 저장되는 공간이다. state는 변경되는 데이터를 말한다. 버튼을 누르면 숫자가 1 증가하거나 감소하는 프로그램이 있다고 할 때, 여기에서의 state는 변경되는 숫자이다. 이러한 state들을 저장하는 곳이 store이다. store는 아래와 같이 생성한다. import { createStore } from 'redux' const store =..