프리랜서 실수령 30%,하청구조의 진실
·조회 37
프리랜서 실수령 30%의 진실 | 아티링
/* ===== Reset & Base ===== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Pretendard', -apple-system, sans-serif;
color: var(--black);
background: var(--bg-light);
line-height: 1.7;
font-size: 16px;
}
/* ===== Color Variables ===== */
:root {
--blue: #4169E1;
--gray: #5A5A5A;
--green: #2ECC71;
--beige: #F5DEB3;
--purple: #9B59B6;
--sky: #87CEEB;
--pink: #FF69B4;
--yellow: #FFD700;
--black: #2C2C2C;
--white: #FFFFFF;
--bg-light: #FAFAFA;
}
/* ===== Container ===== */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
}
.container-narrow {
max-width: 800px;
margin: 0 auto;
padding: 0 24px;
}
/* ===== Hero Section ===== */
.hero-section {
background: white;
padding: 80px 0 60px;
text-align: center;
}
.breadcrumb {
font-size: 14px;
color: var(--gray);
margin-bottom: 24px;
}
.breadcrumb span:last-child {
color: var(--blue);
font-weight: 600;
}
.hero-title {
font-size: clamp(32px, 5vw, 56px);
font-weight: 800;
line-height: 1.2;
margin-bottom: 20px;
letter-spacing: -0.02em;
color: var(--black);
}
.hero-subtitle {
font-size: clamp(18px, 2.5vw, 24px);
color: var(--gray);
margin-bottom: 32px;
line-height: 1.5;
}
.meta-info {
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
font-size: 14px;
color: var(--gray);
flex-wrap: wrap;
}
.meta-info .divider {
color: #D1D5DB;
}
/* ===== Key Stats ===== */
.key-stats-section {
padding: 60px 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
}
.stat-card {
background: white;
padding: 40px 32px;
border-radius: 16px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transition: transform 0.3s, box-shadow 0.3s;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0,0,0,0.12);
}
.stat-icon {
font-size: 48px;
margin-bottom: 16px;
}
.stat-number {
font-size: 56px;
font-weight: 900;
color: var(--blue);
line-height: 1;
margin-bottom: 4px;
}
.stat-unit {
font-size: 24px;
font-weight: 700;
color: var(--blue);
margin-bottom: 12px;
}
.stat-label {
font-size: 16px;
color: var(--gray);
font-weight: 500;
}
/* ===== Content Section ===== */
.content-section {
padding: 80px 0;
width: 100%;
}
.content-section .container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
}
.section-header {
text-align: center;
margin-bottom: 48px;
}
.section-tag {
display: inline-block;
padding: 6px 16px;
background: var(--blue);
color: white;
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
border-radius: 20px;
margin-bottom: 16px;
}
.section-title {
font-size: clamp(28px, 4vw, 40px);
font-weight: 700;
margin-bottom: 16px;
line-height: 1.3;
color: var(--black);
}
/* ===== Content Card ===== */
.content-card {
background: white;
border-radius: 16px;
padding: 48px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.card-body {
display: flex;
flex-direction: column;
gap: 40px;
}
.text-block {
max-width: 680px;
margin: 0 auto;
}
.text-block p {
font-size: 18px;
line-height: 1.8;
color: var(--gray);
margin-bottom: 20px;
}
.lead-text {
font-size: 20px;
font-weight: 600;
color: var(--black);
margin-bottom: 20px;
line-height: 1.6;
}
.text-block ul {
list-style: none;
padding: 0;
margin: 20px 0;
}
.text-block ul li {
padding: 12px 0 12px 32px;
position: relative;
font-size: 17px;
color: var(--gray);
line-height: 1.7;
}
.text-block ul li::before {
content: '•';
position: absolute;
left: 12px;
color: var(--gray);
font-weight: bold;
}
/* ===== Chart ===== */
.chart-wrapper {
background: var(--bg-light);
padding: 32px;
border-radius: 12px;
}
.chart-title {
font-size: 18px;
font-weight: 700;
margin-bottom: 24px;
text-align: center;
color: var(--black);
}
.chart-caption {
margin-top: 16px;
font-size: 14px;
color: var(--gray);
text-align: center;
}
/* ===== Quote ===== */
.quote-section {
padding: 80px 0;
background: var(--blue);
color: white;
}
.big-quote {
text-align: center;
padding: 0;
border: none;
}
.big-quote p {
font-size: clamp(24px, 3vw, 36px);
font-weight: 700;
line-height: 1.4;
margin-bottom: 24px;
}
.big-quote cite {
font-size: 16px;
font-style: normal;
opacity: 0.8;
}
/* ===== Comparison Grid ===== */
.comparison-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 32px;
width: 100%;
justify-items: stretch;
}
.compare-card {
background: white;
border-radius: 16px;
padding: 40px 32px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transition: transform 0.3s;
width: 100%;
box-sizing: border-box;
}
.compare-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0,0,0,0.12);
}
.compare-card.before {
border-top: 4px solid var(--gray);
}
.compare-card.after {
border-top: 4px solid var(--blue);
}
.compare-card.optimized {
border-top: 4px solid var(--green);
}
.card-header {
margin-bottom: 24px;
}
.badge {
display: inline-block;
padding: 4px 12px;
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
border-radius: 12px;
margin-bottom: 12px;
}
.badge-gray {
background: #F3F4F6;
color: var(--gray);
}
.badge-blue {
background: #DBEAFE;
color: var(--blue);
}
.badge-green {
background: #D1FAE5;
color: var(--green);
}
.card-header h3 {
font-size: 24px;
font-weight: 700;
margin: 0;
color: var(--black);
}
.big-number {
font-size: 64px;
font-weight: 900;
line-height: 1;
margin-bottom: 16px;
}
.big-number.color-gray {
color: var(--gray);
}
.big-number.color-blue {
color: var(--blue);
}
.big-number.color-green {
color: var(--green);
}
.compare-card p {
font-size: 18px;
color: var(--gray);
line-height: 1.7;
margin-bottom: 20px;
}
.sub-value {
font-size: 16px;
color: var(--gray);
margin-bottom: 16px;
font-weight: 600;
}
.feature-list {
list-style: none;
padding: 0;
margin-top: 24px;
}
.feature-list li {
padding: 12px 0 12px 32px;
position: relative;
font-size: 17px;
color: var(--gray);
line-height: 1.7;
}
.feature-list li::before {
content: '•';
position: absolute;
left: 12px;
color: var(--gray);
}
/* ===== Data Table ===== */
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 15px;
margin-top: 24px;
}
.data-table thead {
background: var(--bg-light);
}
.data-table th {
padding: 16px;
text-align: left;
font-weight: 700;
color: var(--black);
border-bottom: 2px solid #E5E7EB;
}
.data-table td {
padding: 16px;
border-bottom: 1px solid #E5E7EB;
}
.data-table tbody tr:hover {
background: var(--bg-light);
}
.data-table tbody tr:last-child {
font-weight: 700;
background: var(--bg-light);
}
.data-table tbody tr:last-child td {
border-top: 2px solid #E5E7EB;
}
/* ===== Timeline ===== */
.timeline {
position: relative;
padding-left: 40px;
max-width: 600px;
margin: 0 auto;
}
.timeline::before {
content: '';
position: absolute;
left: 15px;
top: 0;
bottom: 0;
width: 2px;
background: var(--blue);
}
.timeline-item {
position: relative;
padding-bottom: 48px;
}
.timeline-marker {
position: absolute;
left: -40px;
top: 0;
width: 32px;
height: 32px;
background: var(--blue);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 14px;
}
.timeline-content {
text-align: center;
}
.timeline-content h4 {
font-size: 20px;
font-weight: 700;
margin-bottom: 12px;
color: var(--black);
}
.timeline-content p {
font-size: 18px;
color: var(--gray);
line-height: 1.7;
margin-bottom: 12px;
}
.timeline-content .timeline-features {
list-style: none;
padding: 0;
margin-top: 16px;
text-align: left;
display: inline-block;
}
.timeline-content .timeline-features li {
padding: 8px 0 8px 24px;
position: relative;
font-size: 16px;
color: var(--gray);
line-height: 1.6;
}
.timeline-content .timeline-features li::before {
content: '→';
position: absolute;
left: 0;
color: var(--blue);
}
/* ===== Source Section ===== */
.source-section {
padding: 40px 0;
background: var(--bg-light);
}
.source-text {
text-align: center;
font-size: 14px;
color: var(--gray);
opacity: 0.7;
}
/* ===== CTA Section ===== */
.cta-section {
padding: 80px 0;
background: var(--black);
color: white;
}
.cta-card {
text-align: center;
padding: 60px 40px;
background: var(--black);
border-radius: 20px;
}
.cta-title {
font-size: clamp(28px, 4vw, 40px);
font-weight: 700;
margin-bottom: 20px;
line-height: 1.3;
}
.cta-description {
font-size: 18px;
opacity: 0.8;
margin-bottom: 40px;
line-height: 1.6;
}
.cta-buttons {
display: flex;
justify-content: center;
gap: 16px;
flex-wrap: wrap;
margin-bottom: 40px;
}
.btn {
display: inline-block;
padding: 16px 40px;
font-size: 16px;
font-weight: 700;
border-radius: 50px;
text-decoration: none;
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
border: none;
}
.btn:hover {
transform: scale(1.05);
}
.btn-primary {
background: var(--yellow);
color: var(--black);
}
.btn-primary:hover {
box-shadow: 0 8px 20px rgba(255, 215, 0, 0.4);
}
/* ===== Responsive ===== */
@media (max-width: 768px) {
.hero-section {
padding: 60px 0 40px;
}
.content-card {
padding: 32px 24px;
}
.stats-grid {
grid-template-columns: 1fr;
}
.comparison-grid {
grid-template-columns: 1fr;
}
.cta-buttons {
flex-direction: column;
}
.btn {
width: 100%;
}
.data-table {
font-size: 13px;
}
.data-table th,
.data-table td {
padding: 12px 8px;
}
}
블로그 > 프리랜서 생존 가이드
프리랜서 실수령 30%의 진실
정부 발주 500만원, 중간 착취 70%, 실제 수령액 150만원의 구조
2026.01.05
•
12분 읽기
💸
0
%
중간 착취율 (정부 발주 기준)
📉
0
만원
실제 수령액 (발주 500만원 기준)
Problem
정부 발주 500만원, 프리랜서는 왜 150만원만 받을까?
정부가 500만원을 발주하면, 실제 작업하는 프리랜서는 150만원(30%)만 받습니다. 나머지 350만원(70%)은 어디로 갈까요? 1차 업체, 2차 업체, 3차 하청을 거치며 중간 착취가 발생합니다.
1
1단계: 정부/지자체 발주
발주 금액: 500만원
정부 또는 지자체가 프로젝트를 발주합니다.
2
2단계: 1차 업체 수주
총액: 500만원
1차 업체 마진: 150만원 (30%)
2차 업체로 하청: 350만원 (70%)
3
3단계: 2차 업체 하청
하청 금액: 350만원
2차 업체 마진: 100만원 (20%)
3차 업체로 하청: 250만원 (50%)
4
4단계: 3차 업체 하청
하청 금액: 250만원
3차 업체 마진: 100만원 (20%)
프리랜서에게 지급: 150만원 (30%)
실제 사례 분석
서울시 홍보물 디자인 프로젝트 (예산 500만원)
1차 업체 (광고 대행사): 마진 150만원 (30%) → "기획비"
2차 업체 (디자인 스튜디오): 마진 100만원 (20%) → "관리비"
3차 업체 (소규모 에이전시): 마진 100만원 (20%) → "중개비"
실제 작업 프리랜서: 수령 150만원 (30%) → "실작업비"
작업 시간 대비 시급
프리랜서가 해당 프로젝트에 투입한 시간: 80시간
실수령액: 150만원
시급: 18,750원 (최저시급 9,860원의 1.9배)
하지만 프리랜서는 4대보험, 퇴직금, 연차 없이 순수 작업 시간만 보상받으므로, 실질 시급은 최저임금 수준입니다.
왜 이런 구조가 유지되는가?
정부 발주 시스템: 최저가 낙찰제로 중간 업체 개입 필수
프리랜서 개인 자격: 나라장터 입찰 불가 (법인/개인사업자만 가능)
책임 회피: 1차 업체는 실작업 없이 "관리·감독" 명목으로 마진 확보
정보 비대칭: 프리랜서는 원 발주 금액을 모르는 경우가 대부분
정부 발주금 흐름 (단위: 만원)
출처: 조달청 발주 사례 분석
Data Analysis
숫자로 보는 하청 구조의 실체
연간 착취 규모
2,100만원
프리랜서 1인당 연간 손실
계산: (500만원 - 150만원) × 월평균 5건
프리랜서 400만명 기준
연간 총 착취액: 84조원
실제 작업자에게 미지급
GDP 대비 4.2%
단계별 마진율
20-30%
중간 업체 평균 마진
1차 업체: 30% (관리·기획비)
2차 업체: 20% (중개·조정비)
실작업 없이 마진만 확보
"갑질" 구조 고착화
프리랜서 협상력 제로
프리랜서 소득 현실
150만원
월 평균 실수령액
최저생계비: 200만원
생계비 미달 75%
4대보험 가입 불가
저축 여력 제로
노후 준비 불가능
Data Table
발주 금액에 따른 프리랜서 실수령액 (단위: 만원)
정부 발주액
1차 마진(30%)
2차 마진(20%)
3차 마진(20%)
실수령(30%)
착취액
300
90
42
33
90
210 (70%)
500
150
70
55
150
350 (70%)
1,000
300
140
110
300
700 (70%)
2,000
600
280
220
600
1,400 (70%)
5,000
1,500
700
550
1,500
3,500 (70%)
*가정: 3단계 하청 구조, 각 단계별 마진율 적용
*출처: 한국노동사회연구소 프리랜서 실태조사 (2021)
표 해석: 발주 금액이 클수록 착취 절대액도 증가합니다. 5,000만원 프로젝트의 경우 중간 착취액이 3,500만원에 달하지만, 프리랜서는 1,500만원만 수령합니다.
Timeline
하청 구조는 어떻게 만들어졌나 (2000-2024)
1
1단계: 형성기 (2000-2010)
정부 발주 전자화 (나라장터 출범)
법인/개인사업자만 입찰 가능
대형 광고 대행사 독점 구조
프리랜서는 "하청" 인력으로만 참여
2
2단계: 확대기 (2010-2020)
디지털 전환으로 발주 급증
중간 업체 난립 (디자인 스튜디오)
2-3단계 하청 구조 일반화
프리랜서 협상력 약화
3
3단계: 고착화 (2020-2024)
코로나로 비대면 발주 증가
플랫폼 수수료 20-30% 추가
4-5단계 하청도 발생
프리랜서 실수령 20-30%로 하락
4
4단계: 현재 (2026)
하청 구조 "당연시"
정부 정책 실효성 낮음
프리랜서 400만명 중 280만명 4대보험 미가입
구조적 개선 요구 증가
Comparison
해외는 어떻게 하청 착취를 막을까?
미국 (직접 계약)
시스템: 프리랜서 직접 계약 (Upwork, Fiverr)
수수료: 20% (플랫폼 수수료만)
실수령: 80%
중간 업체 개입 최소화
발주자-프리랜서 직접 소통
계약서 표준화
독일 (법적 보호)
시스템: 프리랜서 보호법 (Freelancer Protection Act)
수수료: 10-15%
실수령: 85-90%
중간 착취 불법화
최저 단가 법제화
4대보험 의무 가입
일본 (소속사 모델)
시스템: 에이전시 소속 (K-Pop 모델 유사)
수수료: 20-30% (소속사 수수료)
실수령: 70-80%
소속사가 4대보험 부담
안정적 일감 제공
백업 시스템 운영
한국 (현재)
시스템: 다단계 하청 구조
수수료: 70% (중간 착취)
실수령: 30%
3-5단계 하청 일반화
법적 보호 장치 전무
4대보험 미가입 70%
Data Table
발주 방식에 따른 프리랜서 수령액 차이
발주 방식
발주액
중간 마진
플랫폼 수수료
실수령액
실수령률
정부 직접 발주
500만원
0원
0원
500만원
100%
1단계 하청
500만원
150만원
0원
350만원
70%
2단계 하청
500만원
250만원
0원
250만원
50%
3단계 하청 (현재)
500만원
350만원
0원
150만원
30%
플랫폼 + 하청
500만원
350만원
30만원
120만원
24%
시사점: 직접 발주 시 프리랜서는 500만원 전액을 수령할 수 있지만, 현재 구조에서는 30% 이하만 받습니다. 플랫폼 수수료까지 더하면 24%로 떨어집니다.
"하청 구조는 프리랜서의 노동을 착취하는 합법적 시스템입니다. 실제 작업자가 30%만 받는 구조에서 양질의 결과물을 기대하는 것은 모순입니다."
한국노동사회연구소, 2021 프리랜서 실태조사 보고서
Living Cost
프리랜서 월 소득 150만원의 현실
월 150만원으로는 기본 생활비 135만원을 감당하기도 빠듯합니다. 4대보험료(27만원), 저축, 노후 준비는 엄두도 내지 못합니다.
월 소득 150만원 대비 생활비 구성
저축: 0원 (0%), 여유: 15만원 (10%)
Conclusion
하청 구조 해체, 지금 시작해야 한다
착취 구조의 본질
정부 발주 500만원 중 프리랜서가 150만원(30%)만 받는 구조는 개인의 문제가 아닙니다. 나라장터 입찰 자격을 법인·개인사업자로 제한하고, 최저가 낙찰제를 유지하며, 중간 업체 개입을 방치한 "시스템의 문제"입니다.
중간 착취의 규모
프리랜서 400만명이 연평균 5건의 프로젝트를 수행한다고 가정하면:
1인당 연간 착취액: 2,100만원
전체 착취 규모: 84조원
이는 대한민국 GDP(2,200조원)의 3.8%에 해당합니다.
이 84조원은 실제 작업자가 아닌 중간 업체의 수익으로 빠져나갑니다.
왜 바뀌지 않는가?
기득권 구조: 1-2차 업체는 "관리·감독" 명목으로 마진 확보, 변화 저항
정보 비대칭: 프리랜서는 원 발주액을 모르는 경우가 대부분
정책 실효성 부재: 정부 지원 연 1.35조원이나 하청 구조 개선 없음
개인화된 책임: "협상을 잘못한 프리랜서 탓"으로 개인 책임 전가
해외 사례가 주는 교훈
미국: 플랫폼 수수료 20%, 실수령 80% (직접 계약)
독일: 프리랜서 보호법으로 중간 착취 불법화, 실수령 85-90%
일본: 소속사 모델로 4대보험 보장, 실수령 70-80%
한국만 3단계 하청에 실수령 30%입니다.
지금 필요한 변화
나라장터 입찰 자격 확대: 소속사·협동조합 등 프리랜서 조직 형태 허용
적정 마진 규제: 중간 업체 마진 15% 이하로 제한 (조달청 고시)
발주 금액 공개 의무화: 프리랜서도 원 발주액 확인 가능하도록
직접 발주 인센티브: 중간 업체 없이 직접 계약 시 가산점 부여
소속사 모델 활성화: 법인이 4대보험 부담, 프리랜서는 안정적 복지
데이터가 말하는 진실
현재: 발주 500만원 → 실수령 150만원 (30%)
1단계 개선: 발주 500만원 → 실수령 350만원 (70%, 중간 업체 1곳만 거침)
직접 계약: 발주 500만원 → 실수령 400만원 (80%, 플랫폼 수수료 20%)
소속사 모델: 발주 500만원 → 실수령 475만원 (95%, 소속사 수수료 5%)
마무리: 30%에서 95%로
프리랜서가 정당한 대가를 받는 것은 시혜가 아닌 권리입니다. 실제 작업자가 30%만 받는 구조에서 양질의 결과물을 기대할 수 없으며, 이는 결국 발주자에게도 손해입니다.
하청 구조 해체는 프리랜서만의 문제가 아닙니다. 대한민국 경제의 84조원이 비효율적으로 새는 구조적 문제입니다. 지금 바꾸지 않으면, 앞으로도 70%는 계속 증발할 것입니다.
프리랜서 400만 시대, 30%의 진실을 직시하고 95%의 미래를 만들어야 합니다.
출처: 조달청, 한국노동사회연구소 (2021)
하청 착취, 함께 바꿔나가야 합니다
이 글이 도움이 되셨다면 주변 프리랜서들과 공유해주세요. 구조적 문제는 개인이 아닌 시스템 변화로 해결해야 합니다.
다른 프리랜서 이슈 보기
// iframe 높이 자동 전달 (부모 창에 메시지 전송)
function sendHeightToParent() {
if (window.parent !== window) {
const height = Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.documentElement.clientHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight
);
window.parent.postMessage({
type: 'iframe-resize',
height: height
}, '*');
}
}
// 초기 높이 전달
window.addEventListener('load', () => {
sendHeightToParent();
setTimeout(sendHeightToParent, 2000);
});
// 리사이즈 이벤트 감지
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(sendHeightToParent, 300);
});
// MutationObserver로 DOM 변경 감지
const observer = new MutationObserver(() => {
sendHeightToParent();
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});
// AOS 초기화
AOS.init({
duration: 800,
once: true,
offset: 100
});
// 카운터 애니메이션
function initCounters() {
if (typeof CountUp === 'undefined' && typeof countUp === 'undefined') {
document.querySelectorAll('.stat-number').forEach(el => {
const target = parseFloat(el.dataset.count);
if (target && !isNaN(target)) {
const hasDecimal = target % 1 !== 0;
const decimals = hasDecimal ? 1 : 0;
el.textContent = target.toFixed(decimals);
}
});
setTimeout(initCounters, 500);
return;
}
const CountUpClass = typeof CountUp !== 'undefined' ? CountUp : countUp;
document.querySelectorAll('.stat-number').forEach(el => {
const target = parseFloat(el.dataset.count);
if (target && !isNaN(target)) {
const hasDecimal = target % 1 !== 0;
const decimals = hasDecimal ? 1 : 0;
const options = {
duration: 2,
useEasing: true,
separator: ',',
decimal: '.',
decimals: decimals
};
try {
const counter = new CountUpClass(el, target, options);
if (counter.error) {
el.textContent = target.toFixed(decimals);
return;
}
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
counter.start();
observer.unobserve(entry.target);
}
});
}, { threshold: 0.5 });
observer.observe(el);
} catch (e) {
el.textContent = target.toFixed(decimals);
}
}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCounters);
} else {
setTimeout(initCounters, 100);
}
// 차트 초기화 함수
function initCharts() {
if (typeof Chart === 'undefined') {
setTimeout(initCharts, 500);
return;
}
// 차트 1: 정부 발주금 흐름 (바 차트)
const ctx1 = document.getElementById('chart1');
if (ctx1) {
new Chart(ctx1.getContext('2d'), {
type: 'bar',
data: {
labels: ['정부 발주', '1차 업체', '2차 업체', '3차 업체', '프리랜서 실수령'],
datasets: [{
label: '금액 (만원)',
data: [500, 350, 250, 150, 150],
backgroundColor: [
'rgba(65, 105, 225, 0.8)',
'rgba(135, 206, 235, 0.8)',
'rgba(176, 196, 222, 0.8)',
'rgba(211, 211, 211, 0.8)',
'rgba(90, 90, 90, 0.8)'
],
borderWidth: 0,
borderRadius: 8
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0,0,0,0.8)',
padding: 12,
titleFont: { size: 14, weight: 'bold' },
bodyFont: { size: 13 },
cornerRadius: 8,
callbacks: {
label: function(context) {
return context.parsed.y + ' 만원';
}
}
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: '금액 (만원)'
},
grid: {
color: '#F3F4F6'
},
ticks: {
callback: function(value) {
return value + '만원';
}
}
},
x: {
grid: {
display: false
}
}
}
}
});
}
// 차트 2: 월 소득 대비 생활비 (파이 차트)
const ctx3 = document.getElementById('chart3');
if (ctx3) {
new Chart(ctx3.getContext('2d'), {
type: 'pie',
data: {
labels: ['주거비', '식비', '교통·통신비', '공과금', '의료비', '기타 생활비', '여유'],
datasets: [{
data: [50, 30, 15, 10, 10, 20, 15],
backgroundColor: [
'rgba(65, 105, 225, 0.8)',
'rgba(135, 206, 235, 0.8)',
'rgba(90, 90, 90, 0.6)',
'rgba(200, 200, 200, 0.6)',
'rgba(255, 99, 132, 0.6)',
'rgba(255, 206, 86, 0.6)',
'rgba(153, 102, 255, 0.6)'
],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 20,
font: { size: 14 }
}
},
tooltip: {
backgroundColor: 'rgba(0,0,0,0.8)',
padding: 12,
titleFont: { size: 14, weight: 'bold' },
bodyFont: { size: 13 },
cornerRadius: 8,
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.parsed || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return label + ': ' + value + '만원 (' + percentage + '%)';
}
}
}
}
}
});
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
setTimeout(initCharts, 100);
});
} else {
setTimeout(initCharts, 100);
}
