프론트엔드 개발 환경 체크리스트(2023)

🗓 2023-03-31

Image by Andrea Piacquadio from Pexel

프론트엔드 프로젝트를 시작할 때마다 매번 정해야 하는 것들이 있습니다. 개발 환경과 개발 스택을 정하고 대부분 Git이겠지만 형상관리 도구도 정하고 브랜치를 어떻게 관리할지도 정해야 하고 버저닝은 어떻게 해야 할지 등등 프로젝트를 새로 시작할 때면 매번 점검하거나 새롭게 정해야 할 것들이 많았어요. 물론 이미 오랜 기간 숙련된 팀의 경우 기존의 방식을 활용할 수 있겠지만 매번 기존 프로젝트 진행했던 문제가 됐던 것들은 항상 있었기 때문에 같은 방법과 도구들을 그대로 사용하는 경우는 없었던 것 같아요. 조금이라도 달랐어요. 프로젝트들이 짧은 숨으로 진행되는 회사라면 그 변경 정도가 적겠지만 긴 숨으로 진행되는 프로젝트들이 많은 회사의 경우 가끔씩 새로운 프로젝트가 시작되기 때문에 시작할 때마다 "뭐부터 정해야하지?"라는 고민에 빠집니다.

특히 매번 새로운 디펜던시 설치 및 설정 작업도 해야 합니다. 적어도 버전이라도 올리게 되죠. 버전을 올리면 새로운 디페던시와 다를 게 없어지는 경우도 많습니다 :( 결국 매번 새롭습니다. 단 한 번도 기존의 환경을 그대로 사용하는 법은 없었어요. 그러다 보니 몇 번 그때그때마다 제가 잊어버리지 않으려고 개발 환경을 구축하는 방법에 대한 글을 종종 작성했었는데요. 그 글들은 유통기한도 짧았어요. 환경을 구성하는 도구 하나만 해도 메이저 버전이 업데이트되면 이런저런 설정을 다시 만져줘야 했고요. 서로 연동이 필요한 도구들의 경우 필요한 다른 도구의 업데이트로 인한 변화에 많은 시간을 들여 대응해야 하는 작업도 해야 했죠. 프로젝트별로 기본적인 도구들은 비슷할지 몰라도 어떻게 조합하느냐에 따라 정말 다양한 설정 방법들이 존재합니다. 디펜던시가 많은 도구일수록 골치 아프죠. 요즘은 점점 나아지고 있다고 생각합니다.

유통기한이 짧은 실제 설정에 대한 내용은 공홈만 따라가도 크게 어렵지 않으니, 프로젝트를 시작할 때 결정해야 할 도구들의 목록만 체크리스트처럼 관리하고 새로 생기거나 관심이 가는 도구들을 추가해두면 나중에 하나씩 뿌러트리면서 정하기 좋을 것 같다는 생각을 했어요. 매번 프로젝트를 시작할 때마다 빼먹거나 게으름 때문에 고생한 경우가 많았습니다. 이렇게 미리 정해야 할 것들의 목록과 후보들을 정리해 두고 하나하나 검토하면서 기존의 사용했던 도구들도 회고할 겸 같이 작업하는 분들과 함께 논의하면 좋을 것 같습니다.

소스코드 형상관리도구

형상관리 도구는 특별한 경우가 아니라면 깃(git)을 사용합니다. 리모트 저장소는 선택해야겠지만 이것도 특별한 경우가 아니라면 깃헙(Github)을 선택하겠죠. 상황에 따라 다른 선택지도 있어요. 깃헙 다음으로 유명한 서비스로는 깃랩(Gitlab)이 있고요. 지라로 유명한 아틀라시안에서 서비스하는 비트버켓이 있습니다.(Bitbucket) 웬만해선 깃헙이 좋겠죠.

로컬에 깃 저장소를 git init 으로 만드셨다면 제일 처음 해야 할 일은 .gitignore 파일을 만드는 것입니다. 기존에 사용하시는 것이 있으시다면 그냥 복붙하셔도 좋고요. 새로 만드셔야 한다면 쌩으로 만드시는 것보다는 gitignore.io 라는 서비스를 사용하시는 것을 추천드립니다.

image

이런 식으로 환경에 맞는 키워드로 태그를 추가하시면 원하시는 .gitignore 를 깔끔하게 만들어줍니다. 좀 과하다 싶으면 어차피 텍스트니까 직접 수정하면 됩니다.

패키지 매니저

명확히는 Node.js Package Manager죠. 나중에 deno가 대세가 된다면 패키지 매니저의 역할이 모호해지겠지만 그때가 돼도 비슷한 다른 도구는 필요할 것 같아요. 현재는 패키지 매니저가 프론트엔드 프로젝트에서 매우 중요한 역할을 합니다. 디펜던시를 설치하고 관리할 수 있게 해주니까요. 예전에는 원엔온리로 npm이었죠. 변칙적인 bower도 있었지만 제외할게요. 요즘은 잘 안 쓰기도 하고요. 이제는 npm 말고도 선택지가 조금 생겼습니다. yarn과 pnpm를 사용할 수 있습니다. 노드의 빌트인 도구라는 이점을 가진 npm이 비해 각자 내세우는 특징과 장점이 있습니다. 요즘은 yarn과 pnpm, npm 모두가 닮아가면서 상향 평준화가 된 느낌입니다. 이런 경쟁 좋죠. 몇 년 전까지는 모노리포 때문에 yarn을 고려했었는데요. 그때 당시 필요했던 workspace 기능이 이제는 모든 도구에서 충분히 지원하고 있습니다.

제 개인적인 생각은 특별히 이유가 생기기 전까진 그냥 npm 쓰면 될 것 같아요. 속도 문제도 패키지 매니지의 속도가 영향을 줄 수 있는 게 배포할 때 정도일 것 같은데 요즘엔 캐시를 이용한 방법으로 보완할 수 있고요. 패키지들 이 설치되는 속도보다 번들링 되는 속도가 더 신경이 많이 쓰이는 것 같아요. 이것도 다양한 방법으로 개선되고 있죠.

정적 분석 도구

정적 분석 도구는 소스코드를 텍스트 그대로 분석해서 유용한 기능을 제공하는 도구입니다.

예전에는 도구가 정말 다양했어요. 어떻게 보면 자바스크립트 개발 환경은 정적 분석 도구들의 발전에서 시작됐던 것 같아요. 참 다양한 도구들이 많이 나왔었습니다. 여차저차해서 결국 정적 분석 도구 중에서 제일 많이 사용되는 것은 위 두가지 툴입니다.

코드 스멜을 잡아주거나 프로젝트 컨벤션을 유지하는데 독보적인 ESLint, 대충 문법에 맞게 코딩하고 저장 한 번 눌러주면 코드가 깔끔하기 정리되는 프리티어(Prettier). 이제 코딩하는데 없어서는 안 될 필 수 도구입니다. 특히 프리티어는 코드의 인덴테이션을 개발자가 직접 정리하는 시간을 아예 없애버렸죠. 예전에는 제일 많이 눌렀던 단축키가 인덴테이션을 정리하는 키였던 것 같은데 이젠 누를 일이 거의 없습니다. 다른 언어를 사용할 때면 프리티어가 없다는 게 얼마나 아쉬운지, 그 가치를 재발견하게 됩니다.

여긴 선택의 여지가 없네요. 모두 필수로 설치하시고 사용하시는 에디터나 IDE에서 제공하는 방법에 맞게 설정해주세요.

번들러

번들러는 그 계보 안에서 태스크러너 grunt ,gulp로 시작해서 많은 발전을 이뤄왔어요. 빌드 과정을 자동화 하는 태스크 러너에서 모듈 번들러와 태스크러너를 통합하는 형태로 발전했습니다. 모던 프론드 엔드 개발 환경이 정적 분석 도구로 시작했다면 번들러의 발달을 통해 비로소 꽃피웠다고 볼 수 있죠. 모든 도구들을 통합해 주는 역할을 했으니까요. 정말 다양한 번들러 중에서 왕좌를 거머쥔 걸출한 스타는 바로 웹팩(Webpack)입니다. 한동안 원톱 체제를 유지했지만 점점 왕좌를 넘보는 경쟁자들이 많이 생겨났습니다. 다양한 강점으로 무장했죠.

고려해볼만한 번들러 목록입니다.

웹팩을 제외하고 이 중에서 기회가 되면 한 번 써보고 싶을 만큼 안정화됐다고 느끼는 것은 es빌드(esbuild)와 비트(vite), 퍼셀(Percel)입니다. 나머지도 좋은 도구입니다만 생태계나 호환성을 고려했습니다. 그중에서도 es빌드의 경우는 그 속도 때문에 조만간 프로젝트 적용해 볼 예정입니다. 같이 일하시는 분들이 적용해 보신 후 속도 면에서 몇 배로 개선된 부분이 있었다고 들었습니다. 그 배경에는 내부적으로 바벨로 커버했던 트랜스파일러가 내장돼 있어서 성능적으로 개선할 여지가 더 있었을 것 같고요. 고(Go)라는 언어의 장점도 영향이 있는 것 같습니다. 새로 프로젝트를 시작한다면 es빌드를 사용해 보려고 합니다.

트랜스파일러

트랜스파일러가 맞지만 컴파일러라고도 자주 불립니다. 얼마 전까지만 해도 바벨로 대통합 시대였습니다. 번들러 원탑이 웹팩이면 트랜스파일러 원탑은 바벨이었죠. 초기에는 아직 브라우저가 지원하지 않는 최신 자바스크립트 스펙을 사용할 수 있게 해주거나 오래된 브라우저가 요즘 스펙을 지원할 수 있게 변환해 주는 역할을 했었는데요. 바벨 자체가 애초에 자바스크립트 문법을 확장할 수 있는 토대를 제공하고 있기 때문에 JSX를 변환한다던지 타입스크립트를 변환하는 등의 역할도 제공하고 있습니다. 그래서 언어에 새로운 문법이나 기능까지 추가할 수 있게 해줍니다. 예전에 바벨로 변환된 코드를 살펴보다가 Async/Await을 스위치문으로 구현한 것을 보고 이미를 탁 쳤던 기억이 납니다.

그리고 swc라는 걸출한 새로운 도구가 등장했고 esbuild도 트랜스파일을 지원하기 때문에 경쟁자가 조금 생겼습니다. 제가 최근 진행한 토이 프로젝트에서 직접 swc 사용해 봤는데요. 웹팩과 스토리북 등과의 연동성에서 무엇 하나 빠지는 것 없이 완벽하게 잘 동작했습니다. 아직 실험적이지만 React-Fresh도 동작합니다. 실험적이라고는 해도 딱히 아주 잘 동작합니다. 특히 테스트 도구인 jest를 사용할 때 좋았던 것 같아요. 설정이 매우 간결하고 깔끔하게 끝났습니다.( https://swc.rs/docs/usage/jest ) 타입스크립트는 타입 체커(tsserver), 컴파일러(tsc) 이 두 가지로 동작하는데요. 각각 독립적입니다. swc가 커버하는 것은 컴파일러만 입니다. swc는 자체적인 설정 파일 .swcrc를 사용하지만 타입 체커를 위해서 tsconfig.json도 만들어야 합니다. 그래야 에디터나 IDE에서 동일하게 동작합니다.

모두 좋은 도구들이기 때문에 무엇을 선택해도 특별히 문제는 없어 보입니다. 중요한 건 프로젝트에 필요한 다른 도구와의 궁합인 것 같습니다.

테스트

이제는 FE단도 테스트 도구들이 많이 안정화된 것 같아요. 고민스러운 선택지가 조금 있긴 하지만 모두 좋은 도구들입니다. 유닛 테스트부터 E2E 테스트까지 이제는 정말 쉽게 테스트를 프로젝트에 통합할 수 있습니다. 테스트 도구도 몇 가지 종류로 나눌 수 있지만 현재로 가장 이상적이라고 생각하는 도구들만 종류 구분 없이 나열해 보겠습니다.

우선 유닛테스트를 위해 제스트(Jest)는 필수인 것 같습니다. 그리고 퍼피티어(puppeteer)나 플레이라이트(playwright)와 연동해서 E2E 테스트까지 커버할 수 있습니다. 하지만 E2E는 그냥 싸이프레스(Cypress)를 쓰시는 게 가장 속 편하실 겁니다. 싸이프레스가 조금 무거워서 제스트로 유닛테스트와 E2E테스트를 모두 커버해 보고자 퍼피티어나 플레이라이트와 연동을 몇 번 해봤는데요. 불편하고 부족합니다. 여러 면에서 결론은 싸이프레스였습니다.

싸이프레스도 유닛테스트가 가능합니다만 기본적으로 브라우저가 하나 뜬 상태로 테스트가 돌아가기 때문에 무겁습니다. 유닛테스트는 제스트로 자주 돌리고 E2E는 싸이프레스로 선택적으로 진행하는 게 가장 개발자 경험이 좋았습니다.

E2E 도구를 선정할 때는 지원하는 브라우저에 조금 덜 민감해도 될 것 같습니다. 테스트 케이스는 예상치 못했던 크로스 브라우징 이슈를 추적하려는 목적으로 작성하는 것이 아닙니다. 저희가 작성하는 테스트 케이스는 개발자가 알고 있고 예측할 수 있는 졍상적인 동작을 테스트하는 것입니다. 개발자의 실수를 빨리 파악하기 위함이지 브라우저의 실수를 파악하려는 것은 아닙니다. 애초에 매번 크로스 브라우징 이슈를 염두 해서 테스트 케이스를 작성할 수도 없고요. 가끔 얻어걸릴 뿐이지 그리 유용하지도 않습니다. 그래봐야 사용하면 안 되는 API를 사용했을 때의 오류뿐입니다. 이런건 손으로 테스트하는 편이 좋습니다. 픽셀이 틀어지거나 하는 디자인적인 오류의 테스트라면 더더욱 코드로 테스트하면 안 됩니다. 테스트 케이스를 읽기 힘들 뿐만 아니라 깨졌을 때 바로 직관적으로 문제를 발견하기도 쉽지 않아요. 유용하지가 않은 거죠. 그런 테스트가 반드시 필요하다면 자동화된 이미지 비교를 고려하는 것이 좋습니다.

프레임웍

프레임웍은 정말 크고 작은 변화들이 많았습니다. 다양한 철학과 구현을 담은 여러 프레임웍들이 나타났다 사라졌고 요즘은 예전만큼 과열되진 않았지만 그래도 종종 새로운 프레임웍이 나옵니다. 아직까지는 리액트(React), 뷰(Vue), 앵귤러(Angular)가 천하 삼분지계로 유지되고 있습니다. 물론 점유율로 따지면 삼분은 아닙니다. 리액트 점유율은 어디에서 조사하든 항상 절반을 많이 넘습니다. 한때 뷰가 리액트를 맹렬히 따라잡으며 빠르게 성장했었는데요. 요즘은 또 시들시들해졌어요. 그때 뷰를 선택했던 프로젝트들도 다시 하나둘 리액트로 갈아타는 추세입니다.

저는 3개의 프레임웍 모두를 실무 프로젝트에서 사용해 봤었는데요. 저도 개인 적인 취향은 리액트인 것 같습니다. 언아일체(프로그래밍 랭귀지 === 자아)이신 분들처럼 프아일체(프레임웍 === 자아)이신 분들도 계시기 때문에 조금 조심스럽지만 예나 지금이나 판을 바꾸거나 눈에 뛰는 개선을 앞장선 건 항상 리액트 커뮤니티 였다고 생각합니다. 뷰가 빠르게 따라붙을 수 있었던 이유도 리액트의 그것들을 빠르게 흡수했기 때문이라고 생각합니다. 뷰의 반응형 시스템은 훌륭했다고 생각합니다. 이름은 리액트지만 뷰가 더 리액티브하죠. 하지만 뷰는 그 이상이 없었던 것 같아요.(개인 생각입니다) 리액트도 Mobx를 활용하면 Vue만큼 리액티브해집니다.

프레임웍은 항상 선택지가 많았습니다. 아마 앞으로 더 생겨날 겁니다. 이미 팀에 충분히 익숙한 프레임웍이 있다면 그것을 사용하시면 될 것 같습니다. 익숙한 프레임웍이 제각각이거나 아예 새롭게 시작하는 프로젝트라면 아직까진 고민 없이 리액트를 추천하고 싶습니다. 첫번째 이유로는 커뮤니티를 꼽을 수 있을 것 같고, 두 번째는 그 순수함입니다. 프레임웍이 의도한 코드 자체가 함수형 프로그래밍의 순수함을 추구하고 또 너무 순수해서 매직이 거의 없죠. 그냥 자바스크립트니까요. 그래서 이것저것 조합해서 다양한 요구나 상황에 대응하기 좋습니다.

스벨트는 초기에 데모를 보고 "와"하는 감탄은 있었지만 실무에 사용하기엔 글쎄라는 생각이 듭니다. 이후 단순하게 몇 번 코드를 실행해서 결과만 확인해 본 것이 전부입니다만 저 같은 경우는 스벨트가 하는 내부 작업들을 어느 정도 이해하기 전까지는 쓰기 부담스러울 것 같습니다. 안돼도 문제지만 왜 되는지 모르니 더 불안해요.

몇 년 전까지 만 해도 새로 나오는 프레임웍들에 대해 관심이 많았어요. 뭔가 나오면 항상 설치해서 이것저것 해봤죠. 어떤 새로운 아이디어와 철학이 있는지 궁금하기도 하고요. 그냥 재미도 있었어요. 하지만 최근엔 크게 눈에 띄는 것도 없고 크게 관심을 두지 않는 것 같아요. 저는 당분간 걸출하고 안정적인 신예가 생길때까진 리액트로 충분할 것 같습니다.

상태관리도구

상태관리도구는 선택의 여지가 없는 경우가 많아서 많이 다룰 게 없을 것 같아요. 뷰라면 뷰엑스를 써야 하고요. 리액트도 뭐 아직까진 리덕스(redux)를 써야 합니다. 요즘은 리덕스 툴킷으로 거의 표준화되는 것 같아요. 거기에 리액트 쿼리(react-query)를 섞어서 많이들 사용하죠.

그밖에 유용한 상태관리도구로는 프레임웍 구분없는 범용성을 가진 몹엑스(Mobx)와 엑스테이트(XState)가 있습니다.

리액트 + 몹액스 조합으로 프로젝트를 하나 개발했던 경험이 있는데요. 꽤 괜찮았습니다. 스토어를 기존과 조금 다르게 바라봐야 해서 어떻게 분리해야 할까 혼란이 있었는데요. 다시 한다면 더 잘할 수 있을 것 같습니다. RTK 조합과 비교해 본다면 어느 게 더 좋다기보다는 취향 차이 정도로 보시면 될 것 같아요. 하지만 아무래도 커뮤니키 파워를 보면 RTK가 나아 보이긴 합니다. 제 느낌이지만 최근에는 몹엑스도 조금 상승세가 꺾인 것 같아요. 클래스 대신 함수형 스타일로 모듈을 만들 수 있다면 더 많이 사용할 것 같은데 아쉽네요.

리코일도 고려해 볼만 한데 저는 왜인지 손이 안 가서 아직 제대로 본 적이 없습니다.

XState는 복잡한 상태 기계를 구현할 수 있는 FSM(Finite state machines)의 자바스크립트 구현체입니다. 자체적으로 지원하는 기능을 이용하면 상태관리 도구로도 손색이 없지만 일부 크고 작은 제어 구조 정도에만 사용할 수도 있습니다. 그렇기 때문에 리덕스로 스토어를 사용하면서 일부 복잡한 상태를 갖는 UI 컴포넌트에만 지역적으로 XState를 활용해 제어 구조를 간결하게 유지할 수 있습니다. 저는 실무 프로젝트에는 적용해 본 적은 없고 공부하면서 이런저런 테스트만 해봤는데요. 외부 디펜던시를 늘리는 것에 매우 보수적인 저였지만, 한 개의 컴포넌트에서 사용되더라도 적절하게만 사용한다면 그 충분한 가치가 있겠다고 생각했습니다. 기본적으로 함수형을 지향하고 유닛 테스트까지 충분히 고려한 도구입니다. 실무에 언제 써볼까 호시탐탐 기회만 노리고 있습니다. 물론 간단하게 FSM을 직접 구현한 것에 비해 얻는 이점이 있는지 잘 따져봐야겠습니다. 간단한 경우는 미리 정해진 상태와 분기만으로 충분히 구현할 수 있으니까요.

주스탠드

주스탠드(Zustand)와 조테이?(Jotai)와 같은 차세대 상태관리도구로 불릴만한 것들도 있습니다. 주스탠드는 구현 코드를 살펴보니 참 심플했습니다. 예전 초창기 리덕스 코드를 뜯어봤을 때의 그 느낌이 들어서 좋았습니다. 이렇게 어떻게 동작하는지 쉽게 이해할 수 있는 도구는 마음이 놓이고 왠지 정이 갑니다. 그리고 주스탠드의 곰 이미지를 보면서 오픈소스도 브랜딩이 중요하다는 생각을 다시금 하게 됩니다 :)

CSS도구

카테고리를 뭐라고 이름 지어야 할지 고민하다가 CSS 도구라고 했습니다. CSS 관련도구는 그동안 양상이 조금 바뀌었어요 처음에는 Sass, Less, Stylus와 같이 전처리 도구를 이용한 CSS 확장한 언어들이 대세였던 반면 최근엔 CSS를 자바스크립트 안에서 해결하려는 도구들이 대세가 되었죠. 스타일드 컴포넌트(Styled-component). CSS in JS, 테일윈드(tailwind) 등의 도구가 있어요. 이쪽에서도 스타일드 컴포넌트가 주류였다가 테일윈드에게 바통을 넘겨주고 있습니다. CSS라는 언어의 한계를 또다른 언어로 확장한 도구들은 CSS 자체가 발전함에 따라 점점 그 인기가 시들해지는 것 같아요. 킬링 포인트였던 CSS Variable과 Nesting이 이젠 표준으로 지원하죠. 관련해서 PostCSS는 전처리 도구에 가깝지만 유용하게 사용되고 있습니다. CSS계의 바벨이라고 볼 수 있는데요. 코드베이스에는 최신 버전의 CSS문법을 사용하고 빌드할때 이를 지원하지 않는 브라우저에서도 사용할 수 있도록 변환해 줍니다. 테일윈드와 PostCSS 조합으로 많이 사용합니다.

스타일드 컴포넌트와 테일윈드는 실무에서 사용해 봤는데요. 둘 다 장단이 있어요. 스타일드 컴포넌트와 테일윈드 모두 CSS를 자바스크립트 컴포넌트 안으로 모듈화하려는 의도는 동일한데요. 방법이 조금 다릅니다. 길게 이야기 하지 않고 둘의 단점만 꼽자면 스타일드 컴포넌트는 컴포넌트가 너무 많아지고요 테일윈드는 class 코드가 너무 길어져요. 검토해 보시고 팀 취향에 맞는 도구를 선택하시면 좋을 것 같습니다.

스토리북

카테고리를 따로 구분할 필요가 없네요. 아직까진 독보적입니다. 스토리북은 FE개발자에겐 축복이라고 할 수 있을 정도로 유용한 도구입니다. 매번 테스트할 때마다 서버를 열어 찾아갈 필요 없이. 분리된 각 컴포넌트들 사이에서 필요한 컴포넌트를 쉽게 열어 다양한 방법으로 시각적인 확인을 할 수 있습니다. 단일 컴포넌트를 개발할 때도 유용하며 개발된 컴포넌트들을 전체적으로 조망할 때도 유용합니다. 스토리북과 싸이프레스 같은 E2E 테스트 도구를 연동해 컴포넌트 테스트를 돌릴 수도 있습니다.

FE개발자 뿐 아니라 개발이 완료된 컴포넌트들을 기획자나 디자이너와 공유하고 의견을 나눌때도 유용합니다. 특히 디자인 시스템을 도입한 프로젝트의 경우 스토리북은 그 시작이자 끝에 위치하는 도구입니다.

다만 워낙 무거운 도구다 보니 내부 환경 디펜던시와 자주 충돌을 일으킵니다. 뭐하나 업데이트하면 실행이 안되고 그래요. 그래도 예전에 비하면 융통성을 많이 갖게 됐어요. 내부 번들러도 변경할 수 있더군요. 갈수록 나아질 거라 기대해 봅니다. 최근에 swc와 연동할때도 걱정을 많이 했는데 생각보다 금방 설정을 끝낼 수 있었습니다.

마무리

이렇게 FE 프로젝트의 개발 환경을 구성하는 도구는 종류도 많고 각 종류별로 대안까지 많습니다. 아마 앞으로도 유용한 도구들이 많이 생겨나겠죠. 물론 종류도 생겨날 수 있고요. 더 나은 도구의 출현이나 기존 도구들의 개선으로 매번 새로운 프로젝트를 시작할 때면 고민이 많아집니다. 각 종류별로 팀의 다양한 의견을 수용해 팀과 프로젝트에 맞는 옳은 개발 환경을 구축해야겠습니다.

♥ Support writer ♥
with kakaopay

크리에이티브 커먼즈 라이선스이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.

© Sungho Kim2023