Menu
Coddy logo textTech

JSON 영속성 계층

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 102번째.

challenge icon

챌린지

쉬움

도서 관리 시스템에 데이터 지속성을 추가해 봅시다! 도서관 데이터를 저장하기 위해 JSON 형식으로 변환하고, JSON 문자열에서 다시 데이터를 로드할 수 있는 JSON 지속성 레이어를 구현하게 됩니다. 이는 세션 간에 데이터를 보존해야 하는 모든 실제 애플리케이션에 필수적입니다.

코드는 다음 다섯 개의 파일로 구성됩니다:

  • book.go: 직렬화를 제어하기 위한 JSON 구조체 태그가 포함된 Book 구조체입니다. 각 필드는 id, title, author, isbn, available에 해당하는 JSON 태그를 가져야 합니다. NewBook 생성자를 포함하세요.
  • user.go: id, name, email, borrowed_books에 대한 JSON 구조체 태그가 포함된 User 구조체입니다. NewUser 생성자를 포함하세요.
  • data.go: JSON 직렬화를 위한 전송 객체 역할을 하는 LibraryData 구조체를 생성합니다. 이 구조체는 Books (Book 포인터 슬라이스)와 Users (User 포인터 슬라이스)라는 두 개의 필드를 가져야 하며, 각각 적절한 JSON 태그(booksusers)를 가져야 합니다.
  • library.go: 도서와 사용자를 위한 맵을 가진 Library 구조체입니다. 다음 두 가지 새로운 메서드를 추가하세요:
    • ToJSON()json.MarshalIndent를 사용하여 2칸 들여쓰기가 적용된 형식의 JSON 문자열로 도서관 데이터를 변환합니다. 맵에 있는 모든 도서와 사용자를 LibraryData 구조체로 수집한 다음 직렬화해야 합니다.
    • FromJSON(jsonStr string) — JSON 문자열을 받아 LibraryData 구조체로 언마샬링하고, 로드된 도서와 사용자로 도서관의 맵을 채웁니다.
  • main.go: 도서관을 구축하고 JSON으로 변환하여 지속성 레이어를 시연합니다.

    도서 수를 읽은 다음, 각 도서의 ID, 제목, 저자, ISBN을 읽습니다. 그다음 사용자 수를 읽고, 각 사용자의 ID, 이름, 이메일을 읽습니다. 도서관 데이터를 모두 채운 후, ToJSON()을 호출하고 결과 JSON 문자열을 출력합니다.

다음 입력이 제공됩니다:

  • 도서 수, 이어서 각 도서의 ID, 제목, 저자, ISBN (각각 별도의 줄에 입력)
  • 사용자 수, 이어서 각 사용자의 ID, 이름, 이메일 (각각 별도의 줄에 입력)

예를 들어, 다음과 같이 입력하면:

2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com

출력은 다음과 같아야 합니다:

{
  "books": [
    {
      "id": "B001",
      "title": "The Go Programming Language",
      "author": "Alan Donovan",
      "isbn": "978-0134190440",
      "available": true
    },
    {
      "id": "B002",
      "title": "Clean Code",
      "author": "Robert Martin",
      "isbn": "978-0132350884",
      "available": true
    }
  ],
  "users": [
    {
      "id": "U001",
      "name": "Alice Smith",
      "email": "alice@library.com",
      "borrowed_books": []
    }
  ]
}

그리고 다음과 같이 입력하면:

1
B100
Design Patterns
Gang of Four
978-0201633610
0

출력은 다음과 같아야 합니다:

{
  "books": [
    {
      "id": "B100",
      "title": "Design Patterns",
      "author": "Gang of Four",
      "isbn": "978-0201633610",
      "available": true
    }
  ],
  "users": []
}

중요: 슬라이스를 만들기 위해 맵을 순회할 때, 도서는 B001, B002 등의 순서(ID 기준 알파벳순 정렬)로 추가하고 사용자도 마찬가지로 추가하세요. 이렇게 하면 일관된 JSON 출력이 보장됩니다. 순회하기 전에 맵 키에 sort.Strings를 사용할 수 있습니다.

LibraryData 구조체는 맵 기반 저장소와 JSON의 배열 기반 형식 사이의 간극을 메워줍니다. 이러한 전송 객체(Transfer Object) 패턴은 복잡한 데이터 구조를 직렬화할 때 흔히 사용됩니다!

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 새로운 도서관 생성
	library := NewLibrary()

	// 도서 수 읽기
	numBooksStr, _ := reader.ReadString('\n')
	numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))

	// TODO: 각 도서의 상세 정보(ID, title, author, ISBN) 읽기
	// 그리고 도서관에 추가
	for i := 0; i < numBooks; i++ {
		// TODO: 도서 ID 읽기
		// TODO: 도서 제목 읽기
		// TODO: 도서 저자 읽기
		// TODO: 도서 ISBN 읽기
		// TODO: 도서 생성 및 도서관에 추가
	}

	// 사용자 수 읽기
	numUsersStr, _ := reader.ReadString('\n')
	numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))

	// TODO: 각 사용자의 상세 정보(ID, name, email) 읽기
	// 그리고 도서관에 추가
	for i := 0; i < numUsers; i++ {
		// TODO: 사용자 ID 읽기
		// TODO: 사용자 이름 읽기
		// TODO: 사용자 이메일 읽기
		// TODO: 사용자 생성 및 도서관에 추가
	}

	// TODO: 도서관 정보를 JSON으로 변환하고 출력하기
	fmt.Println(library.ToJSON())
}

객체 지향 프로그래밍의 모든 레슨