본문 바로가기
⚒️ Projects

[프로젝트 후기] IT 트렌드 매거진, DEVzine

by vodkassi 2021. 9. 12.
728x90

landing page

 

Intro


개발을 공부하다 보면 IT 트렌드나 키워드에 관심이 생기기 마련이다. 여러 포털이나 사이트를 방문해 기사를 검색하다 보면 광고성 글이나 불필요한 글이 너무 많고, 필요한 글은 여기저기 흩어져 있어 한 눈에 보기 어렵다는 단점이 있다. 

 

DEVzine 은 이러한 불편함을 해결하기 위해,

매일 새로운 IT 소식을 키워드별로 모아서 보여주고, 추천 글을 메일로 보내주는 서비스이다. 

 

 

DEVzine 바로 보러가기:

 

DEVzine

 

devzine-port.com

 

 

 

DEVzine 의 핵심 기능


다시 강조하자면 DEVzine 은 "매일 최신 개발 뉴스를 모아 매거진 형태로 발간하고, 구독자 메일로 보내주는 서비스" 이다. 구체적인 기능으로는, 

 

🕹️  매일 업데이트 되는 최신 뉴스 보기

🕹️  구독하여 추천 소식을 메일로 받아보기

🕹️  자신의 글을 기고하여 모두에게 공유하고

🕹️  Devzine의 핵심 데이터를 차트로 확인하고

🕹️  (관리자라면) 관리자 페이지를 통해 여러분이 올린 기고글을 관리하기

 

등이 있다! 

 

기고글 & 최신 기사를 볼 수 있는 Magazine page

 

기고신청을 할 수 있는 Contribution Request Page 

 

 

 

팀원 & 포지션

 

지난 Gallery:port 프로젝트 당시 팀원들의 조합이 괜찮았기에, 이번에도 동일한 팀 구성으로 4주 프로젝트를 새로 진행했다. 

 

🧙‍♂️ 팀장 : 권효승님 (Backend, Deploy)

🧙‍♂️ 팀원 : 강하은 (Backend, DB) --> Me! 

🧙‍♂️ 팀원 : 박성현님 (Frontend, Interaction)

🧙‍♂️ 팀원 : 박종아님 (Frontend, UI Design)

 

나는 이전 프로젝트와 마찬가지로, 이번에도 백엔드 전반을 효승님과 함께 담당하고, DB 를 전담해 설계하고 작업했다. 

팀원들의의 구체적인 Role 은 DEVzine 의 노션 위키에서 확인할 수 있다:

 

 

6. 200ok (DEVzine:port)

📍 목차

codestates.notion.site

 

 

 

 

프로젝트 1주차:
스택 결정, 문서 작성, 기초 세팅과의 고군분투

 

이미 2주 프로젝트를 겪어봤기 때문에 4주 프로젝트의 문서 작성은 수월할 것이라고 생각했고, 기초 세팅 역시 빠르게 진행할 수 있을 것이라고 생각했다. 하지만 이는 나의 안일함에서 비롯한 크나큰 착각이었다. 

 

 

첫 번째 난관 : 스택 결정 

 

팀원들 모두 능력이 많은만큼 욕심도 많았다. 그래서 다들 처음에는 nginx, typescript, p5, socketio... 등 시도해보지 못했던 여러 가지 스택을 써 보고 싶다고 어필했다. 하지만 모두가 같은 커리큘럼을 통해 학습을 했으니, 새로운 스택에 대해서 잘 아는 사람도, 왜 써야하는지를 설명할 수 있는 사람도 없었다 (그저 마음만 앞섰을 뿐). 4주라는 시간이 있었기 때문에 더 많은 욕심을 내고 싶었지만, 새로운 스택을 적용하는 만큼 더 많은 시행착오를 겪게 될 것 같았다. 

 

그래서 팀원들 각자 활용하고 싶은 스택을 깊게 조사해온 뒤 근거를 가지고 설득하는 자리를 마련했다. 그 결과, "정말 필요하다"고 여겨지는 스택 몇 가지를 제외하고는 수료 이후에 각자 학습하기로 결정했다. 스택 결정에 들인 시간이 꽤 길었는데, 지금 돌이켜보니 팀을 위해서는 꼭 필요했던 과정이었다. 

 

결과적으로 이번 프로젝트에서 활용할 스택은 다음으로 결정되었다.

 

 

 

 

두 번째 난관 : 문서 작성

 

문서 작성이라 함은 API 문서, SR (Software Requirements), Wireframe, DB schema 등을 의미하며, 기초 세팅이라 함은 클라이언트/서버 기초 세팅 및 AWS 배포를 의미한다.

 

이 역시 4주 프로젝트인 만큼 더 많은 공을 들여야 할 것임을 제대로 인지하지 못하고 시작했다가, 이후 큰 낭패를 볼 뻔했다. 2주 프로젝트 정도에 준하는 기능을 Bare-minimum 에 포함했다가, 엔지니어의 피드백을 받은 후 대거 수정하여 결과적으로는 훨씬 다채롭고 다양한 기능을 구현하기로 결정했다. 문서 작업을 할 때 이전 프로젝트를 참고하는 것은 좋은 자세이나, 가진 자원 (스택, 기간, 에너지 등) 을 고려하여 적절히 발전시키는 것이 더 중요하다는 점을 많이 배웠다. 

 

 

번째 난관 : 기초 세팅 

 

이번에는 noSQL 중에서도 Document-type DB 인 MongoDB 를 사용하였는데, DB 스키마가 이전 프로젝트와는 비교할 수 없을 정도로 자주 바뀌었다. 기능이 수정되면 바뀌고, 추가되면 바뀌고, 프론트 측에서 데이터 타입 변환 요청이 들어오면 바뀌고, 서버에서 문제 생기면 바뀌고 ... 이 때문에 로컬에서 작업한 DB 내용이 배포 서버에는 제대로 반영되지 않는 경우가 초반에는 자주 발생했다.

 

또한, 이번에는 배포용 DB 를 AWS 에 띄우지 않고 MongoDB Atlas 에 띄웠는데, connection error 가 꽤나 자주 생겼다. 때문에 배포 서버에서 502 에러를 자주 만났고, 에러를 해결하여 기초 세팅을 완료하는 데만 1주일이 소요되었다. 하지만 새로운 유형의 에러와 문제에 직면한 만큼, 더 끈기있게 문제의 원인을 찾아 디버깅을 해낼 수 있는 시간이었다. 

 

 

 

 

 

프로젝트 2~4주차:
백엔드에 한층 더 집중할 수 있었던 기회


지난 프로젝트는 시간의 제약으로 인해 기본적인 CRUD 기능 구현에 초점을 맞추었다. 그러나 이번에는 4주라는 시간이 주어졌기에, 더 많은 기능을 더 탄탄하게 설계하고 구현할 수 있는 기회로 삼을 수 있었다. 

 

기본적인 유저 또는 기고글 CRUD 구현 외에, 내가 이번에 백엔드 엔지니어로서 핸들링 했던 네 가지 특수한 상황 및 기능을 간략히 소개해보고자 한다. 

 

 

✨  전체 그림 속의 DB  (Stack: MongoDB, Mongoose)

 

이전 프로젝트에서는 유저와 프로젝트 간의 join 을 많이 활용해야 했기에 sql 을 사용했었지만, 이번 프로젝트의 초창기 기획 당시에만 해도 join 이 필요한 케이스는 전혀 존재하지 않았다. (물론 이후 기능이 추가되고 확장됨에 따라 join 이 필요한 한 두 개 정도의 케이스가 생기긴 했으나, 이 역시 mongoDB 의 유용한 aggregation pipeline 을 통해 해결할 수 있었다) 또한, 우리 서비스의 특성상 기본 기능을 구현해 놓는다면 이후 여러 방면으로 확장 가능성이 매우 높다는 의견이 있었다. 가령, 본격적인 추천 시스템이나 결제 시스템, 관심 기사나 기고글 보관함에 담기 등 여러 가지 추가 기능을 생각해 볼 수 있었다. 팀원 모두가 DEVzine 을 프로젝트 이상으로 바라보고 있었기에, 용이한 확장력에 초점을 두어 NoSQL 인 MongoDB 를 선택했다. 

 

 

📍

DB 의 유형에 따라 고려되어야 할 요소들이 있다. 가령, NoSQL 을 사용한다면 session 을 사용하는게 더 좋은지, token 을 사용하는게 더 좋은지 등의 이슈들이다. 사소한 부분일 수 있지만 서비스 뒷단의 일관성을 위해서라도 고민해야 하는 부분이라고 생각했고, 나와 백엔드 동료는 이 부분을 정말 치밀하게 찾아보고 고민했다. 그리고 '확장 가능성' 이라는 목표를 중심으로 서비스를 설계하기로 하였으니, 일관성을 위해 역시 '확장에 용이한' 토큰을 사용하기로 결정했다. 

 

 

📍

데이터는 서버를 거쳐 DB 에 저장되긴 하지만, DB 에 저장되는 데이터의 구조나 자료형에 따라 Front end 가 작업 방향을 달리 잡아야 하는 경우가 발생한다. API 문서를 함께 작성하며 이런 부분들을 보완했음에도 예상치 못한 여러 문제들이 발생하기도 했다. 가령, 다음과 같은 상황이 있었다. 

 

초반에는 기고글 기능을 그렇게 크게 기획하지 않아, 기고글의 상태를 '승인' 또는 '대기중' 두 개로만 설정해 두었었다. 따라서 db.contributions.status 의 상태 역시 'pending' 또는 'accepted' 가 되도록 했는데, 이후 기고글 기능이 갑자기 확장되면서 기고글 상태 역시 승인 대기, 승인 거부, 승인 확정, 수정 대기, 수정 거부, 수정 확정, 삭제 대기, 삭제 거부, 삭제 확정으로 세분화 되었다. 상태별로 key 값을 만들어 0 혹은 1값을 부여할까, 혹은 기고글 상태를 위한 중첩 객체를 만들까, 등의 고민을 하게 되었다. 하지만 이미 대부분의 DB 가 안정적으로 구상된 상태에서, 팀원 모두의 혼란을 줄일 수 있는 최적의 방법을 찾고 싶었다.

 

그래서 떠올린 해결책은 '상태 코드' 였다. 각 상태에 1:1로 대응하는 정수 상태 코드를 만든 뒤, Front 와 Back 모두 이에 맞춰 작업을 하면 될 것이라는 생각이었다. 실제로 기존 DB 스키마를 건드리지 않고, 각 기고글의 status 값만 새롭게 부여함으로써 문제가 간단히 해결되었다. 이때 고안한 상태코드는 이후 서비스가 확장되어 새로운 기고글 상태가 필요하게 되어도, DB 의 안정성을 해치지 않게 된다는 장점이 있다. 

 

 

 

 

💡  위의 두 경험 덕분에 DB 를 '설계'한다는 것의 의미와, DB 의 역할을 되새겨 보게 되었다. 단순히 어떤 데이터를 어떻게 저장할 것인지를 넘어, 서버와 클라이언트에게 안정적이고 직관적인 데이터를 전달할 수 있는 방법을 깊이 고민해보게 된 계기였다. 

 

 

 

✨  서버의 성능을 향상하는 Cache (Stack: Redis)

 

캐시 ! 이번 백엔드 설계 중에서 가장 중요하다고 생각했던 부분이다. 캐시를 구현하고 싶은 욕심은 있었지만, 실제로 우리 프로젝트 기능 중에 캐싱이 유용하게 사용될 수 있는 것이 있어, 구현해보게 되었다. 

 

 

Visual Page

 

📍

이번에 구현한 페이지 중 'Visual Page' 는 사용자와 기사의 데이터를 활용하여 통계 자료처럼 시각화하여 보여주는 페이지이다. 

 

Front End 가 구현하고자 하는 테이블에 맞게 DB 에서 받아온 데이터를 정리해 보려니, 서버 단에서 매우 길고 복잡한 쿼리를 작성하게 되었다. (내가 기억하기로 유저 / 기사 데이터당 약 200줄 정도..) 쿼리가 길고 복잡해지니 당연히 서버에서 클라이언트로 데이터를 전송하는 속도가 1초대로 느려졌는데, 여러 명이 동시에 이 페이지에 접속하게 된다면 큰 문제가 생길 것 같았다. 

 

고민하다, Visual Page 데이터의 핵심은 "실시간 데이터를 보여주지 않아도 된다는 것" 이라는 생각이 번쩍 들었다. 그래프의 설명란에 간간이 보이다시피, Visual Page 의 그래프는 "최근 한 달, 혹은 하루 전까지를 기준으로" 데이터를 보여주고 있다. 그렇다면 굳이 해당 페이지에 접속할 때마다 복잡하고 긴 요청을 날릴 필요 없이, 응답 속도를 개선해주는 캐시를 활용하면 될 것이라는 생각이 들었다. 

 

그래서 Redis 를 활용하여 로컬 서버에 In-memory Cache 를 구현했다. 길고 복잡한 쿼리는 처음 요청이 들어왔을 때 한 번만 실행되어, 그 이후부터는 캐시에서 데이터가 반환되도록 했으며, 캐시 유효시간을 12시간으로 설정해 DB에서 주기적으로 캐시를 업데이트 해주기만 하면 됐다. 캐시 구현의 가장 큰 이점은 역시 서버 성능 (즉, 응답 속도) 의 큰 개선이었다. 1초대에 달하던 Visual Page 의 응답 속도가 0.007~8초대로 뚝 떨어졌고, 페이지가 브라우저에서 더 빨리 렌더링 되었다. 

 

 

📍 

기능 하나에만 적용하고 두기에는 아까워서, 개인적인 욕심으로 최신 기사와 기고글 페이지에도 캐싱을 적용했다. 해당 내용은 이번에 진행한 개인 기술 발표 영상에서 확인할 수 있을 것이다. 

 

[Co'Talk] Redis와 In-memory Cache로 서버 성능 개선하기 - Codestates 수료생 강하은

강하은님이 참고하고 기록한 자료 👇 - 강하은님 블로그 (https://haeunyah.tistory.com/) - 200ok 팀 깃헙 (https://github.com/codestates/DEVzine-port) - 파이널 프로젝트 'DEVzine' (https://devzine-port.com/) - 강하은님이 참

youtu.be

 

❗ 개인 기술 발표 주제로 Redis & Cache 를 선택한 이유? 

우선, 이번에 새롭게 사용하고 배운 스택 중 나에게 제일 도전적인 것을 선택하고 싶었다. 그리고 우리 프로젝트 스택을 보고 '왜 굳이 Redis 를 사용했지?' 라는 의문을 갖는 사람들을 설득하고 싶었다. 적어도 개인 기술 발표를 통해 Redis 와 Cache 를 잘 모르고 무턱대고 쓴 것은 아니라는 점을 보여주고 싶었고, 우리의 선택에는 합리적인 이유가 있었다는 것과 매우 많은 공을 들여 공부를 했다는 것을 간접적으로라도 알리고 싶었다.

또한, 내가 아는 캐싱에 대한 정보의 총체를 기록해 둠으로써 미래에 내가 더 많은 것을 알게 되었을 때, 스스로 얼마나 성장했을지 볼 수 있는 체크포인트가 될 수 있을 것이라고 생각했다. 나중에 다시 이 영상을 보았을 때, 내가 주니어일 당시에는 캐싱에 대해 어떤 이해를 가지고 있었으며, 어떻게 공부했었는지를 회고할 수 있는 지표가 될 수 있지 않을까? 싶었다. 

 

💡 캐시를 구현하며, 서버의 성능을 직접 개선하는 경험을 했다. 덕분에 백엔드의 역할과, 서버에서 소숫점 단위의 응답 속도 차이가 성능에 얼마나 큰 영향을 미치는지에 대해서도 더욱 고찰할 수 있었다. 

 

 

✨  자동으로 외부 기사를 수집해오는 Crawler (Stack: Cheerio) 

 

매일 오전, 최신 기사를 수집하기 위해 IT 매체를 여러 군데 찾아보고, 크롤링이 가능한지 점검했다. 결과적으로 3 군데의 매체에서 기사를 수집해 오는 크롤러를 구현했는데, 크롤러를 서비스에서 사용하게 된다면 크롤링을 당하는 입장에서는 민감하거나 불쾌하게 받아들일 수 있겠다고 생각했다. 따라서 상대 서비스를 고려하여 크롤러 구현 과정 중 특별히 신경 쓴 부분들이 있다. 

 

📍 

크롤링 (또는 웹 스크래핑) 은 웹의 HTML 태그에 접근하여 기재된 정보를 긁어오는 작업이다. 법적으로 금지된 기술은 아니지만, 데이터를 대량으로 수집하거나 수집한 데이터를 통해 영리적인 이익을 취하게 될 경우 정보보호법 위반으로 간주될 수 있다. 따라서 나는 합법적 크롤링을 하기 위한 조치를 취했다. 조치라고 해도 별 건 아니고, 이러한 문제를 사전에 인지하여, 크롤러가 너무 자주 작동하지 않도록 24시간 단위의 시간 설정을 했다. 또한, 수집하는 매체별 기사 수를 10개 이내로 제한하였고, 각 사이트의 크롤링 허용 여부를 표시해주는 robots.txt 파일을 꼼꼼히 읽어보며 크롤러 접근 권한이 있음을 확인했다.

 

 

📍 

기사를 수집한 매체에게 피해가 가지 않도록 했다. selenium 등의 가상 브라우저를 활용한다면 기사 전문을 긁어와 우리 서비스에 게재하는 것도 충분히 가능한 일이었다. 하지만 그렇게 했을 때, 우리의 서비스로 인해 기존 매체들의 기사 조회수가 낮아져 피해를 입을 수 있기 때문에, 기사 전문 대신 미리보기 본문만을 긁어와 유저가 해당 매체의 기사 url 로 직접 이동할 수 있도록 클릭을 유도했다.

 

 

💡 크롤러 구현을 통해 크게 배운 두 가지가 있는데, 그 중 첫 번째는 바로 '서비스에 대한 주인의식' 이다. 비록 프로젝트였지만, 나와 우리 팀은 프로젝트보다는 실제 서비스를 만들 듯이 기능에 접근했다. 그 과정에서 모든 기능이 조금이라도 유저 친화적일 수 있도록 개선하는 등의 노력을 하기도 했는데, 크롤러를 구현하면서는 '우리 서비스가 법적인 문제를 야기하지 않도록' 무척이나 신경썼다. 덕분에 기업에 들어가서도, 서비스 중심의 사고를 하는 개발자로 프로젝트에 참여할 수 있을 것이라고 생각한다. 

 

💡 두 번째로 배운 점은 바로 '함수 추상화와 모듈화의 중요성' 이다. 아무래도 '크롤러'라는 것 자체가 이미 하나의 추상화된 기능이기도 하고, 크롤러 구현에 활용된 코드 전체를 작은 단위로 쪼개지 않고서는 작업이 효율적으로 이루어지지 않았다. 크롤링 시간, 도메인, 주기에 따라 기존 함수를 적절히 사용할 수 있도록, 그리고 함수명을 보았을 때 한 눈에 함수의 역할이 이해되도록 코드를 작성하려 했다. 

 

Crawler module

 

 

✨  Admin/User 에 따른 권한 차등 부여  (Stack: passport) 

 

이번 프로젝트에서 특별했던 기능 또 하나는 바로 '관리자(admin)' 기능이었다. 사용자들이 기고글을 게시하면 이를 검토하여 승인하거나 거부하는 역할을 담당하게 되는 관리자 역기능을 만들었는데, 이전에 한 번도 다루지 않았던 권한 차등 부여를 이번에 코드로 구현해보게 되었다.

 

Admin Page

 

📍 

관리자 기능도 사실 초반에는 기획에 포함되지 않았지만, 뒤늦게 필요성이 생겨 급하게 투입한 기능이다. 그러다보니 이미 일반 모든 권한은 일반 유저에 맞춰져 있었고, 관리자가 유저와 같은 엔드포인트에 접속했을 때 데이터를 다르게 조작할 수 있는 방법을 찾아야 했다.  (관리자만을 위한 엔드포인트를 새로 만들기에는 시간과 비용이 너무 아깝다고 생각했기 때문에 꼭 필요한 경우가 아닌 이상 고려하지 않았다) 가령, 모든 유저가 접속할 수 있는 '기사 보기' 페이지에 관리자 역시 접속할 수 있는데, 관리자 계정으로 접속했을 때는 해당 글의 조회수를 늘리지 않아야 했다. 또는, 관리자 계정으로 접속했을 때는 유저들에게는 보이지 않는 삭제된/수정 대기 상태인 게시글이 보여야 했다

 

DB 에 새로운 필드를 추가하려면 이미 잘 돌아가고 있는 배포 서버의 모든 유저 데이터를 다 조작해야 했기 때문에, 그보다는 관리자만을 위한 토큰을 따로 만들어 관리자 로그인 시 관리자 토큰을 발급했다. 따라서 권한 차등 부여가 필요한 엔드포인트일 경우 토큰의 payload 를 검토해 접속자가 일반 user 인지, admin 인지 확인하도록 했다. 이렇게 함으로써 같은 엔드포인트에 접속했을지라도 admin 일 때는 user 일 때와 다른 페이지를 보여줄 수 있었다. 

 

 

💡 관리자 기능이 조금 뒤늦게 기획에 포함되어, 조금 더 효과적인 코드 구현을 하지 못했던 것이 아쉽다. 새로운 토큰을 발급하기보다 모두에게 동일한 토큰을 발급하되, 토큰의 payload 에 user/admin 정보를 넣어 이에 따라 각 엔드포인트에 차등적으로 접근할 수 있도록 했으면 어땠을까 싶다. 

 

 

 

 

프로젝트 마무리:
일 줄 알았지?

 

4주차에는 모든 기능을 완성하여, 팀 발표 영상도 찍고, 그렇게 프로젝트를 마무리 지었다. 

 

 

❗ 앗, 정말 그랬을까? 

대외적으로는 프로젝트를 마무리하긴 했지만, 최종 발표일까지도 사소하지만 서비스를 개발한 당사자들에게는 매우 잘 보이는 버그가 계속 발견되어, 이로 인해 심적으로 너무 고통받았다. 서비스 규모가 생각보다 커졌던 만큼, 예상치 못한 부분에서 계속 의도치 않은 결과가 나오는 것이다. 물론 주요 기능들은 문제 없이 잘 돌아가지만, 누군가 언젠가 이 버그를 발견하게 될까봐 불안한 마음이 들기에... 

 

우리 팀은 다음 주부터 다시 전체 디버깅과 리팩토링에 돌입하기로 했다. 그래서 버그가 발견되거나 고쳐야 하는 코드를 찾을 때마다 팀 채널에 기록하고 있으며, 가능한 경우에는 생각나는 개선 방향까지도 공유한다. 디버깅.. 정말.. 기대된다 😇

 

 

💡 지난 프로젝트 후기에도 비슷한 내용을 썼던 것 같은데, 프로젝트는 나의 실력을 검증하고 대폭 향상할 수 있는 최고의 기회이다. 머리로만 알던 것들을 현출하여 응용하고, 내가 생각하지 못했던 부분들까지도 다뤄야 하는 '실전'에 가깝기 때문이다. 4주 프로젝트를 진행하며 많이 지치기도, 힘들기도 했지만, 그 시간 덕분에 이제는 누구의 가이드라인 없이도 직접 하나의 서비스를 구현하고, 서비스에 대해 고민할 줄 아는 '개발자'의 모습에 더 가까워졌다. 앞으로도 여러 사이드 프로젝트를 통해, 다양한 방면으로 도약하길 기대해본다. 

 

 


DEVzine Github : 

 

GitHub - codestates/DEVzine-port: DEVzine, latest IT trends & news for you

DEVzine, latest IT trends & news for you. Contribute to codestates/DEVzine-port development by creating an account on GitHub.

github.com

 

DEVzine 팀 발표 영상:

 

[수강생 프로젝트] DEVzine:port - 29기 200ok 팀

IT 트렌드를 찾는 당신을 위한 매거진, DEVzine - 매일 아침에 추가되는 최신 IT 뉴스를 볼 수 있습니다. - 구독 신청을 하여 이메일로 받아볼 수 있습니다. - DEVzine에 기고하여 당신만의 IT 글을 사람

youtu.be

 

 

댓글