구현기 13

Github Page + Github Action으로 CRA 리액트 앱 자동 배포하기

https://sadie100.github.io/CypherTypeTest/ 사이퍼즈 성향 테스트 sadie100.github.io 3년 전에 만들고 Netlify를 통해 배포했던 사이퍼즈 플레이어 타입 테스트.도메인도 만료된 지 한참 전이고, 얼마 전 Netlify에서도 배포했던 프로젝트가 expire됐다는 메일을 받았다.이대로 묵혀둘까... 했는데 그래도 만들어둔 게 아쉬워서,별도의 도메인 구매가 필요 없는 깃헙 페이지를 이용해서 배포하여영원히 사는 프로젝트로 만들기로 했다.하는 김에 깃헙 액션을 통해 CI/CD도 연결해서, 거하게 리팩토링 작업을 했다.  Github Action을 위한 yaml 파일 만들기깃헙 액션 워크플로우를 만들기 위해서는 yaml 파일이 필요하다.해당 워크플로우가 어떤 Git..

GPT 주도 개발로 코딩하기 - HTML/CSS/JS 기반 프로젝트를 리액트 프로젝트에 이식하기(feat. 카드 짝 맞추기 게임)

이전에 GDD(Gpt Driven Development)로 만들었던 카드 짝 맞추기 게임. GPT 기반으로 코딩하기에는 확실히 HTML+CSS+Vanilla JS 스택을 선택하는 것이 가장 심플하고 대답도 잘 해주는 선택지겠지만... 나는 웹 게임을 붙여서 개발하겠다는 취지로 빌드해 둔 Next.js 앱이 있었고 거기에 카드 짝 맞추기 게임을 이식하고 싶었다. 그래서 GPT가 1부터 100까지 짜 준 게임 코드를 리액트 기반으로 바꾸기로 했다! 물론 GPT에게 코드를 맡겨서. 하지만 HTML 기반 프로젝트를 처음부터 코딩하는 것과 다르게, 이미 존재하는 리액트 기반 프로젝트에 코드를 변환하여 이식하는 일은 쉽지 않았다... 예전엔 순도 100%의 GPT 코드만으로도 잘 돌아가는 게임을 만들 수 있었지만,..

GPT 주도 개발로 코딩하기 - 카드 짝 맞추기 게임

최근 심심한 나머지 GPT를 활용해서 카드 짝 맞추기 게임을 개발한 적이 있었다. 직접 머리 싸매고 코딩하기는 너무나 귀찮아서, GPT가 시키는 대로만 복사해서 만들었다. 그 결과, 약 30분만에 HTML, JS, CSS로 애니메이션이 담긴 멀쩡한 웹 게임 하나를 만들 수 있었다. 직접 타이핑한 코드 한 줄도 없이, 오직 GPT의 대답만으로. 그 과정이 무척 재밌었고, 마침 GPT가 예전 Chat 기록을 이제 다 보관해주는 만큼, 내 GPT 주도 개발 과정을 프롬프트와 결과 위주로 기록하려 한다. 먼저 GPT 님이 카드 짝 맞추기 게임을 모르실 수도 있기 때문에, 확실히 이 게임에 대해 알고 있는지 확인하고자 했다. 잘 알고 계셨다. 그래서 복잡하게 프롬프트 짤 것 없이 간단하게 만들어 달라고 했다. 자..

[프로그래머스 코딩테스트 연습] 기능개발 JS

https://school.programmers.co.kr/learn/courses/30/lessons/42586?language=javascript 나의 풀이 슈도 코드 progresses 돌려서 완료일까지 남은 날짜수 담은 goalQueue 배열 정의 현재 날짜 date 변수를 정의하고 answer에 넣게 될 complete 변수 정의 goalQueue의 맨 앞에 있는 애 가져옴(goal) 해당 goal과 date 비교 만약 date가 goal보다 크거나 같으면 pop으로 goalQueue에서 비우고 배포 처리, complete 1 증가 위 3~5를 계속 반복. goal이 date보다 작게 나오면 반복 탈출 한번에 배포처리한 수 complete를 answer에 넣고 complete 0으로 초기화. d..

[프로그래머스 코딩테스트 연습] 베스트 앨범 JS

https://school.programmers.co.kr/learn/courses/30/lessons/42579 나의 풀이 슈도 코드 먼저 장르별로 담고 있는 음악과 총 재생수를 저장하기 위한 genreDic 딕셔너리를 정의한다.genreDic = { classic : { music : [각 장르에 담긴 고유번호 배열], count : 각 장르의 재생수 합 }, pop : { ... }, ... } genres를 반복문으로 돌리면서 genreDic의 각 장르별 music 배열 데이터를 채운다. genreDic 객체의 각 장르별 music 배열을 반복문으로 돌리면서 plays 배열을 참고해 count 합계를 계산하고, genreDic의 count를 채운다. genreDic의 장르들을 count들로 sor..

[Spring Boot] Access denied for user 'root'@'localhost' (using password: YES)

팀 프로젝트에서 서버 측과 연동하기 위해 스프링부트와 낮부터 씨름하고 있는데 계속 에러가 났다. 문제 상황 빌드 과정 전체가 에러의 연속이었는데, 어찌어찌 헤쳐나가다 mysql을 깔래서 깔고 서버를 실행시켰더니 에러 발생. [Spring Boot] Access denied for user 'root'@'localhost' (using password: YES)위 에러메시지를 중심으로 찾아보니 mysql 로그인 오류라고 한다. 그러나 해당 메시지로 구글링을 하면 mysql 자체에서의 해결법이 나오고, 나처럼 스프링부트 환경에서 이런 에러를 해결한 경우가 없어서 조금 헤맸다. 해결법 gradle 사용 시 스프링 부트에서 mysql 연동을 하기 위해서는 src/main/resour..

Netlify로 빌드한 웹사이트에 URL parameter를 붙여 접속하면 404가 뜰 때 해결법

react app gets 404 when fetching url parameter 이 글을 쓰게 만든 문제 상황 자체는 위 키워드와 같았다. 빌드한 리액트 프로젝트에 url 파라미터를 붙여서 접속하면 자꾸 404가 뜨는 것. 아래에서 자세히 쓸 거지만... 주요 원인이 클라이언트 사이트 라우팅 등과 관련된 것 때문이라는 걸 몰라서 더 헤맸다. 때문에 나와 같은 상황에 처한 누군가가 비슷한 키워드로 서치했을 때 원인을 바로 파악했으면 하는 마음에 내가 서치했던 키워드를 글 상단에 추가해 보았다. 문제 상황 나의 토이프로젝트인 사이퍼즈 성향 테스트는 카카오톡으로 테스트 결과를 공유하는 기능이 있었다. 즉 해당 버튼을 누르면 카카오톡으로 결과 페이지 url을 전송해서 다른 사람들로 하여금 접속할 수 있게 하..

React로 Full Height 화면을 만들었던 과정

브라우저 창에 꽉꽉 차는 화면.Height를 full로 하기 위한 여정을 기록한다.먼저 간단하게 전체 화면을 구성하는 컨테이너 div태그의 height를 100vh로 주었다.vh란, 뷰포트 높이에 따라 달라지는 단위이다. 1vh는 뷰포트 높이의 1%이므로, 100vh는 뷰포트의 100%, 즉 full 높이를 말한다고 볼 수 있다.이렇게 하니 정말 화면이 꽉꽉 차 보인다.하지만 모바일 화면으로 접속해 보니 이상했다.간격이 적용되지 않는 문제는 둘째치고, 화면이 묘하게 아래로 처져 있었다.찾아보니 모바일에서는 vh 계산을 할 때 상단에 위치한 url바와 하단의 네비게이션바의 높이까지 포함하여 계산한다고 한다. 그래서 조금씩 어긋나게 되는 것.구글링을 통해 해결방안을 구했다.먼저 url바와 네비게이션바의 높이..

Netlify로 서버리스 프로젝트 배포하기

프로젝트를 빌드하기로 했다. 구글에 치니, netlify를 이용하면 간단하게 깃허브 프로젝트를 빌드할 수 있다는 말이 굉장히 많았기에 netlify 이용! 회원가입하고 깃허브에서 빌드할 프로젝트 레포지토리를 선택 후, 빌드한다. 빌드 세팅은 이렇게 해 주었다. 사실 여러 에러를 겪은 결과인데, 처음엔 Build command에 npm run build만 저장하고 빌드했다. 그랬더니 에러 발생. 각 버튼을 클릭하면 에러 이유를 알 수 있는 Deploy log를 볼 수 있다. 쭉쭉 내려 보니 Treating warnings as errors because process.env.CI = true.라는 문구와 함께 컴파일 실패 문구가 떠 있었다. 구글링해보니 빌드 명령어를 npm run build에서 CI=fa..

백준 2941 : 크로아티아 알파벳 js 풀이

문제 링크 다음처럼 풀었다. const fs = require("fs"); const input = fs.readFileSync("/dev/stdin").toString().trim(); const chroa = ["c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="]; let result = input; const getChroa = (text, word, count = 0) => { if (text.indexOf(word) === -1) { result = result.replaceAll(word, "0"); return count; } else if (text.indexOf(word) !== -1) { count++; return getChroa(text.replac..