Media Art ProgrammingWeek 11 · Period 01 Handout

p5.js / Media Art Programming

11주차 1교시 — 데이터를 코드로 불러오기: preload, JSON, CSV

External Data and Data Art 주제의 학생용 강의 자료입니다.

WEEK 11 PERIOD 01 P5.JS MEDIA ART

11주차 1교시 — 데이터를 코드로 불러오기: preload, JSON, CSV

강의 아웃라인: week-11-outline 다음 교시: week-11-period2-student (데이터를 시각으로 매핑)

항목 내용
대상 P5.js 입문자 (테크아트 전공)
소요 시간 45분
핵심 도구 P5.js Web Editor, data.json, data.csv
학습 목표
  • preloadsetupdraw의 실행 순서를 설명할 수 있습니다
  • loadJSON으로 JSON 파일을 불러오고 점 표기법으로 데이터에 접근할 수 있습니다
  • loadTable로 CSV 파일을 불러오고 getString / getNum으로 값을 꺼낼 수 있습니다

도입

10주차에서 11주차로

지난주에는 힘과 물리 시뮬레이션을 다루며 중력 0.1, 바람 0.05 같은 숫자를 코드에 직접 적었습니다. 손으로 쓴 숫자가 시뮬레이션을 움직였습니다.

이번 주는 한 발 더 나아갑니다. 그 숫자가 현실의 데이터라면 어떻게 될까요?

예를 들어, 오늘 서울의 실제 기온이 18도라면 파티클 색상이 미지근한 주황으로, 내일 5도로 떨어지면 자동으로 파란색으로 바뀌게 만들 수 있습니다. 코드는 그대로 두고 데이터 파일만 바꾸면 그림이 따라 바뀌는 구조입니다.

전 세계 지진 데이터를 점으로 표현한 시각화에서, 지진이 큰 곳은 큰 원, 작은 곳은 작은 원으로 그려지는 예시를 떠올려보세요. 이 그림에서 숫자를 손으로 입력한 것은 한 개도 없습니다. 전부 데이터 파일에서 자동으로 가져온 값입니다.

08 earthquake data map

오늘 배우는 것은 바로 이것입니다 — 외부 데이터 파일을 P5.js로 불러와서, 데이터가 그림을 만들게 하기.

오늘 할 일

이번 시간이 끝나면 다음 세 가지를 할 수 있게 됩니다.

  1. JSON 파일과 CSV 파일을 구분하고, 메모장으로 열어서 읽을 수 있다
  2. preload()가 왜 필요한지 30초 안에 설명할 수 있다
  3. JSON과 CSV 양쪽에서 도시 인구 데이터를 꺼낼 수 있다

데이터를 다루는 두 가지 태도

본격적으로 들어가기 전에, ’데이터로 무언가를 한다’는 것이 어떤 의미인지 정리합니다. 크게 두 가지 태도가 있습니다.

데이터 시각화 — 데이터를 읽히게 만드는 일입니다. 막대 그래프, 선 그래프, 지도 위의 점이 대표적인 예입니다. 목적은 정보 전달입니다. “이 도시 인구가 저 도시보다 두 배 많다”가 한눈에 보여야 성공한 시각화입니다.

데이터 아트 — 데이터를 느끼게 만드는 일입니다. 정확한 비교는 어려워도, 보면서 어떤 인상이나 감정이 남는 표현입니다. 경험이 목적입니다.

15 data visualization vs data art

두 작품을 짧게 살펴봅니다.

Dear Data (조지아 루피·스테파니 포사베츠) — 두 디자이너가 1년 동안 매주 자기 일상을 데이터로 기록해서, ‘이번 주에 웃은 횟수’, ‘잠을 못 잔 시간’, ‘거울 본 횟수’ 같은 일상의 숫자를 엽서에 손으로 그려 서로 보낸 작업입니다. 숫자가 색·선·도형으로 바뀌었습니다.

09 dear data postcards

Aaron Koblin “Flight Patterns” — 미국의 모든 항공편을 선으로 그린 작품입니다. 데이터가 수십만 건인데, 자동으로 그렸더니 미국 지도의 윤곽이 저절로 떠올랐습니다.

10 flight patterns style

두 사례 모두 데이터가 색, 선, 위치 같은 시각 요소로 번역됐다는 점이 같습니다. 오늘 배우는 기술이 이 과정을 코드로 가능하게 합니다. 표현 방향은 작업자의 선택입니다.


핵심 개념 1 — JSON과 CSV, 두 가지 데이터 파일 형식

오늘 다룰 파일 형식은 두 가지입니다. 코드로 들어가기 전에 파일 자체의 모양을 봅니다.

JSON

첫 번째는 JSON입니다. 풀어쓰면 JavaScript Object Notation. 이름에 JavaScript가 들어 있고, P5.js도 JavaScript 기반이라 둘의 궁합이 좋습니다.

{
  "cities": [
    { "name": "서울", "population": 9736027, "area": 605 },
    { "name": "부산", "population": 3359527, "area": 770 },
    { "name": "대구", "population": 2385412, "area": 883 }
  ]
}

세 가지 기호만 알면 구조를 읽을 수 있습니다.

  • 중괄호 { } — 하나의 묶음 (객체). 7주차 클래스로 만든 객체와 같은 모양입니다
  • "키": 값 — 이름표와 내용. "name": "서울"은 “name이라는 이름표 아래 서울이 있다”는 의미입니다
  • 대괄호 [ ] — 같은 종류 여러 개를 줄 세운 것 (배열). "cities": [ ... ]는 도시들이 줄 서 있는 모양입니다

7주차에서 ball.x, ball.size로 객체의 값을 꺼냈던 것과 같이, JSON에서도 점(.)으로 값을 꺼냅니다.

CSV

두 번째는 CSV입니다. Comma-Separated Values, 쉼표로 구분된 값. JSON보다 훨씬 단순합니다.

name,population,area
서울,9736027,605
부산,3359527,770
대구,2385412,883

표 형태입니다. 첫 줄은 열 이름(header)이고, 그 아래는 각 행입니다. 쉼표가 칸막이 역할을 합니다.

엑셀이나 구글 시트에서 ’다른 이름으로 저장 → CSV’를 누르면 정확히 이 형태가 됩니다. 스프레드시트에서 만든 데이터를 그대로 P5.js로 가져올 수 있습니다.

둘을 언제 쓸까

항목 JSON CSV
모양 중괄호 + 키-값, 중첩 가능 쉼표 구분 표, 단순
접근 방법 키 이름으로 (data.cities[0].name) 행 번호 + 열 이름 (table.getString(0, "name"))
어울리는 데이터 웹 API, 설정 파일, 중첩 구조 엑셀에서 내보낸 통계, 단순 표
공통점 둘 다 일반 텍스트 파일. 메모장으로 열 수 있습니다
02 json vs csv
기억할 한 줄

표 형태면 CSV, 중첩 구조면 JSON. 오늘은 둘 다 다룹니다. 실습에서는 JSON으로 진행하지만, CSV도 같이 알면 어디서 데이터를 가져와도 대응할 수 있습니다.

확인 질문

엑셀에서 만든 가게 매출 표를 P5.js로 가져오려면 어떤 형식이 더 자연스러울까요?

: CSV. 엑셀에서 바로 내보내기 가능하고, 표 구조라서 잘 맞습니다.


핵심 개념 2 — preload()가 왜 따로 있을까

지금까지의 실행 순서

지금까지 사용한 P5.js의 흐름은 다음과 같았습니다.

setup() → draw() → draw() → draw() → ...

setup()이 한 번, draw()가 매 프레임 반복되는 구조입니다. 오늘부터는 여기에 하나가 더 추가됩니다.

preload() → setup() → draw() → draw() → ...

preload()가 가장 앞에 있고, preload() 안의 일이 완전히 끝날 때까지 setup()은 시작되지 않습니다.

01 preload flow

왜 따로 있는가

이유는 한 가지 사실 때문입니다 — 데이터 파일을 읽는 데는 시간이 걸립니다.

파일이 크면 더 오래 걸리고, 인터넷에서 가져오면 네트워크 속도에 따라 들쭉날쭉합니다. 만약 setup() 안에서 loadJSON을 호출하면 다음과 같은 일이 벌어집니다.

let data;

function setup() {
  createCanvas(400, 400);
  data = loadJSON("data.json");  // 읽기 시작 (끝날 때까지 안 기다림)
  console.log(data);             // 아직 비어 있음 → undefined
}

loadJSON읽기를 시작만 하고 바로 다음 줄로 넘어갑니다. 그 다음 줄에서 data를 쓰려고 하면 아직 비어 있어서 에러가 발생합니다.

preload()는 이 문제를 해결합니다. P5.js에게 ‘이 안의 일이 다 끝날 때까지 setup() 시작하지 마’ 라고 알려주는 자리입니다.

식당 비유

preload()는 식당의 재료 준비 단계에 해당합니다. 셰프(setup)가 요리를 시작하기 전에 재료가 다 배달되어야 합니다. 채소도 안 왔는데 도마부터 두드리면 진행이 막힙니다. 그래서 P5.js는 ’재료 다 왔어요’라는 신호를 받을 때까지 셰프를 잡아둡니다.

기본 구조

let data;

function preload() {
  data = loadJSON("data.json");  // 데이터 준비
}

function setup() {
  createCanvas(400, 400);
  console.log(data);  // 여기에선 data가 준비되어 있음
}

function draw() {
  background(220);
}
주의

이번 수업에서는 preload() 안에 로드 함수만 둡니다. loadJSON, loadTable, loadImage, loadFont 같은 함수들입니다. createCanvas나 도형 그리기는 setup()에서 해야 합니다.

확인 질문

P5.js의 실행 순서를 세 단계로 말해볼까요?

: preload()setup()draw() 반복.


핵심 개념 3 — loadJSON()으로 JSON 불러오기

파일 준비

P5.js Web Editor에서 데이터 파일을 추가합니다.

14 p5 file upload steps
  1. 화면 왼쪽 위 화살표() 클릭해서 파일 패널 열기
  2. 파일 목록 위쪽의 클릭 → “Create File” 선택
  3. 파일명 data.json 입력 후 생성
  4. 아래 내용을 그대로 붙여넣고 저장 (Ctrl/Cmd + S)
{
  "cities": [
    { "name": "서울", "population": 9736027, "area": 605 },
    { "name": "부산", "population": 3359527, "area": 770 },
    { "name": "대구", "population": 2385412, "area": 883 },
    { "name": "인천", "population": 2948375, "area": 1063 },
    { "name": "광주", "population": 1455048, "area": 501 }
  ]
}

한국 5개 도시의 이름·인구·면적 데이터입니다. 곧 이 데이터를 코드로 꺼냅니다.

로드하고 콘솔로 확인

let cityData;

function preload() {
  cityData = loadJSON("data.json");
}

function setup() {
  createCanvas(400, 400);
  console.log(cityData);
}

이게 전부입니다. preload()에서 한 줄, setup()에서 콘솔 확인 한 줄.

작업 습관

데이터를 시각화하기 전에 항상 console.log로 데이터 모양을 먼저 봅니다. 데이터를 안 보고 그림부터 그리면, 버그가 났을 때 무엇이 잘못된 것인지 찾기 어렵습니다.

점 표기법 — 한 단계만 깊이 가보기

데이터 안의 값을 꺼낼 때는 점(.)을 써서 단계별로 들어갑니다.

function setup() {
  createCanvas(400, 400);

  console.log(cityData.cities);          // 도시 배열 5개
  console.log(cityData.cities[0]);       // 첫 번째 도시 객체
  console.log(cityData.cities[0].name);  // "서울"
}

세 줄에서 점이 한 단계씩 깊어집니다. cityData → 그 안의 cities 배열 → 0번째 → 그 객체의 name.

7주차에 ball.x로 객체 프로퍼티 꺼냈던 그 문법, 그대로입니다. 새 문법이 아닙니다.

모든 도시 꺼내기 — for문

도시 5개를 cities[0], cities[1]처럼 다섯 줄로 쓰는 대신, 6주차 for문을 그대로 가져옵니다.

function setup() {
  createCanvas(400, 400);

  let cities = cityData.cities;
  for (let i = 0; i < cities.length; i++) {
    let city = cities[i];
    console.log(city.name + " — 인구 " + city.population);
  }
}

기대 콘솔 출력.

서울 — 인구 9736027
부산 — 인구 3359527
대구 — 인구 2385412
인천 — 인구 2948375
광주 — 인구 1455048

let city = cities[i] 한 줄이 핵심입니다. i번째 도시를 city라는 짧은 이름으로 받아두면, 그 다음부터 city.name, city.population로 깔끔하게 쓸 수 있습니다. cities[i].name을 반복하는 것보다 읽기 좋습니다.

확인 질문

cityData.cities[2].name은 어떤 도시일까요?

: 대구. 인덱스 0이 서울이니까 2면 세 번째, 대구.


핵심 개념 4 — loadTable()로 CSV 불러오기

파일 준비

P5.js Web Editor에서 data.csv 파일을 새로 만들고 아래 내용을 붙여넣습니다.

name,population,area
서울,9736027,605
부산,3359527,770
대구,2385412,883
인천,2948375,1063
광주,1455048,501

JSON과 똑같은 데이터, 형식만 표입니다.

로드 — 인자 세 개

let table;

function preload() {
  table = loadTable("data.csv", "csv", "header");
}

function setup() {
  createCanvas(400, 400);
  console.log(table.getRowCount());
}

loadTable의 인자가 세 개입니다.

  1. "data.csv" — 파일 이름
  2. "csv" — 형식이 CSV라고 알려주는 표시
  3. "header" — 첫 줄을 데이터가 아니라 열 이름으로 인식하라는 지시. 이걸 빼면 “name, population, area”도 데이터로 들어가서 결과가 망가집니다

table.getRowCount()로 행 수를 찍어보면 5가 나옵니다. 헤더 빼고 5줄.

값 꺼내기 — 두 메서드만 기억

function setup() {
  createCanvas(400, 400);

  console.log(table.getString(0, "name"));        // "서울"
  console.log(table.getNum(0, "population"));     // 9736027
}

메서드 두 개만 알면 됩니다.

  • getString(행번호, "열이름") — 글자(이름·문자) 가져오기
  • getNum(행번호, "열이름") — 숫자 가져오기

CSV 파일에서는 모든 값이 먼저 글자로 저장됩니다. 숫자도 "9736027"이라는 글자로 들어 있습니다. getNum은 그 값을 실제 숫자로 바꿔주는 함수입니다.

흔한 실수

인구를 getString으로 꺼내서 더하면? 9736027 + 3359527 = 13095554가 아니라, 글자 이어붙이기 "97360273359527"이 됩니다. 숫자는 반드시 getNum.

전체 행 순회

for문으로 행 번호를 돌립니다.

function setup() {
  createCanvas(400, 400);

  for (let r = 0; r < table.getRowCount(); r++) {
    let name = table.getString(r, "name");
    let pop = table.getNum(r, "population");
    console.log(name + " — 인구 " + pop);
  }
}

JSON에서 cities[i].name을 꺼냈던 것과 패턴이 똑같습니다. for문으로 인덱스 돌리고, 각 항목에서 값 두 개 꺼내고, 사용. JSON이든 CSV든 이 패턴만 익히면 됩니다.

JSON과 CSV 비교

작업 JSON CSV
로드 loadJSON("file.json") loadTable("file.csv", "csv", "header")
전체 개수 data.cities.length table.getRowCount()
i번째 이름 data.cities[i].name table.getString(i, "name")
i번째 인구 data.cities[i].population table.getNum(i, "population")
핵심 패턴 for문으로 인덱스 돌리기 for문으로 인덱스 돌리기
기억할 한 줄

JSON은 점으로, CSV는 메서드로. for문 순회 패턴은 똑같다.

확인 질문

CSV에서 인구 숫자를 가져올 때 getString 쓰면 어떻게 될까요?

: 글자로 와서 숫자 계산이 안 됩니다. getNum을 써야 합니다.


예제 — 처음부터 끝까지 한 번에

지금까지 본 내용을 P5.js Web Editor에서 처음부터 끝까지 이어 봅니다.

예제 1 — JSON 로드

  1. P5.js Web Editor에서 새 스케치 열기
  2. 파일 패널에서 data.json 새로 만들고, 도시 5개 데이터 붙여넣기 → 저장
  3. sketch.js에 아래 코드 입력
let cityData;

function preload() {
  cityData = loadJSON("data.json");
}

function setup() {
  createCanvas(400, 400);
  console.log(cityData);
  console.log(cityData.cities[0].name);
}
  1. 실행 → 콘솔 열기
  2. 첫 줄에 객체, 두 번째 줄에 "서울"이 찍히는지 확인
  3. 콘솔에서 객체 옆 화살표()를 클릭해 펼쳐 보면 데이터 구조가 한눈에 들어옵니다

시각화 들어가기 전에 항상 이 단계를 거치는 습관을 들이세요.

예제 2 — CSV 로드

  1. 파일 패널에서 data.csv 새로 만들고, 같은 데이터를 CSV로 붙여넣기 → 저장
  2. sketch.js를 아래로 교체
let table;

function preload() {
  table = loadTable("data.csv", "csv", "header");
}

function setup() {
  createCanvas(400, 400);
  console.log("행 수: " + table.getRowCount());
  for (let r = 0; r < table.getRowCount(); r++) {
    console.log(table.getString(r, "name") + " — " + table.getNum(r, "population"));
  }
}
  1. 실행 → 콘솔에서 5개 도시 출력 확인

JSON과 모양은 다르지만, 콘솔에 찍히는 결과는 똑같습니다. 도구만 다른 것입니다.

예제 3 — preload()를 빼면 어떻게 되는가

JSON 스케치로 돌아가서, preload를 통째로 주석 처리하거나 삭제하고, loadJSON 호출을 setup() 안 첫 줄로 옮깁니다.

let cityData;

// function preload() {
//   cityData = loadJSON("data.json");
// }

function setup() {
  createCanvas(400, 400);
  cityData = loadJSON("data.json");
  console.log(cityData.cities[0].name);  // 에러 예정
}

실행하면 콘솔에 다음 에러가 출력됩니다.

TypeError: Cannot read properties of undefined (reading 'cities')

cityData가 아직 안 채워진 상태에서 .cities를 꺼내려고 하니까 에러입니다. 비유로만 설명했던 식당 이야기가 실제 코드에서 그대로 나타나는 장면입니다.

다시 preload로 옮기고 실행하면 정상 출력됩니다. 앞으로 같은 에러를 만나면 ‘preload 빼먹었구나’ 떠올리면 됩니다.


정리

한 화면 요약

개념 한 줄 정의 핵심 코드
JSON 중괄호 + 키-값, 중첩 가능 loadJSON("file.json") / data.cities[i].name
CSV 쉼표 구분 표, 단순 loadTable("file.csv", "csv", "header") / table.getNum(i, "population")
preload() 데이터 다 준비될 때까지 setup 대기 preload → setup → draw 순서
한 문장 요약

JSON은 점으로, CSV는 메서드로, 데이터를 불러올 땐 항상 preload()로.

2교시 예고

1교시에서는 데이터를 불러와서 콘솔에 찍는 단계까지 진행했습니다. 2교시에서는 이 데이터를 그림으로 바꿉니다.

핵심은 5주차에서 배운 map()입니다. 인구 → 원 크기, 면적 → 위치, 인덱스 → 색상. 데이터의 숫자를 시각 요소로 번역하는 작업이 데이터 시각화·데이터 아트의 출발점입니다.