본문 바로가기

분류 전체보기

3개월간의 루비콘 멘토링 프로젝트 활동 회고 2편 - 서비스 릴리즈, 나의 성장 본 프로덕트 개발하기 4월은 아이디어 선정과 프로토타입을 만들고 나니 금방 지나갔다. 5월 한달은 프로토타입을 굴려보면서 본 프로덕트를 기획+개발한 후에 6월 초에 배포하려고 계획했었으나, 결국 6월 초 배포는 실패했다. 왜 실패하게 됐는지 원인을 살펴보고, 우리팀은 이를 어떻게 극복했는지 얘기해보고자 한다. 계획했던 배포를 실패하게 된 가장 큰 이유 4가지는 아래와 같다. 컨디션 난조로 인한 작업시간 부족 각 팀원이 생각하는 커리어집이 제공하는 가치가 달라 기획에 많은 시간 소요 기능을 어디까지 cut off 할 것인가에 대한 모호한 기준 좋아요!는 너무 많지만... 다행히 팀원들이 프로젝트에 대한 모티베이션이 떨어진 것은 아니었기 때문에 우리는 위의 문제들을 해결해나가면서 진행속도를 높일 수 있었다... 더보기
3개월간의 루비콘 멘토링 프로젝트 활동 회고 1편 - Kick off, Prototype 루비콘 신청 목적 작년말에 작성했던 회고글을 보면 알 수 있겠지만 2021년 새해가 밝았음에도 불구하고 그 당시 하고있던 고민을 해결하지 못하고 있었다. 내가 하던 고민은 크게 아래 네가지가 있었다. 나름 공부를 하고 있지만 내가 올바르게 하고있는가에 대한 의문 동시에 프론트엔드 사수, 동료 없는 회사 주니어로서 일을 하면서 성장하고 있다는 느낌이 들지 않음 주변에 개발자 or IT 계열 직군 네트워크가 전혀 없어 이에 대한 갈증이 있음 개발문화가 좋은 회사에서는 어떻게 일하고 있을까 하는 궁금증 이러한 고민을 하던 와중에 우연히 루비콘 멘토링 프로젝트 멘티들을 모집한다는 글을 보게 되었다. 모집요강(?)을 보고 있으니 내가 하고있던 모든 고민에 대한 답을 찾을 수 있지 않을까 하는 생각으로 지원하였고,.. 더보기
@font-face속성에서 url()로 폰트 리소스 호출 시 만난 CORS에러 문제상황 기존 소스파일에 포함되어있었던 폰트, 이미지, 아이콘 파일 등등을 CDN으로 받아오려고 작업하다가 만난 에러이다. AWS S3에 올리고 CloudnFront로 받아오도록 작업했는데, 다른 파일들은 괜찮은데 폰트를 받아오는 경우에만 CORS error 가 발생했다. 검색해보니 CSS 내에서 @font-face 속성으로 Cross-Origin의 폰트 리소스를 호출하는 경우에 해당되기 때문에 발생하는 에러였다. 사파리에서는 이상없이 잘 되는데 크롬에서 CORS에러가 발생함... 브라우저마다 CORS 정책이 달라서 그런것 같다. 아래의 W3C 권장사항을 참고해보면 나는 세번째 경우에 해당하므로 Access-Control-Allow-Origin 리스폰스 헤더 값을 와일드카드(*)로 지정해주어야한다. 해결.. 더보기
Github Actions를 이용해서 S3, CloudFront 배포 하기 문제 상황 회사에서 사용하는 프론트엔드 배포 환경은 총 4가지가 있다. 1. dev - 내부 개발용 2. test, stage - QA용(회사 특성상 더미 데이터를 가지고 있는 test 환경, 실제 라이브 데이터를 가지고있는 stage 두가지로 나뉜다.) 3. prod - 실제 라이브 환경 브랜치는 dev, test, master로 나누어져있었으며, 일반적으로 dev브랜치에서 새로운 브랜치를 따서 기능개발이 이루어지면 dev로 머지 → dev에서 test로 머지 → test, stage 환경에 배포 → QA 테스트 → QA 후 master로 머지되어 라이브로 배포된다. 특히나 한창 QA 돌릴 시기에는 하루에도 몇번씩 배포를 했어야했는데 가내수공업으로 스크립트를 돌리고, 빌드 후 배포가 완료될때까지 다른 .. 더보기
자바스크립트의 가비지컬렉션(Garbage Collection) 메모리 관리는 왜 필요한가? 대부분의 언어에서 메모리 라이프 사이클은 메모리 할당 → 메모리 사용 → 메모리 해제의 단계를 거친다. C같은 low-level 언어의 경우 이 라이프 사이클을 개발자가 malloc()이나 free()를 사용하여 직접 관리를 해주어야 하지만 자바스크립트와 같은 high-level 언어는 대부분 Garbage Collection이라는 자동 메모리 관리를 사용하기 때문에 개발자가 별도의 신경을 쓰지 않는다. 가비지컬렉션(Garbage Collection)이란? 가비지컬렉션은 더이상 사용하지 않는 메모리를 발견하고 이를 해제해주는 역할을 한다. 가비지컬렉션이 자동으로 메모리 관리를 해준다고해서 개발자가 완전히 신경을 쓰지 않는다면 메모리 누수(memory-leak)가 발생할 수도 .. 더보기
moment.js 최적화 - 불필요한 locale파일 빌드 시 제외시키기(with webpack) 현재 회사 프로젝트에서 moment.js를 사용중인데, 실제로 사용하고 있는 local 파일은 ko뿐인데 어마어마하게 많은 모든 local파일을 포함해서 빌드하는것을 발견하였다. 웹팩 번들 애널라이즈로 보면 moment가 차지하는 사이즈가 꽤 크다. 파일의 크기가 크면 클수록 페이지를 로드하는 시간이 길어지기 때문에 되도록이면 사용하지않는 라이브러리는 빌드에 포함시키지 않고 번들링 사이즈를 작게 관리하는 것이 중요하다. 따라서 webpack을 사용하여 번들링 할 때 ko locale만을 번들링파일에 포함시켜 파일 사이즈를 줄여보도록 하겠다. 불필요한 locale 파일들 왜 모두 번들되나요? function loadLocale(name) { var oldLocale = null; // TODO: Find .. 더보기
자바스크립트에서 불변성(Immutability)이란 사실 나는 불변성이라는 개념을 자바스크립트 언어 자체를 공부할 때 말고 리액트를 공부하면서 state를 변경할 때 처음 접했었다. 그냥 단순하게 '새로운 값을 할당하지 않으면 리렌더링이 안되니까 항상 새로운 값으로 줘야지!'의 개념에서 그쳤기 때문에 불변성을 지키지 않은 코드로 버그를 발생시키기도 했고, 디버깅할 때도 애를 먹었다. 불변성 개념은 특별히 자바스크립트 언어에 한정되는 것이 아니고, 다른 언어에서도 존재하는 개념이다. 얕은 복사(shallow copy)와 깊은복사(deep copy)의 개념까지 어느정도 이어지기 때문에 꼭 숙지하는 것이 좋다. 불변성이란 무엇인지와 왜 불변성을 지키는 것이 중요한지에 대해 알아보자. 변수에 값 할당하기 다들 알고 있겠지만 변수에 값을 할당한다는 것은 값의 메모.. 더보기
Programmers - 메뉴 리뉴얼 / Javascript function solution(orders, course) { let answer = []; const list = {}; const getCombination = (arr, n) => { const result = []; if(n === 1) return arr.map(e => [e]); arr.forEach((e, idx, origin) => { const rest = origin.slice(idx + 1); const combinations = getCombination(rest, n-1); const attached = combinations.map(combi => [e, ...combi]); result.push(...attached); }); return result; } orders.map.. 더보기
Programmers - 신규 아이디 추천 / Javascript function solution(new_id) { let string = ''; //소문자변환 string = new_id.toLowerCase() //알파벳 소문자, 빼기, 밑줄, 마침표 제외하고 제거 .replace(/[^a-z0-9\.\-\_]/gi,'') //마침표가 2번 이상 연속된 경우 하나의 마침표로 치환 .replace(/\.+/g,'.') //마침표가 처음이나 끝에 위치한다면 제거 .replace(/^\.+|\.+$/g,''); //빈 문자열이라면 'a'를 대입하고 아니라면 15자까지만 자르기 string = string? string.substr(0, 15) : 'a'; //끝에 위치한 마침표 제거 string = string.replace(/\.+$/g,''); //글자수가 2이하인 .. 더보기
Programmers - 문자열 압축 / Javascript function solution(s) { //문자열 길이 1인 경우 if (s.length === 1) return 1; let strings = []; let answer = 0; //첫번째 반복문은 압축할 문자열 길이 1부터 시작 ~ 문자열 길이 / 2 for(let i = 1; i 1? string + cnt + current : string + current; cnt = 1; } } strings.push(string.length); } return Math.min(...strings); } 남는 문자열 처리하는걸 고심하다가 푸는데 오래걸렸다. 겨우 다풀었나 했는데 테스트케이스 5번에서 틀렸다고 나와서 한참 보니까 문자열 길이 1인 경우를 생각안하고 돌림ㅠㅠㅠㅠㅠ 이래서 제한사항도 유심히 읽어보고.. 더보기