사실 처음에는 어느 정도 규모가 있는 회사에서 인턴을 준비하고자 했으나 역시 전공과목을 많이 듣는 학기라서 준비할 시간이 많지도 않았고, 연세대학교 창업지원단에서 지원할 수 있는 스타트업 인턴십이 무려 3000대 과목 6학점을 지급한다고 해서 그중 조건이 좋아 보이는 ABM에 지원하였다.
지원 당시 ABM의 자사 앱인 ‘엔퍼센트’의 유지/보수 및 backend 개발에 기여하는 것을 목표로 하였다. 연세대학교 창업지원단 인턴 전에도 개인적으로 해왔던 토이 프로젝트나 각종 창업대회, 팀 프로젝트를 경험하고, lablup이라는 회사에서 backend.ai라는 서비스에 dev-ops팀으로 기여하면서 느꼈던 부족한 점들을 보완하고자 했다. 가장 먼저 느꼈던 것 중에 하나는 내가 작성하는 코드가 과연 효율적인 코드인지 검증하는 과정이 필요하다는 것이었는데, 이는 단순히 혼자서, 혹은 나와 비슷한 수준의 개발자와 팀으로 협업하는 것 이외에도 훌륭한 개발자 아래에서 코드리뷰, 스타트업 특유의 빠른 피드백을 받을 수 있는 환경이라면 더욱더 탄력을 받을 것이라고 생각하였다.
또한 DevOps 팀에서는 이미 베타 런칭을 완료한 서비스의 버그 픽스, 추가 기능 구현에 조금 더 초점을 맞추었다면 이번 인턴에서는 product가 개발되어 가는 cycle을 온전히 경험해보고 싶다는 생각 또한 들었다. 그리고 backend로 지원한 가장 큰 동기는 각종 데이터들에 대해서 handling 해보고 내가 이러한 데이터를 설계하는 것에 대해서 실습을 할 수 있는 기회가 있었으면 좋겠다고 생각해서 데이터들을 DB에 저장하고 관리하고 가공하는 backend 엔지니어 포지션을 희망했다.
그렇게 backend 엔지니어로 지원을 하고 화상으로 어느 정도 기본적인 질문 + 자기소개서에 대한 질문을 받은 후, 며칠 후 이메일로 합격메일을 받을 수 있었다.
인턴으로 들어오기 전에 회사에 대해서 알아봤던 정보와 내가 맡을 것이라고 생각했던 업무와는 어느 정도 차이가 있었다. 앞서 말한 것처럼 기존의 자사 앱인 '엔퍼센트'를 개발하는 일 대신 완전히 새로운 플랫폼을 처음부터 개발하는 업무를 맡게 되었다. 그렇게 해서 취미 매칭 플랫폼인 'ourB'를 프론트엔드 인턴으로 들어온 친구와 같이 둘이서 개발하게 되었다.
프로젝트를 진행한 github repository는 다음과 같다.
https://github.com/vesselofgod/ABM_back
GitHub - vesselofgod/ABM_back
Contribute to vesselofgod/ABM_back development by creating an account on GitHub.
github.com
그래서 가장 먼저 개발한 것은 바로 회원가입/로그인 시스템을 구현하는 것이었다. 이 때 기존에 했던 프로젝트와 가장 달랐던 점은 아무래도 실사용자를 고려하여 개발을 진행해야 하기에 단순한 ID, password 중복 체크와 같은 것뿐만 아니라 사용자 인증과정, 그리고 효율적인 유저 시스템 관리를 고려해서 개발을 진행하고자 노력했다.
사실 이 과정에서 어떤 DB와 기술스택을 사용해서 하는 것이 효율적인가에 대해서 우선 backend 자체는 기존에 해왔던 프로젝트에서 비슷한 프로젝트를 진행하기도 했고 보완해야 할 점들에 대한 아쉬움이 있었기에 이 참에 조금 더 자세하게 배워보고자 node.js를 통해서 작성을 하였고, 원래는 프론트엔드에서 사용할 기술스택인 flutter에 친화적인 firebase를 사용하고자 하였다. 다만 firebase는 각종 기능들을 손쉽게 구현할 수 있도록 지원하는 점에서는 상당히 매력적이지만 정작 각종 기능들의 document들의 버전이 전혀 맞지 않고, 버전이 업데이트가 될 때마다 structure에 큰 변화가 있기에 빠른 시일 내에 기능들을 개발하기 편하다는 본 목적에 맞지 않기에 이전부터 한 번쯤 사용해보고 싶었던 mongoDB를 사용하였다.
그래서 가장 먼저 mongo DB DataBase를 구축하여 유저들의 정보들을 저장할 수 있도록 하였고, JSON web token을 이용한 인증과정을 거쳐 로그인을 할 수 있도록 하였다. 이 때 기존에 사용되던 cookie, session을 이용한 방식 대신 jwt token을 이용한 인증방식을 채택한 이유는 크게 두 가지가 있다.
가장 먼저 보안적인 측면에서 문제가 있다. 만약 중간에 man in the middle 등의 공격으로 인해서 보안에 문제가 발생을 한다면 세션 저장소를 지우는 방식 등으로 대처가 가능하지만, 만약 attacker가 클라이언트로 위장하여 attack을 진행한다면 보안에 약점이 생길 수 있다는 단점이 있다.
두 번째로는 overhead가 크다는 단점이 있다. 우선 로그인 정보를 저장하는 저장소가 server에 있기에 사용자가 많아질수록 메모리를 많이 차지하며, 매번의 request(ex : 클라이언트의 state가 변경되는 등의 request가 있을 때마다 session 저장소를 조회함)마다 DB를 조회하는 overhead가 발생한다.
이를 해결할 수 있는 방법이 바로 jwt token을 사용하는 것인데 먼저 jwt token의 경우에는 HMAC을 이용해서 token에 서명을 한다. 그렇기에 key pair를 가지고 있는 server가 이 token이 정상적인 토큰인지 인증을 할 수 있기에 보안적인 측면에서 안전하다. 또한 token을 클라이언트에 발급을 하여 인증을 하기에 필요한 경우가 아니라면 클라이언트의 상태를 매번 조회하고, 변경하지 않아도 되기에 오버헤드를 상당히 줄일 수 있다는 장점이 있기에 로그인 시에 jwt를 발행하여 사용자 인증을 진행하는 방식으로 개발을 진행하였다.
그리고 사용자가 여러 개의 device에 접속을 할 수 있다는 점을 염두에 두고 logout을 설계하였다. 사실 처음에는 이에 대해서 크게 생각을 하지 않았지만 한 유저에게 알림이 전송될 때 해당 유저가 로그인한 모든 device에 알림을 전송하는 로직을 구현할 때 해당 디바이스에 저장된 device token을 통해 해당 device에 로그인된 유저의 정보를 delete 처리하는 방식으로 구현하였다.
그리고 회원가입을 할 때 토이 프로젝트의 경우에는 개인인증 절차가 굳이 필요하지도 않았고, 실제로 사용자 인증 API를 사용함에 따라서 발생하는 비용 문제 때문에 처음으로 개발을 진행하였다.
우선 API가 상당히 여러 개가 있어서 찾아보던 중 이미 사내에서 사용하고 있는 API가 있다고 해서 Iamport를 사용해서 각각의 사용자를 인증하는 코드를 작성하였다. 공식 document를 읽어보면서 그대로 코드를 작성하고 아직 디자인이나 프론트엔드 개발이 되어있는 상태는 아니라서 postman을 통해서 test를 진행하였는데 인증 요청이 실제 휴대폰으로 날아오는 것이 상당히 신기한 경험이었다.
먼저 imp_uid를 통해서 인증 여부를 조회한 다음, 만약 인증이 되었다면 인증 정보를 담고 있는 데이터에서 unique_key를 대조해서 해당 유저가 중복으로 서비스에 가입했는지에 대한 여부를 확인하는 방식으로 개인 인증 과정을 거쳤다.
또한 회원가입 과정에서 기본적인 개인정보 이외에도 추가적인 프로필 설정을 진행해야 회원가입이 완료되는 방식으로 진행되었는데, 추후에 카테고리나 관심 지역으로 취미 매칭, 검색 과정에서 편리함을 위해서 관심분야, 관심지역에 대한 스키마를 따로 설계하였다. 또한 프로필 사진의 경우 우선은 S3에 저장을 한 후, 유저가 가지고 있는 정보에서 프로필 이미지 URL을 저장하는 방식으로 프로필 이미지를 설정하였다.
기본적인 회원가입, 로그인을 구현한 다음에는 취미 매칭 플랫폼에서 가장 핵심적인 기능인 취미 매칭에 대한 기능을 구현하여야 하는데 여기에서 가장 먼저 해야 할 일로는 각종 매칭에 기본이 되는 게시글을 Create, Read, Update, Delete 하는 CRUD API를 작성하여야 한다.
일단 처음에 CRUD API를 설계할 때는 이전에 했었던 일이기도 하고 일반적으로 그렇게 복잡하지 않은 경우가 많기에 2~3일이면 충분히 다 짤 수 있을 것이라고 생각했다. 하지만 이 당시에는 아래와 같은 디자인은 물론, 기획도 상당히 rough 하게 나온 상태라서 기획이 변경될 때마다 수정을 하는 사항들이 상당히 많았다. 여하튼 그렇다고 하더라도 사실 오래 걸리는 일은 아니었기에 기획이 바뀔 때마다 조금씩 API를 바꾸기는 했지만 큰 이슈는 없었다.
우선 모임글에 대해서 분야(단 분야는 최대 3개가 설정 가능했다.)와 관심지역을 여러 곳을 설정하도록 변경하고, 해당 게시글들 중 자신이 작성한 것과 자신이 지원한 모임, 그리고 종료된 모임을 분리하여 API로 전송했고, 해당 유저가 이 게시글을 scrap하는 기능을 추가하였다. 그리고 홈페이지에서는 자신이 관심 있는 지역과 분야에 맞는 모임글들을 띄워주는 방식으로 CRUD API를 작성할 수 있었다.
이 중에서 가장 까다로웠던 부분은 바로 모임글을 작성할 때 한 번에 여러 개의 사진을 업로드하는 기능인데 post api를 작성할 때 파라미터 설정을 다음과 같이 업로드되는 태그명과 업로드 가능한 이미지의 개수를 설정하였다.
그 후 각종 설정한 카테고리와 지역, 이미지가 선택되지 않은 경우 undefined로 설정되어 전송되는 것을 예외처리를 하여 작성할 수 있었다.
사실 모집글의 CRUD 자체의 난이도보다는 모집글에서 지원하는 가입 신청과 문의하는 것에 대한 기능을 구현하는 것이 훨씬 난이도가 높았다. 모집을 하는 과정에서 생각을 해야 할 부분들이 많았는데 우선 모집을 하는 사람과 가입을 하는 사람 사이에서의 매칭을 신청하는 관계를 효율적으로 관리하기 위해서 match schema를 설계하고 유저가 모임에 대해서 가입신청을 하면 이제 해당 신청 정보가 모임장에게 알림이 가고, 수락/거절 등의 관리를 할 수 있다. 마찬가지로 신청한 유저도 자신이 신청한 모임에 대한 정보들을 손쉽게 확인을 할 수 있도록 설계를 해야 했다.
이 기능을 설계할 때 '어떤 방식으로 앱이 작동해야 더욱 편리하게 사용할 수 있을까?'를 정말 생각을 많이 했다. 신청을 하는 사람은 신청 과정에서 자신이 이 모임에 대한 신청서를 제출하는 과정에서 사용자 편의와 비정상적인 접근을 막는 기능들을 추가하고자 했다. 먼저 모임에 대한 가입신청을 한 후 3일간 수락/거절이 없을 경우 pending out이 되도록 하는 옵션을 추가해서 무한대기를 하는 상황을 막았고, 신청자의 재신청이 1회로 제한되도록 구현하였다. 이 점에 대해서 기획자들끼리의 의견이 많이 갈렸는데, 보통 거절을 계속하더라도 신청을 넣을 수 있는 상황이 발생하면 여러모로 모임 관리에 있어서 불편한 점들이 있을 것이라고 생각했다. 또한 각각의 게시글의 update시 로그 기록기능 추가하였다. 사실 이것은 회사 입장에서 만약 로그를 가지고 있어야 하는 상황 (예를 들어서 모임글에 대한 로그를 누군가 요구할 경우)을 대비해서 이를 기록을 하도록 하였다.
모임을 관리하는 입장에서는 일정, 콘텐츠를 공지하고 어떤 분들이 참가를 하는지 여부를 확인하고 관리하는 것이 편안해야 한다고 생각했다. 그래서 모임 관리를 하는 것에 대한 부수적인 기능들을 추가해야 하였다. 그런데 백엔드에서는 정보를 제공하는 API들을 만드는 것만 하면 되는 일이라서 개발이 오래 걸리지는 않았다. 다만 프론트엔드 개발자, 디자이너분들의 노고가 느껴졌다.
앱을 사용하는 편의성 중에서 가장 중요하다고 생각하는 것이 바로 푸시알림이다. 사용자들이 취미 매칭을 신청, 관리한다고 하더라도 항상 그것만 신경을 쓰기는 어려우니까 매칭 결과 혹은 모임에 대한 사항들을 푸시 알림으로 받을 수 있는 기능은 반드시 구현을 해야겠다고 생각하였다.
가장 먼저 할 일은 유저가 앱을 사용하고 있는 device에 푸시 알림을 전송하는 것인데 이를 위해서는 해당 기기의 device token이 필요하다. firebase에서 지원하는 푸시 알림을 기반으로 만약 유저가 새로운 device에 로그인을 할 경우 device token을 받어서 device schema에 저장을 하고, 로그아웃을 할 경우 해당 토큰을 삭제하는 방식으로 관리를 하였다. 그리고 device schema에 timestamp를 설정하여 주기적으로 timestamp를 확인해서 활성토큰인지 여부를 확인하여 장기간 사용하지 않은 경우 새롭게 로그인을 해야 하도록 설정하였다.
그렇게 해서 user가 로그인된 기기에 알림 전송 기능 구현을 하게 되었는데 이때 한 명의 유저가 여러 개의 device에 로그인을 한 경우에는 해당 유저가 가지고 있는 모든 device에 알림을 전송하도록 token_list에 해당 유저가 로그인한 모든 device의 token을 저장한 다음 일괄적으로 알림을 전송하도록 코드를 작성하였다. 또한 알림을 클릭을 할 경우 관련 페이지로 이동을 할 수 있도록 알림을 카테고리별로 구분하였고, 해당 페이지 id를 통해서 관련 페이지로 전환할 수 있게 하였다. 이는 Notice Schema에 각각의 알림을 카테고리화를 했고, fid를 넣는 방식으로 해결을 했다.
그리고 처음에는 알림을 매칭 시에 API 호출을 하는 것처럼 작성을 했는데 여기에서 무언가 이상함을 느꼈다. 알림이라는 기능이 사실 매칭 매니저가 모임 매칭에 대해서 수락/거절을 했을 경우 신청자에게 푸시 알림이 가도록 설정하는 것 이외에도 유저가 매칭 신청 시 매칭 매니저에게 푸시 알림이 가도록 설정해야 했고, 이 과정에서 동일한 코드가 사용되는 것을 보고 '알림이라는 기능이 다른 곳에도 많이 사용될 수 있을 텐데... 너무 확장성이 없게 코드를 작성한 것이 아닌가...'라는 생각이 들어서 결국은 자주 쓰이는 함수들을 모아놓은 utils 파일로 분리를 했다. 이렇게 자주 쓰이는 코드를 모듈화를 하고 나니 추후에 채팅 알림을 구현할 때도 상당히 편리하게 사용했다.
이전에도 프로젝트를 하면서 socket 프로그래밍은 몇 번 해보기도 했기에 솔직히 말해서 채팅 관련 코드는 금방 작성할 것이라고 생각을 했었다. 그렇지만 생각보다 실제 서비스에서 사용할 만큼 코드를 작성하기에는 고려할 사항들이 꽤나 많았다. 우선 채팅방의 종류를 1:1 문의, 모임 채팅방 등으로 분리를 했어야 했다. 이 이슈는 생각보다 socket.io에서 꽤나 편리하게 지원을 했다. 이를 따로 설정하는 것이 아니라 room에 들어와 있는 id가 몇 개 있는지 확인하면 된다. 기본적으로 User와 Server 사이에 private room이 1개 있고 이를 이용할 경우 1:1 채팅이 된다. 그리고 여러 명이 있을 경우에는 countRoom 함수를 통해서 방에 사람이 몇 명이 있는지 계산했다.
그리고 room id를 unique 하게 부여해야 하는데 ramdom 하게 난수를 생성하려는 생각을 했으나 서비스가 커질 경우 당연하게도 room id가 겹치는 일이 발생하게 된다. 그렇기에 uuid v4를 이용해서 room id가 겹치는 일을 방지하였다.
그리고 socket 연결이 끊길 시 room 정보가 초기화되는 문제가 있었다. 이 문제가 대표적으로 혼자 프로젝트를 할 때는 별로 신경을 쓰지 않았는데 실제 서비스에 적용하자니 각 유저별로 들어가 있는 채팅방의 room id를 가지고 있어야 한다는 것을 알게 되었다. 그래서 room schema를 새롭게 만들고 나서 연결이 끊긴 경우에는 해당 유저가 들어간 채팅방의 정보들을 DB를 조회한 다음 reconnect 하는 방식으로 다시 복구를 할 수 있었다.
그런데 이때 이전의 채팅기록을 볼 수 없는 문제가 발생해서 채팅의 로그를 db에 기록한 다음, 메시지 로그 기록하고 load 하는 API 구현하는 방식으로 이전의 채팅 정보들을 다시 복구하였다. 그리고 채팅 로그에서 created라는 변수에 채팅을 친 시간을 기록하여 다시 reload 할 때 채팅을 친 시간 순서대로 다시 불러오도록 설계하였다.
그리고 socket event는 사실 별로 특별한 것은 없다. 채팅방을 입장하는 join_room 이벤트의 경우 만약 room의 정원이 0인 경우 room을 새롭게 만들고, 이미 존재하는 방이라면 해당 room에 입장을 하는 방식으로 설계하였다. room에 들어간 인원에 변동이 있는 경우에는 DB를 update 하는 방식으로 backup을 하였다. 그리고 leave_room 이벤트는 socket.leave 메소드를 통해서 room 밖으로 나가게 된다. 그리고 new_message 이벤트는 채팅을 유저가 입력했을 때 socket.on("message")으로 유저가 앱에서 채팅을 쳤을 때 server로 보내는 역할을 하고, socket.emit을 통해서 전송된 메시지를 상대방이 앱에서 읽을 수 있도록 서버에서 메시지를 뿌려준다. 그 후 await utils.sendNotice(device_tokens, notice)을 통해서 채팅방에 있는 모든 유저들에게 알림을 보낸다. 그리고 알림에 isread라는 변수를 통해서 메시지를 읽었는지 확인을 하도록 구현하였다.
그리고 사실 풀스택으로 개발을 진행할 때는 느끼지 못했던 점이 있다. socket으로 채팅을 구현하는 것을 우선 백엔드에서 코드를 작성한 다음 클라이언트 쪽에서 socket을 통해서 이벤트를 맞추고 코드를 작성하는 순서로 개발을 진행했는데, 문제는 나 혼자서 짠 코드가 잘 작동하는지 테스트를 하기 어려운 환경이었다.
그런데 마침 혼자 테스트를 할 때 주로 사용했던 postman에 socket.io를 테스트하는 환경이 beta지만 이걸로 socket event들이 잘 작동하는지 확인을 할 수 있었다. 이런 걸 보면 참 개발자들이 편하게 개발하는 환경을 제공하는 것 또한 정말 중요하다고 느꼈다. 그리고 개발자들도 이런 툴들을 잘 사용하면 더 생산성이 좋게 일을 하겠구나 느꼈던 것 같다.
그리고 이건 이전 api를 문서화하면서 유지보수/ 협업에 도움이 되고자 했다. 사실 API 문서화를 개발하면서 동시에 진행한 것은 이번이 처음인데 이러한 작업을 통해 프론트엔드 개발자가 백엔드 코드를 뜯어보지 않더라도 어떤 값을 전송하고 보내야 하는지에 대해서 명확하게 알 수 있다는 점이 좋았고, 무엇보다도 배포단계까지 완성하기에는 현장실습 인턴 기간이 짧았고, 무엇보다도 다음 개발자에게 직접 인수인계를 할 수 없는 환경이라서 반드시 작성을 해야겠다는 생각이 들었다.
문서화 작업을 하면서 느낀 점으로는 json으로 api문서를 일일이 다 작성하기에는 매우 불편했다. 그렇기에 자동화를 하였다. 비록 API에 대한 상세한 내용에 대해서는 직접 작성해야 하지만 그래도 꽤나 문서화가 간편해졌다.
두 번째로는 바로 테스트 데이터를 작성하고 테스트 환경을 통일하는 shell code를 작성하여 테스트를 진행하였다. 기획안이 아직 완성이 되지 않은 시점에서 개발을 진행해야 했기에 중간중간에 데이터 수정 사항이 상당히 많았다. 그렇기에 테스트 데이터를 사용해서 테스트 환경을 프론트와 동일하게 맞추고 invalid data가 들어가서 테스트에 지장을 주는 상황을 줄이고자 사용하게 되었다. 그리고 각종 테스트를 거치면서 서로의 테스트환경이 바뀌는 것을 방지하기 위해 테스트 환경을 초기화하는 shell, batch file을 작성하여 프로젝트를 진행했다.
세 번째로는 협업 툴들을 사용하여 개발을 진행했는데 slack과 git을 연동하면 푸시알림이 와서 따로 notification을 주지 않아도 되었기에 상당히 편했다. 그 외에도 각자 지금 하고 있는 일, 해야 할 일, 완료된 일을 trello를 이용하여 간단하게 업데이트를 했다. 이렇게 하면 일의 우선순위를 설정하거나, 협업자가 작성한 코드를 리뷰하는 과정에서 어떤 맥락으로 코드를 작성을 했는지 알기 쉬웠다.
우선 실력적인 부분에서의 발전한 점은 테스트 기반 개발, 프론트엔드 개발자와의 소통, socket 테스트 환경 경험, API 문서 작성을 하면서 성장한 것이 많았던 것 같다. 무엇보다 같이 일하는 프론트엔드 인턴이 2년 정도의 현업 경험이 있는 분이라서 협업 방식에 대해서 많이 배울 수 있었다. 기존에는 API 문서 작성법에 대해서 잘 알지 못했고, 귀찮다는 등의 이유로 잘 사용하지 않았는데 서로 협업을 하는 과정과 코드의 유지/보수 차원에서 훨씬 도움이 된다는 생각이 들었기에 앞으로도 대부분의 프로젝트에서 사용할만한 방법이라고 생각한다. 게다가 이 귀찮은 과정을 자동화하는 autogen-swagger를 통해서 보다 간편하게 API 문서화 작업을 진행할 수 있었다.
그리고 앱의 방향성과 사용자 경험에 대한 생각을 많이 했던 것 같다. ABM이라는 회사는 마케팅 중심의 수익구조를 가지는 회사였고, 실제로 사내에는 정직원 개발자는 한분이 있었다. 그렇지만 이미 다른 프로젝트를 진행하고 있었기에 자사 앱의 기획안을 바탕으로 프론트엔드 인턴과 단 둘이서 개발을 했다. 그런데 기획안이 아직 완성이 된 것이 아니었기에 outline 정도의 역할은 할 수 있었지만, 실제로 사용자들이 어떻게 이 앱을 사용할지에 대한 디테일들을 채우는 과정에서 고민을 많이 했던 것 같다. 대표적으로 모집글들의 게시판에서 사용자들에게 모든 모집글을 보여주는 것보다는 자신이 작성한 글, 자신이 지원한 모임 등을 분류해서 보여주는 것이 사용자 입장에서는 편리할 것이라고 생각을 하여 기획진들과 상의를 했고 실제로 반영이 되었을 때 뿌듯함을 느꼈다.
아쉬웠던 점으로는 나름대로 처음에는 이것저것 신경을 많이 쓰면서 코드를 작성했지만 나중에 시간에 쫓길 때에는 RESTful API의 철학하고는 꽤 많이 달라졌던 점이 아쉬웠다. 나름 알면서도 생각보다 지키기 꽤 어려웠는데 이런 점들이 곱씹을수록 스스로에게 참 아쉬운 점이다.
또한 개발자가 상당히 정신적인 소모가 심한 직업이라는 것을 다시 한번 느꼈다. 몰입하면서 일을 할 때의 그 쾌감을 즐기는 편이지만, 현실적으로 항상 일에 몰입을 하는 것은 누구에게나 어려운 일이다. 나 또한 이번에 인턴을 하면서 건강이 발목을 잡는 등의 경험을 하면서 평소 자기 관리와 생활패턴을 규칙적으로 가져가는 것에 대한 중요성을 느꼈다.
AWS X Yonsei Cloud Winter Camp 후기 (0) | 2024.02.27 |
---|---|
node.js를 공부해보자 (4 : express web server 만들기) (0) | 2021.10.08 |
node.js를 공부해보자(2:html 모듈로 웹 서버 만들기) (0) | 2021.10.08 |
node.js를 공부해보자(1, 기본적인 문법과 callback, promise, async/await) (0) | 2021.10.07 |
야구 시뮬레이션 개발일기 (1. 왜 내가 하던 게임은 망겜소리를 듣나) (0) | 2021.09.18 |