블로그스팟에서 React 코드 사용하기 + S&P 500 Market Overview 예시
1. 개요
블로그스팟은 순수 HTML, CSS, JavaScript 코드를 직접 삽입해 활용할 수 있습니다. 그러나 React 같은 라이브러리 사용을 위해서는 최소한의 설정이 필요합니다. 이번 글에서는 Blogger에서 JSX를 변환하기 위한 Babel Standalone을 사용해 React 코드를 동작시키고, 간단한 S&P 500 Market Overview 예시를 구현해보겠습니다.
2. 준비 사항
React, ReactDOM, Babel Standalone
JSX 문법을 브라우저에서 컴파일하기 위해 다음 CDN을<script>
로 불러옵니다.
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
이렇게 하면 <script type="text/babel">
내부에 작성한 JSX 코드를 자동으로 변환해줍니다.블
블로그스팟 HTML 편집 모드
새 게시물을 작성할 때, HTML 모드로 전환한 뒤 코드를 붙여넣어야 JSX가 올바르게 동작합니다.주의점
<head>
와<body>
가 중첩될 수 있으므로,ReactDOM.render
에서 참조하는<div id="root">
가 실제로 존재하도록 배치합니다.- HTTPS 환경에서
http://
로 된 CDN을 사용하면 혼합 콘텐츠 이슈가 생길 수 있으므로https://
주소를 쓰는 것이 좋습니다.
3. S&P 500 Market Overview 구현 예시
아래 코드는 가상의 S&P 500 종목 데이터를 선언하고, 섹터별 카드 형태로 시각화합니다. 종목 심볼과 이름, 상승/하락률, 시가총액 등을 표시해 블로그스팟에서도 한눈에 볼 수 있게 구성한 예시입니다.
<!-- (1) React/ReactDOM/Babel CDN -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- (2) React 컴포넌트를 렌더링할 대상 -->
<div id="root"></div>
<!-- (3) S&P 500 Market Overview: React JSX 코드 -->
<script type="text/babel">
// 가상의 S&P 500 종목 데이터
const sp500Data = [
{ symbol: 'AAPL', name: 'Apple Inc.', sector: 'Technology', change: 0.20, marketCap: 2300 },
{ symbol: 'MSFT', name: 'Microsoft Corp.', sector: 'Technology', change: -0.30, marketCap: 2100 },
{ symbol: 'GOOGL', name: 'Alphabet Inc. (Class A)', sector: 'Communication', change: 0.15, marketCap: 1500 },
{ symbol: 'AMZN', name: 'Amazon.com Inc.', sector: 'Consumer', change: 0.48, marketCap: 1400 },
{ symbol: 'TSLA', name: 'Tesla Inc.', sector: 'Consumer', change: 1.20, marketCap: 900 },
{ symbol: 'JPM', name: 'JPMorgan Chase & Co.', sector: 'Financial', change: 1.42, marketCap: 420 },
{ symbol: 'V', name: 'Visa Inc.', sector: 'Financial', change: -0.35, marketCap: 440 },
];
// 간단한 카드 컴포넌트
const MarketTile = ({ symbol, name, change, marketCap }) => {
// 배경색 계산: 상승/하락
const getBackground = (chg) => {
if (chg === 0) return 'rgb(48, 51, 54)';
const intensity = Math.min(Math.abs(chg) * 15, 100);
return chg > 0
? `rgb(21, ${Math.floor(118 + intensity)}, 89)`
: `rgb(${Math.floor(220 + intensity)}, 48, 71)`;
};
const tileStyle = {
backgroundColor: getBackground(change),
width: '120px',
height: '90px',
margin: '4px',
borderRadius: '6px',
padding: '8px',
color: '#fff',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between'
};
return (
<div style={tileStyle}>
<div style={{ fontWeight: 'bold' }}>{symbol}</div>
<div style={{ fontSize: '0.85rem', opacity: 0.8 }}>{name}</div>
<div style={{ fontSize: '0.8rem', color: change >= 0 ? '#34d399' : '#ef4444' }}>
{change > 0 ? '+' : ''}{change.toFixed(2)}%
</div>
<div style={{ fontSize: '0.7rem', color: '#ddd' }}>
Cap: ${marketCap}B
</div>
</div>
);
};
// 섹터별 구분 섹션
const SectorSection = ({ sectorName, stocks }) => {
return (
<div style={{ marginBottom: '12px' }}>
<h3 style={{ color: '#ccc', fontSize: '0.9rem', margin: '8px 0' }}>
{sectorName.toUpperCase()}
</h3>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
{stocks.map((stock) => (
<MarketTile key={stock.symbol} {...stock} />
))}
</div>
</div>
);
};
// 메인 컴포넌트
const SP500Overview = () => {
// 섹터별로 데이터 분류
const sectorMap = {};
sp500Data.forEach((stock) => {
const s = stock.sector;
if (!sectorMap[s]) sectorMap[s] = [];
sectorMap[s].push(stock);
});
// 섹터 목록
const sectorNames = Object.keys(sectorMap);
return (
<div style={{ backgroundColor: '#1E222D', padding: '16px', borderRadius: '8px' }}>
<h2 style={{ color: '#fff', marginBottom: '8px' }}>S&P 500 Market Overview</h2>
<div style={{ color: '#aaa', fontSize: '0.8rem', marginBottom: '16px' }}>
Updated: Just Now
</div>
{sectorNames.map((sector) => (
<SectorSection
key={sector}
sectorName={sector}
stocks={sectorMap[sector]}
/>
))}
</div>
);
};
// 렌더링
ReactDOM.render(<SP500Overview />, document.getElementById('root'));
</script>
<!-- (4) 선택 사항: 전체 페이지 스타일 -->
<style>
body {
background-color: #2D3038;
margin: 0;
font-family: Arial, sans-serif;
}
</style>
댓글 쓰기