Frontend 12
게시판 데이터 모델링: 왜 '객체 배열'일까요?
배열과 객체는 알겠는데 게시판의 글 목록이 왜 객체 배열 형태가 되는지 연결이 안 된다.
근거 · 교안 p48-p53
1장: 게시글 하나, 왜 객체로 만들까요?
솔라는 모니터 옆에 붙여둔 작은 메모지들을 가만히 들여다보고 있었다. 어제 커뮤니티에서 본 글귀 하나가 계속 머릿속을 맴돌았기 때문이다. “게시글 하나는 객체로, 게시글 목록은 객체들의 배열로 표현한다.” 객체도 알고 배열도 아는 단어였지만, 두 단어가 합쳐져 만들어진 문장은 어쩐지 당연하게 받아들여지지 않았다. 꼭 그래야만 할까?
솔라는 연필을 들어 깨끗한 메모지 위에 무언가 적기 시작했다.
게시글1_제목 = "고양이 사진 자랑합니다"
게시글1_작성자 = "솔라"
게시글1_내용 = "우리 집 고양이 보세요. 귀엽죠?"
옆에서 조용히 책을 읽던 언니 루나가 솔라의 손을 멈추게 한 것은 바로 그때였다. 루나는 솔라의 어깨너머로 메모지를 들여다보았다.
“게시글 데이터 정리하는구나.”
“응. 그런데 언니, 다들 왜 게시글 하나를 꼭 ‘객체’로 만들어야 한다고 해? 이렇게 그냥 변수로 하나씩 만들면 안 돼? 이게 훨씬 직관적이잖아. 제목, 작성자, 내용. 딱 떨어지고.”
솔라의 목소리에는 진심 어린 의문이 담겨 있었다. ‘다들 그렇게 하니까’라는 이유만으로는 납득하고 싶지 않은 고집도 살짝 묻어났다.
루나는 솔라의 질문에 바로 답하는 대신, 솔라가 쓴 메모지를 손가락으로 가볍게 톡톡 두드렸다.
“깔끔하네. 그럼, 이 게시글에 사람들이 ‘좋아요’를 누를 수 있다고 해보자. ‘좋아요’ 수는 처음엔 0개겠지?”
“응.”
솔라는 망설임 없이 연필을 다시 들었다. 그리고 방금 쓴 내용 밑에 한 줄을 더 추가했다.
게시글1_좋아요 = 0
“이것도 간단하지.” 솔라는 만족스러운 표정을 지었다. 변수를 하나 더 추가하면 그만이었다. 무엇이 문제란 말인가.
루나는 잠시 말이 없었다. 마치 솔라가 스스로 다음 질문에 도달하기를 기다리는 사람처럼 보였다. 잠시 후, 루나가 나지막이 말했다.
“만약에, 솔라 네가 만든 이 게시글 데이터를 어딘가 다른 곳에 보여줘야 한다고 상상해 봐. 예를 들어, 메인 화면의 ‘인기 글’ 목록 같은 곳에. 그럼 이 게시글의 정보들을 전부 그쪽으로 보내줘야겠지?”
“그렇겠지? 제목, 작성자, 내용, 좋아요 수. 이 네 가지를 다 보내줘야지.”
“응, 네 개. 항상 같이 다녀야 하는 한 세트네.” 루나가 말했다. “만약 게시글에 ‘조회수’도 표시해야 한다면?”
“그럼 게시글1_조회수 변수를 하나 더 만들고, 그것까지 다섯 개를 보내주면 되지.”
솔라는 여전히 자신만만했다. 하지만 루나의 다음 말에 솔라의 표정이 미세하게 변하기 시작했다.
“매번 그렇게 할 수 있을까? 게시글 정보를 필요로 하는 곳이 한두 군데가 아니라 열 군데라면? 그때마다 다섯 개의 변수를 실수 없이 다 챙겨서 넘겨줄 수 있을까? 만약 나중에 ‘댓글 수’도 추가되면, 그 열 군데를 전부 찾아가서 코드를 고쳐야 할 텐데.”
솔라의 눈앞에 여러 갈래로 흩어지는 데이터 조각들이 그려졌다. 게시글1_제목은 저쪽으로, 게시글1_작성자는 이쪽으로. 게시글1_좋아요는 또 다른 곳으로. 이것들을 하나로 묶어주는 끈이 없었다. 그저 ‘게시글1’이라는 이름표만 희미하게 공유할 뿐, 본질적으로는 완전히 남남인 데이터들이었다. 함수에 데이터를 전달하는 장면을 상상하자 머리가 복잡해졌다. showPost(제목, 작성자, 내용, 좋아요, 조회수)… 속성이 추가될 때마다 이 함수의 모양도, 이 함수를 쓰는 모든 코드도 바꿔야만 한다.
“아…”
솔라의 입에서 나직한 탄식이 흘러나왔다. ‘간단하다’고 생각했던 방식이 사실은 가장 복잡하고 불안정한 길일지도 모른다는 생각이 처음으로 들었다. 데이터들이 서로 관련 있다는 사실을 코드 그 어디에도 알려주지 않은 채, 그저 개발자의 머릿속에만 의존하는 방식이었다.
그때 루나가 솔라의 메모지 옆에 놓인 새 메모지에 펜으로 네모난 상자를 하나 그렸다. 그리고 상자 위에 ‘게시글1’이라고 이름표를 붙였다.
“만약 이렇게 ‘게시글1’이라는 이름이 붙은 상자가 있다면 어떨까?”
루나는 상자 안을 몇 개의 칸으로 나누고, 각 칸에 ‘제목’, ‘작성자’, ‘내용’, ‘좋아요’라고 적어 넣었다.
게시글1 = {
제목: "고양이 사진 자랑합니다",
작성자: "솔라",
내용: "우리 집 고양이 보세요. 귀엽죠?",
좋아요: 0
}
솔라는 루나가 그린 그림을 물끄러미 바라보았다. 낱개로 흩어져 있던 정보들이 하나의 ‘상자’ 안에 가지런히 정리되어 있었다.
“이렇게 하면… ‘게시글1’ 상자 하나만 옮기면 그 안에 있는 정보들이 전부 한꺼번에 따라오는구나.”
솔라가 혼잣말처럼 중얼거렸다.
“나중에 ‘조회수’가 필요해지면, 그냥 이 상자 안에 ‘조회수’ 칸을 하나 더 만들기만 하면 돼. 상자를 통째로 주고받는다는 사실 자체는 변하지 않으니까, 코드를 고칠 필요도 훨씬 줄어들겠네.”
비로소 솔라는 깨달았다. 객체로 데이터를 묶는다는 것은 단순히 보기 좋게 꾸미는 일이 아니었다. 서로 깊은 관련이 있는 데이터들을 하나의 논리적인 단위, 하나의 ‘덩어리’로 인정해주는 행위였다. 그렇게 함으로써 데이터는 더 안전하게 이동하고, 더 쉽게 관리되며, 변화에 더 유연하게 대처할 수 있게 되는 것이다.
솔라는 자신이 썼던 메모지들을 한쪽으로 밀어놓고, 루나가 그려준 ‘상자’를 자신의 노트에 정성껏 옮겨 그렸다. 이제 ‘게시글 하나는 객체가 된다’는 문장이 더 이상 암기해야 할 규칙이 아니라, 당연한 귀결처럼 느껴졌다.
문득 새로운 궁금증이 고개를 들었다.
“좋아. 게시글 하나는 이렇게 상자, 즉 객체로 만드는 게 맞네. 그런데… 게시판에는 이런 글들이 하나가 아니라 수십, 수백 개가 있잖아. 그럼 이 상자들을 전부 어떻게 관리해야 하지? 게시글1, 게시글2, 게시글3… 이렇게 상자 백 개를 전부 따로따로 만들어야 하나?“
2장: 여러 게시글, 왜 배열에 담을까요?
솔라는 자신의 노트에 새로운 페이지를 펼쳤다. 방금 전 깨달음을 얻은 ‘게시글 상자’ 모델을 직접 적용해 볼 생각이었다. 어차피 게시판에는 글이 여러 개 있을 테니, 처음부터 몇 개를 만들어 보기로 했다. 솔라는 자신감 있게 연필을 움직였다. 마치 게시판 서버의 데이터베이스라도 된 것처럼.
post1 = { title: "첫 번째 글", author: "솔라" }
post2 = { title: "강아지도 귀여워요", author: "루나" }
post3 = { title: "세 번째 글입니다", author: "솔라" }
노트 위에는 post1, post2, post3라는 이름표가 붙은 세 개의 데이터 상자가 나란히 놓였다. 깔끔했다. 각 상자는 서로의 내용물을 침범하지 않으면서도, 게시글이라는 정체성을 명확히 드러내고 있었다. 솔라는 만족감에 고개를 끄덕였다. 지난 장에서 고민했던 ‘낱개 변수’의 문제점은 확실히 해결된 듯 보였다.
“그래. 이렇게 상자로 만들면 관리하기 편하네.”
솔라의 혼잣말을 들은 루나가 조용히 다가와 노트를 들여다보았다.
“벌써 게시글이 세 개나 생겼네. 좋아. 그럼 이제, 이 게시글 목록을 화면에 보여준다고 상상해 보자. 제목만 쭉 나열해서 보여주는 거야. 어떻게 할래?”
“간단하지.”
솔라는 즉시 답했다. 이 정도는 뻔했다.
“첫 번째 게시글 제목 보여주고, 두 번째 게시글 제목 보여주고, 세 번째 게시글 제목 보여주면 되지. 이렇게.”
솔라는 노트의 빈 공간에 코드를 흉내 내어 적었다.
print(post1.title)
print(post2.title)
print(post3.title)
“흠, 게시글이 3개일 때는 괜찮은 방법이네.” 루나가 말했다. “만약 100개라면?”
“100개라고?”
솔라의 손이 순간 멈칫했다. print(post1.title) 부터 print(post100.title) 까지, 100줄의 코드를 쓰는 자신의 모습이 그려졌다. 그건 ‘간단한’ 작업이 아니었다. 무엇보다도, 무척이나 어리석어 보였다.
“말도 안 돼. 그걸 어떻게 다 써. 뭔가… 반복하는 방법이 있을 거 아냐. ‘1번부터 100번까지, 순서대로 게시글의 제목을 출력해’ 라고 컴퓨터한테 한 번만 말하는 방법.”
솔라는 중얼거렸지만, 이내 자신의 모델이 가진 결정적인 한계를 깨달았다. post1, post2, post3… 이 변수들은 이름만 비슷할 뿐, 컴퓨터 입장에서는 완전히 별개의 존재들이었다. ‘다음 번 게시글’이라는 개념 자체가 없었다. post1 다음에 post2가 온다는 것은 오직 코드를 작성하는 사람의 머릿속에만 있는 순서일 뿐, 데이터 구조에는 그 어떤 연결고리도 없었다. 100개의 낱낱이 흩어진 상자를 관리하는 것은 100개의 낱개 변수를 관리하는 것과 본질적으로 다르지 않았다.
“아… 상자들을 그냥 이렇게 따로따로 두면, 결국 하나씩 다 이름을 불러줘야 하는구나.”
바로 그 때, 루나가 솔라가 그려둔 세 개의 상자 그림을 손으로 쓱 감싸 안는 시늉을 하며 말했다.
“이 상자들이 전부 따로따로 흩어져 있으니까 곤란한 거 아닐까? 만약 이 상자들을 순서대로 넣을 수 있는 긴 선반이 있다면 어때?”
루나는 연필을 들어 길고 네모난 괄호 [ ]를 그렸다. 그리고 그 안에 솔라가 만들었던 게시글 상자들을 쉼표로 구분해 집어넣었다. 변수 이름은 사라지고, 상자 그 자체만 남았다.
posts = [ { title: "첫 번째 글", author: "솔라" }, { title: "강아지도 귀여워요", author: "루나" }, { title: "세 번째 글입니다", author: "솔라" } ]
“이 posts라는 선반에는 순서가 있어. 첫 번째 칸, 두 번째 칸, 세 번째 칸. 컴퓨터는 0부터 숫자를 세니까, 0번 칸, 1번 칸, 2번 칸이라고 부르지.”
루나는 말을 이었다. “자, 이제 다시 아까 그 질문. 이 선반을 사용해서 모든 게시글의 제목을 출력하려면 어떻게 해야 할까?”
솔라는 루나가 그려준 새로운 그림을 뚫어지라 쳐다보았다. posts라는 이름의 선반. 그리고 그 안에 순서대로 놓인 게시글 상자들. 해답은 명확했다.
“이렇게 하면 되겠다! ‘posts 선반에 있는 모든 칸을 처음부터 끝까지 하나씩 확인하면서, 각 칸에 들어있는 상자의 제목을 출력해 줘.’ 라고 명령하면 돼. 게시글이 3개든 100개든, 명령은 딱 한 번이면 충분해.”
이제 ‘세 번째 게시글’을 찾는 일도 간단했다. post3라는 변수 이름을 기억할 필요 없이, 그저 ‘posts 선반의 2번 칸에 있는 것’을 꺼내오면 그만이었다. posts[2]. 훨씬 예측 가능하고 일관된 방식이었다.
솔라는 비로소 깨달았다. 배열, 즉 ‘선반’에 데이터를 담는다는 것은 단순히 여러 개의 데이터를 한 곳에 모아두는 것 이상의 의미를 가졌다. 그것은 데이터들에게 ‘순서’라는 질서를 부여하고, ‘목록’이라는 하나의 단위로 묶어주는 행위였다. 덕분에 우리는 수십, 수백 개의 데이터라도 단 하나의 명령으로 일괄 처리할 수 있는 강력한 힘을 얻게 되는 것이다.
솔라는 다시 모니터 옆 메모지를 바라보았다. “게시글 목록은 객체들의 배열이 된다.” 이제 문장의 뒷부분까지 완벽하게 이해되었다. 게시글 하나하나는 속성을 담은 ‘객체’ 상자가 되고, 그 상자들은 순서대로 ‘배열’ 선반에 담겨야만 효율적으로 관리할 수 있었다.
“그렇구나. 상자는 상자끼리 모아서 선반에 정리해야 다루기 편한 거였어.”
솔라는 만족스럽게 중얼거렸다. 그런데 문득, 한 가지 의문이 마음 한구석에서 스멀스멀 피어올랐다.
“알겠어. 데이터는 이렇게 ‘객체들의 배열’로 정리하는 게 맞아. 깔끔하고 강력하네. 그런데… 우리가 보는 게시판 화면은 그냥 글자랑 그림의 목록이잖아. 이 깔끔한 데이터 묶음이, 대체 어떻게 우리가 보는 그 화면으로 변하는 거지? 이 둘 사이에 뭔가 마지막 연결고리가 하나 더 있는 것 같은데…“
3장: 게시판 목록, 왜 ‘객체 배열’이어야 할까요?
솔라의 노트에는 이제 지난 시간의 깨달음이 명확한 형태로 자리 잡고 있었다. ‘게시글 상자’들을 ‘posts 선반’에 가지런히 정리해 둔 코드였다.
posts = [ { title: "첫 번째 글", author: "솔라" }, { title: "강아지도 귀여워요", author: "루나" }, { title: "세 번째 글입니다", author: "솔라" } ]
데이터를 어떻게 정리해야 하는지는 이제 알겠다. 하지만 솔라의 시선은 노트의 데이터와 머릿속에 떠오르는 실제 게시판 화면 사이의 보이지 않는 강을 건너지 못하고 있었다. 데이터는 데이터일 뿐, 화면은 화면 아닌가.
그때, 옆에서 지켜보던 루나가 연필을 들더니 솔라의 노트 위, 데이터 코드 옆 빈 공간에 간단한 그림을 그리기 시작했다. 직사각형으로 그린 게시판 화면 테두리 안에, 세 개의 가로줄을 그었다. 마치 게시글 목록처럼 보였다.
+--------------------------+
| 첫 번째 글 (솔라) |
| 강아지도 귀여워요 (루나) |
| 세 번째 글입니다 (솔라) |
+--------------------------+
데이터 구조와 화면 모형. 두 개의 그림이 나란히 놓이자, 솔라가 느끼던 막연한 간극이 비로소 눈에 보이는 질문이 되었다.
“알겠어. 데이터는 이렇게 ‘객체들의 배열’로 정리하는 게 맞아. 깔끔하고 강력하네. 그런데… 우리가 보는 게시판 화면은 그냥 글자랑 그림의 목록이잖아. 이 깔끔한 데이터 묶음이, 대체 어떻게 우리가 보는 저 그림으로 변하는 거지? 개발자는 이 둘을 어떻게 연결하는 거야? 단순히 ‘이렇게 해야 한다’는 것 이상으로, 이 구조가 왜 좋은지 납득하고 싶어.”
솔라의 질문은 더 이상 막연하지 않았다. 왼쪽의 데이터를 사용해서, 오른쪽의 그림을 그리는 가장 효율적인 방법은 무엇인가에 대한 구체적인 질문이었다.
루나는 오른쪽의 화면 그림을 가리켰다.
“좋은 질문이야. 그럼 우리가 직접 개발자가 되었다고 생각하고, 왼쪽의 posts 데이터를 이용해서 오른쪽 화면을 그린다고 상상해 보자. 가장 먼저 뭘 해야 할까?”
“음…” 솔라는 잠시 생각에 잠겼다. 지난 장에서 했던 생각이 떠올랐다. “posts 선반을 처음부터 끝까지 훑어야지. 반복하는 거야.”
“맞아. 반복. 그리고?”
“각 칸에서 게시글 상자를 하나씩 꺼내서… 그 상자 안에 있는 ‘제목’이랑 ‘작성자’를 화면의 각 줄에 그려주면 돼.”
솔라의 대답은 명쾌했다. ‘배열’이기에 반복할 수 있고, 각 항목이 ‘객체’이기에 .title이나 .author처럼 원하는 속성을 이름으로 정확히 꺼내 쓸 수 있었다. 이제 보니 둘의 조합은 환상적이었다.
루나는 고개를 끄덕이며 다음 과제를 던졌다. 마치 게임의 다음 스테이지 같았다.
“완벽해. 그럼 이번엔 요구사항이 조금 바뀌었어. 화면에 ‘솔라’가 쓴 글만 골라서 보여줘야 한다면?”
“솔라가 쓴 글만?”
솔라의 눈이 다시 왼쪽의 데이터 구조로 향했다. posts 배열 안에는 솔라가 쓴 글도, 루나가 쓴 글도 섞여 있었다. 여기서 어떻게 솔라의 글만 ‘필터링’ 할 수 있을까? 잠시 고민하던 솔라의 입가에 작은 미소가 번졌다. 답은 이미 데이터 구조 안에 있었다.
“이것도 할 수 있어! 아까랑 똑같이, posts 선반을 처음부터 끝까지 훑는 거야. 그러면서 상자를 하나씩 꺼낼 때마다 확인 작업을 하는 거지.”
솔라는 신이 나서 설명하기 시작했다.
“첫 번째 상자를 꺼내서 ‘작성자’가 ‘솔라’인지 확인해. 맞네? 그럼 이 상자의 ‘제목’을 화면에 그려. 두 번째 상자를 꺼내서 ‘작성자’를 확인해. ‘루나’네? 그럼 이건 그냥 통과. 세 번째 상자를 꺼내서 ‘작성자’를 확인해. ‘솔라’네? 이것도 화면에 그려. 이렇게 하면 돼!”
그 순간, 솔라는 거대한 깨달음과 마주했다.
왜 게시판 데이터를 ‘객체 배열’로 만들어야만 하는가. 그 이유는 단순히 데이터를 보기 좋게 ‘정리’하기 위함이 아니었다. 그것은 데이터를 ‘활용’하기 위한, 즉 화면을 그리고 상호작용하기 위한 최적의 설계였던 것이다.
배열의 ‘순회’ 기능과 객체의 ‘속성 접근’ 기능이 결합되자, “목록의 모든 데이터를 화면에 뿌린다”거나 “특정 조건에 맞는 데이터만 골라낸다” 같은 UI 개발의 핵심적인 작업들이 놀랍도록 간결하고 예측 가능한 코드로 바뀌었다. 만약 데이터가 다른 모양이었다면, 예를 들어 titles = ["첫 번째 글", ...] 과 authors = ["솔라", ...] 처럼 따로따로인 배열이었다면, ‘솔라가 쓴 글의 제목’을 찾는 일은 훨씬 복잡하고 지저분해졌을 것이다.
“아…! 이제 알겠다!” 솔라가 외쳤다. “데이터를 ‘객체 배열’로 만드는 건, 그냥 규칙이 아니었어. 화면을 그리는 코드가 가장 편하게 일할 수 있도록 미리 데이터를 챙겨주는 배려였구나!”
데이터 모델링이란, 결국 UI와의 ‘대화’를 염두에 둔 설계 행위였다. 솔라는 비로소 ‘게시글 하나는 객체, 목록은 배열’이라는 문장이 가진 깊은 실용적 지혜를 온몸으로 이해했다.
모든 의문이 풀린 듯 후련해진 솔라를 보며 루나가 슬쩍 다른 질문을 던졌다.
“그럼, 온라인 쇼핑몰의 ‘장바구니’ 화면에 보여줄 데이터는 어떻게 만들면 좋을까? 상품 이름, 가격, 수량이 필요하다고 해보자.”
솔라는 더 이상 망설이지 않았다. 그녀는 노트의 새 페이지에 익숙하면서도 새로운 그림을 자신 있게 그려 나갔다. ‘장바구니’라는 이름의 선반, 그리고 그 안에 담긴 ‘상품’이라는 이름의 상자들.
shoppingCart = [ { name: "우유", price: 2500, quantity: 1 }, { name: "달걀", price: 6000, quantity: 1 }, { name: "빵", price: 3000, quantity: 2 } ]
“장바구니는 목록이니까 배열로 만들고, 각 상품은 이름, 가격, 수량이라는 연관된 정보를 가지니까 객체로 묶어야지.”
솔라는 자신의 그림을 보며 설명했다. “이렇게 해야 전체 상품 목록을 보여주기도 편하고, 나중에 ‘총 주문 금액’을 계산할 때도 배열을 쭉 돌면서 각 객체의 price랑 quantity를 곱해서 더하면 되니까. 훨씬 편하잖아.”
더 이상 루나의 설명은 필요 없었다. 솔라는 이제 새로운 목록형 데이터를 마주하더라도, 왜 그것이 ‘객체 배열’ 형태가 되어야 하는지 스스로 설명하고 설계할 수 있는 단단한 관점을 갖게 되었다. 모니터 옆에 붙어 있던 메모지의 문장은, 이제 솔라에게 당연한 진리이자 강력한 도구가 되어 있었다.