Flutter (앱 개발)/Flutter 트랙

[Flutter 트랙 TIL ]데이터 통신 기초와 JSON-Dart에서 배우는 JSON 활용법

Ize𓆜 2025. 4. 15. 20:54
728x90
728x90

 


Ⅰ. 서론

 

처음에는 JSON이 어렵게 느껴졌다

 

개발을 시작하면서

"JSON"이라는 단어는 자주 들었지만,

정확히 어떤 역할을 하는지

명확하게 와닿지 않았습니다.

 

단순히 {}와 []로 둘러싸인

데이터를 텍스트처럼 보다가,

실습을 통해 직접

데이터를 주고받고 변환해보면서

그 중요성과 구조를 제대로 이해하게 되었죠.

 

Flutter 수업 중에 JSON을 배우게 되었고,

특히 서버와 통신할 때

데이터를 주고받는 형식이라는 점에서

꼭 배워야겠다는 생각이 들었어요.

 

하지만 처음에는

'Map', 'dynamic', 'toJson', 'fromJson' 같은

단어들조차 익숙하지 않았습니다.


시행착오가 주는 학습의 힘

 

 

 

처음에는 JSON 문자열을 복사해와서

jsonDecode만 쓰면 끝인 줄 알았는데,

조금만 복잡한 구조가 나오면 에러가 나기 일쑤였어요.

 

예를 들어 List<String>으로 변환해야 하는데

List<dynamic>이 그대로 들어온다든지,

null 값을 처리하지 않아서

앱이 튕긴다든지 하는 일이 반복됐죠.

 

이 과정을 반복하면서

JSON 구조를 정확히 이해하는 것,

그리고 Dart에서 어떻게

직렬화/역직렬화를 할 수 있는지를

체득하게 되었습니다.

 

이제

제가 공부한 JSON-Dart에 대해서 정리해보았습니다.

 

 


Ⅱ. 본론

 

JSON의 기본 구조와 특징

 

JSON(JavaScript Object Notation)은

JavaScript 객체의 표기법을 기반으로

만들어진 데이터 포맷입니다.

 

주로 API 통신에서

데이터를 주고받는 형식으로 쓰이며,

Dart에서는

이를 Map<String, dynamic> 형태로

다룰 수 있습니다.


Dart에서 JSON 다루기: jsonEncode & jsonDecode

 

Dart에서는 dart:convert 라이브러리를 통해

jsonEncode()와 jsonDecode()로

문자열 ↔ 객체 간 변환이 가능해요.



  • jsonEncode() : Dart의 Map이나 List를 JSON 문자열로 변환
  • jsonDecode() : JSON 문자열을 Dart의 Map 또는 List로 변환
String jsonStr = jsonEncode({"name": "오상구", "age": 7});
var jsonMap = jsonDecode(jsonStr);

TIP: JSON의 루트는 {} 뿐만 아니라 []도 될 수 있어요!


클래스를 활용한 JSON 변환

 

import 'dart:convert';

void main() {
  String jsonString = """
{
	"name": "오상구",
	"age": 7,
	"isMale" : true
}
""";
  // 2. Map<String, dynamic>으로 변환해서 map이라는 이름의 변수에 담기
  Map<String, dynamic> map = jsonDecode(jsonString);
  // 3. jsonString 을 Map 으로 변환 후 Pet class로 변환 후 출력해서 변수에 담기!
  Pet pet = Pet.fromJson(map);
  // 4. print 문으로 Pet 클래스의 toJson 메서드를 호출해서 출력
  print(pet.toJson());
}

/*
 * 1. 아래에서 클래스 정의 Pet
 * (함수 내에서는 클래스를 정의할 수 없습니다!)
 */

class Pet {
  String name;
  int age;
  bool isMale;

  Pet({
    required this.name,
    required this.age,
    required this.isMale,
  });

  Pet.fromJson(Map<String, dynamic> json)
      : this(
          name: json["name"],
          age: json["age"],
          isMale: json["isMale"],
        );

  Map<String, dynamic> toJson() {
    return {
      "name": name,
      "age": age,
      "isMale": isMale,
    };
  }
}

import 'dart:convert';

void main() {
  String jsonString = """
{
	"name": "오상구",
	"age": 7,
	"isMale" : true,
	"favorite_foods" : ["삼겹살", "연어", "고구마"],
	"contact": {
		"mobile": "010-0000-0000",
		"email": null
	}
}
""";
  // 2. Map<String, dynamic>으로 변환해서 map이라는 이름의 변수에 담기
  Map<String, dynamic> map = jsonDecode(jsonString);

  // 3. jsonString 을 Map 으로 변환 후 Pet class로 변환 후 출력해서 변수에 담기!
  Pet pet = Pet.fromJson(map);

  // 4. print 문으로 Pet 클래스의 toJson 메서드를 호출해서 출력
  print(pet.toJson());
}

/*
 * 1. 아래에서 클래스 정의 Contact, Pet
 * (함수 내에서는 클래스를 정의할 수 없습니다!)
 */

class Pet {
  final String name;
  final int age;
  final bool isMale;
  final List<String> favoriteFoods;
  final Contact contact;

  Pet({
    required this.name,
    required this.age,
    required this.isMale,
    required this.favoriteFoods,
    required this.contact,
  });

  Pet.fromJson(Map<String, dynamic> json)
      : this(
          name: json["name"],
          age: json["age"],
          isMale: json["isMale"],
          // jsonDecode는 List타입을 반환할 때 List<dynamic> 타입으로 반환하기 때문에
          // List<String> 타입으로 리스트 변환
          favoriteFoods: List<String>.from(json["favorite_foods"]),
          contact: Contact.fromJson(json["contact"]),
        );

  Map<String, dynamic> toJson() {
    return {
      "name": name,
      "age": age,
      "isMale": isMale,
      "favorite_foods": favoriteFoods,
      "contact": contact.toJson(),
    };
  }
}

class Contact {
  String mobile;
  String? email;

  Contact({
    required this.mobile,
    required this.email,
  });

  Contact.fromJson(Map<String, dynamic> json)
      : this(
          mobile: json["mobile"],
          email: json["email"],
        );

  Map<String, dynamic> toJson() {
    return {
      "mobile": mobile,
      "email": email,
    };
  }
}

 

복잡한 JSON 데이터를 다룰수록 

Map만으로는 

오타나 타입 오류가 발생하기 쉽습니다.

 

 그래서 클래스 내에 

fromJson, toJson 메서드를

 구현하는 것이 좋습니다.

class User {
  String name;
  int age;

  User.fromJson(Map<String, dynamic> json)
      : name = json["name"],
        age = json["age"];

  Map<String, dynamic> toJson() => {"name": name, "age": age};
}

 

이 구조를 이해하고 나니,

코드가 훨씬 깔끔하고

실수도 줄어들었어요.

 


중첩된 JSON 구조 다루기

 

 

다음과 같은 중첩된 

JSON 구조도 클래스 안에

 클래스를 넣어 처리할 수 있어요.

{
  "name": "오상구",
  "age": 7,
  "contact": {
    "mobile": "010-0000-0000",
    "email": null
  }
}

 

이걸 Dart로 표현하면

다음과 같이 작성할 수 있습니다.

 

class Contact {
  String mobile;
  String? email;

  Contact.fromJson(Map<String, dynamic> json)
      : mobile = json["mobile"],
        email = json["email"];
}

 

실제로 만들어보니,

구조만 잘 이해하면

생각보다 간단하더라고요!

 

이제 아래는 Git Hub 링크입니다. 

Linayoo01/-250415-Dart-JSON-Practice

 

GitHub - Linayoo01/-250415-Dart-JSON-Practice

Contribute to Linayoo01/-250415-Dart-JSON-Practice development by creating an account on GitHub.

github.com

 


Ⅲ. 결론

 

단순한 문법 공부를 넘어선 데이터 사고

 

JSON 공부를 통해

 단순히 Dart 문법만 배운 게 아니라, 

데이터를 구조화하는 사고방식도 

자연스럽게 익히게 되었어요. 

 

어떤 정보를 어떻게 표현할지,

 서버와 어떤 형식으로 

주고받아야 할지를 고민하게 되었죠.



클래스를 만들면서

 "이 필드는 null일 수 있을까?",

 "이 리스트의 타입은 무엇일까?"

 같은 질문을 스스로 하게 된 것도

 좋은 변화였습니다.


내가 만든 JSON 변환기가 돌아갈 때의 쾌감

 

처음에는 단순한 출력 코드였지만, 

점점 복잡한 구조의 JSON도

 Dart 객체로 

깔끔하게 변환해내는 걸 보며

 뿌듯함을 느꼈어요.

 

 Pet, Contact 등 

직접 클래스를 만들어

 객체화해보는 과정을 통해

 JSON이 더 이상 낯설지 않게 느껴졌습니다.



앞으로 REST API를 다룰 때도 

이 경험이 큰 밑거름이 될 것 같아요. 

아직 갈 길은 멀지만,

 이 과정을 통해

 "실패하면서 배우는 공부"가

 가장 확실하다는 걸 다시 한 번 느꼈습니다. 🌱

 

 

728x90
728x90