https://viewership.softc.one
소프트콘 뷰어쉽은 아프리카, 트위치에서 방송중인 크리에이터들의 정보를 실시간으로 수집하여 해당 크리에이터의 데이터 및 순위를 보여주는 뷰어쉽 어플리케이션입니다.
제공해주는 정보는 아프리카 + 트위치 통합 방송 랭킹, 뷰어쉽 순위 및 크리에이터 별 상세 방송 데이터 등 입니다. 이런 데이터를 바탕으로 광고주, 크리에이터, 시청자 모두가 만족할만한 정보를 확인할수 있게 하는것이 이 사이트의 궁극적인 목표입니다.
요약하자면,
이렇게 되겠습니다.
저번 연재에 이어서 이번에는 어떤 순서로 개발이 이뤄지게 되었는지 적어보겠습니다!
아이데이션과 검증은 저번시간을 통해 전부 완료했습니다. 이제 와이어프레임부터 기획해봐야겠죠.
이 프로젝트는 저 혼자 진행하기에 최대한 단순하고 확실한 디자인, 그리고 명확한 기준을 가지고 제작을 진행해야 합니다.
보통 저의 경우 참고할만한 디자인 컴포넌트, 시스템을 참고하고 이에 맞춰 와이어프레임을 피그마로 제작하는 편입니다. 강력하고 유연하며 단순한 디자인 컴포넌트를 생각해보니 제가 자주사용하는 vercel의 디자인이 꽤 괜찮다고 생각이 되더라구요.
카드형태로 만들게 되면 반응형 제작에도 강점이 있고, 사용자들에게 굉장히 깔끔하고 유연한 느낌을 줄수 있을것 같습니다. 그러면 이 형태를 기반으로 피그마로 와이어프레임을 제작해봅시다!
최고의 아이디어를 끌어내기위해 카페인 풀도핑하고 본격적으로 디자인을 시작해보죠.. ☕️
[ ... 제작중 ... ]
자 이렇게 완성되었습니다.
딱 이런 느낌으로 순위를 보여주고 현재 크리에이터가 LIVE면 그에 맞춰 화면을 보여주는식으로 제작해봅시다. 그래프에는 그라데이션도 좀 넣고 굉장히 단순해보이지만 각 크리에이터의 썸네일이 단순해보이는 화면에 화려함을 제공해줄것으로 생각됩니다.
디자인적으로 어색한건 개발하면서 수정하면 되고, 디자인 컴포넌트만 잘 갖춰진다면 나중에 추가하는건 전혀 문제가 없을겁니다.
그럴듯해 보이는군요! 그럼 이제 VS Code를 켜볼 시간이군요
서버부터 개발해봅시다.
이전화에서 말했듯 저는 프론트엔드에 강점이 더 있는 개발자입니다. 서버쪽은 어깨넘어 배웠을뿐 자세히는 잘 모른단 말이죠. nest.js
를 사용하여 node 기반의 무언가를 만드는것을 하는건 문제 없지만 그렇다고 본격적으로 DB
를 설계하고 만드는 일은 아직 부족한 실력입니다.
그렇다면 vercel
의 serverless Function
을 적극적으로 활용해보면 어떨까요?
기존 데이터를 수집하는 크롤링 크론 서버는 aws ec2
인스턴스에서 올려놓고, 해당 DB를 serverless Function
으로 연결하면 완벽할것 같습니다!
오호.. 해치웠나?
( 아님 나중에 문제생겼음 )
자 그러면 이제 next.js
를 통해 서버 API와 프론트엔드를 동시에 개발해봅시다!
javascript
개발자의 최대의 장점이자 단점
"너 자바스크립트 할줄 알아?"
지금은 장점입니다.
특히 Prisma
라는 사용하기 편한 ORM이 있으니 Prisma + nest.js
를 이용해서 크롤링 서버를 만들어 봅시다. 일단 여기서 필요한건 딱 1개 입니다. 바로 아프리카TV를 크롤링해서 데이터를 쌓는거죠.
nest.js
에 playwright
를 이용해서 크롤링하는 첫번째 API가 만들어졌습니다. 물론, API를 사용하지는 않고 cron을 해주는 task.service
에서 6분마다 한번씩 해당 서비스를 이용해 데이터를 쌓아주게 됩니다.
// task.service.ts
@Cron('0 */6 * * * *', {
disabled: !!process.env.IS_CRAWLING,
})
async crawlingAfreecaTV() {
this.logger.debug(`[CRON] Crawling AFTV : ${new Date().toISOString()}`);
const createdAt = dayjs().startOf('minute').toISOString();
const result = await this.crawlingService.postAPICrawlingAFTV({
createdAt,
});
return result;
}
이제 DB에 데이터가 잘 들어가는지까지 확인해봅시다.
흠.. 아주 잘 들어가는군요.. 좋습니다!
next.js
로 API와 프론트엔드를 모두 만들어야 합니다.
그렇다면 이참에 Next.js 13
의 App Router
를 이용해봅시다.
이번 Next.js 13.4
에서 Stable로 추가된 App router
는 새로운 프레임워크라고 할 정도로 대격변이 일어나있는 개발 방법입니다. 기존처럼 /app
폴더의 파일들이 실제 도메인이 된다는것 까지는 비슷하지만 이제는 그 하위에 여러 역할을 가진 여러 파일들이 나뉘어 페이지를 표시합니다.
또한 기존의 getStaticProps
, getServersideProps
와 같은 구현방식은 완전히 사라지고 async component
, fetch
등 새로운 방법을 통해 서버 사이드 렌더링을 구현하게 됩니다.
한 페이지 내부에 일부는 CSR
로, 일부는 SSR/ISR
방식으로 구현할 수 있으며 이는 Streaming API
를 이용하여 제작되게 됩니다.
기존처럼 더이상 한 페이지 전체를 서버 사이드 렌더링으로 할 필요 없이, 필요한 부분만 서버 사이드로 하고 나머지는 클라이언트 사이드로 렌더링을 할수 있게 만든다? 정말 혁신적이죠!
물론.. 안정적이라고는 하지만 여러 버그도 존재합니다! 13.5
에서는 많이 개선되었구요.
어차피 Next.js 는 이 방향으로 갈것 같고 미래이기도 하니 한번 사용해보는것도 좋다고 생각합니다!
이제 Next.js 13 에 대한 설명은 충분한것 같습니다.
이제 개발해보죠!
// Prisma ORM
await prisma.user.create({
firstName: “Alice”,
email: “alice@prisma.io”
})
프리즈마, 최고죠.
nest.js
에서도 쓰지만 이를 그대로 next.js
에서도 사용할 수 있습니다.
동일한 DB를 사용하기 때문에 이 ORM을 그대로 next.js
에서 이어서 사용할 수 있습니다.
빠르게 서버 API를 만들어 갑니다.
vercel
에서 사용하는 UI를 차용하여 개발합니다.
극한의 효율성을 위해 <button>
<h1>
<input>
등 아주 기본적인 시멘틱 태그에 CSS를 입혀 어떤일이 있더라도 기본적인 태그를 이용하여 모든것을 만들도록 합시다.
button {
background-color: inherit;
border: none;
color: inherit;
cursor: pointer;
transition: 0.15s;
margin: 0;
padding: 0;
text-align: left;
}
button:hover {
transition: 0.15s;
box-shadow: inset 0px 0px 999px 5px rgba(255, 255, 255, 0.05);
}
button:active {
transition: 0.15s;
transform: scale(0.97);
}
이렇게 하면 모든 버튼엔 동일한 효과가 발생하게 됩니다.
hover시에는 연한 하얀색의 호버 효과가, 누를시에는 버튼이 살짝 작아지는 효과가 구현됩니다.
가장 이상적이고 효율적인 방법입니다. 이 프로젝트는 디자인을 위한 개발
이 아닌 개발을 위한 디자인
이 핵심입니다!
// page.tsx
export default async function LiveTopViewersGraph({
flex = 2,
}: {
flex?: number;
}) {
const all150 = await getStatsTopViewers();
...
return (
<div>
...
<LiveTopGraph data={all150} />
</div>
)
그리고 사용하는 클라이언트 컴포넌트는 아래와 같이 작성합니다.
// LiveTopGraph.tsx
'use client'
export default function LiveTopGraph({
graphData,
colors,
}: {
graphData: any;
colors?: string[];
}) {
return (
<ResponsiveLine
curve='cardinal'
data={graphData}
margin={{ top: 20, bottom: 20, left: 24, right: 24 }}
xScale={{ type: 'point' }}
yScale={{
type: 'linear',
min: 0,
max: 'auto',
reverse: false,
}}
...
여기에 <Suspense>
를 이용하면 SSR에서도 로딩 UI를 구현할수도 있습니다!
이번 Next.js는 아주 잘 만들어 졌군요... 너무 좋습니다!
총 걸린시간은 다음과 같습니다.
( 참고로, 워킹타임을 계산하는 하루 8시간 X 5일
이 아닙니다! 하루 18시간 X 6~7일
입니다 )
저의 모든시간을 갈아 넣어 3주가 지나니 기획에 부합하는 사이트가 배포되었습니다!
( 처음 완성된 사이트, 아프리카만 수집하고 오늘 통계 탭만 존재하고 있습니다 )
와우! 👏
눈물이 찔끔 나는군요 ㅠ
만약 이 프로젝트가 개발용 프로젝트였다면 여기서 연재를 마쳐도 되겠습니다만, 저는 이 사이트를 오래 유지하고 홍보하고 싶기 때문에 아직 더 해야할일이 많습니다.
일단 추가로 진행해야되는 사항은 다음과 같습니다.
이제 순서대로만 진행하면 될것 같습니다.
아주 순조롭습니다..
너무 순조로운데요?
( 다음화에 계속 )
와 진짜 고생 많이 하셧겠네요.. 저걸로 아프리카 지원하면 좋을듯요 ?