플러터 앱 개발

Chapter 13. Flutter 데이터 통신 기초와 JSON

yuna 2026. 1. 21. 21:33

1. JSON 이란?

Dart 코드로 되어있는 객체를 다른 언어로 작성한 언어 및 플랫폼(ex. 자바로 작성된 서버)에서 작동하게 하려면?

-> 통일된 규격으로 변환하는 작업이 필요: 직렬화

-> 해당 작업을 JSON이라고 함!

  • JavaScript Object Notation
  • 자바 스크립트의 객체 표기 방식을 기반한다.
  • JS Object: 중괄호 안에 Key - Value 쌍
  • Key는 반드시 문자열
  • Value에 들어갈 수 있는 타입
    • String
    • Number(int, double)
    • Boolean(bool)
    • Array(대괄호)
    • Object(중괄호)
    • null

2. Dart에서의 사용법

    • 데이터를 주고 받을 때 JSON 형식의 String으로 주고 받음
    • 직렬화: Dart 객체 -> Map -> String
    • 역직렬화: String -> Map -> Dart 객체
      • Map을 거치는 이유: 객체 바로 String으로 변환 하려면 개발가가 직접 구현해야함 복잡
      • 다트SDK dart:convert 라이브러리에 jsonEncode , jsonDecode 함수가 있는데 Map, List String으로 변환해주거나 Map, List String 등으로 변환해줌
      • JSON 루트, 최상위는 리스트가 있음. 대괄호 [ ] 있음 
JSON은 데이터 포장 규칙,
인코딩은 포장하는 과정, 디코딩은 포장을 뜯는 과정이다.

 

1) 직렬화

: 객체(앱에서 쓰는 데이터) -> 문자열(JSON)로 바꾸는 것

 

why?

  • 인처넷으로는 객체를 그대로 못 보냄
  • 그래서 글자(String)로 바꿔서 보냄
User user = User(name: '유나', age: 25);

-> 직렬화 하면
{"name":"유나","age":25}

 

2) 역직렬화

: 문자열(JSON) -> 객체(앱에서 쓰는 데이터)로 바꾸는 것

 

why?

  • 서버에서 받은 건 글자 덩어리
  • 앱에서는 객체여야 쓰기 편함
{"name":"유나","age":25}

-> 역직렬화하면
User user = User.fromJson(json);

 

[한 장 정리][앱 객체]
   ↓ 직렬화
[JSON 문자열]
   ↓ 네트워크
[JSON 문자열]
   ↓ 역직렬화
[앱 객체]

 

정리하자면..

직렬화: 객체를 JSON 형태의 문자열로 변환할 때

  • 객체 -> Map -> String
  • jsonEncode
  • 객체에 toJson 메서드 구현

역직렬화: JSON 형태의 문자열을 객체로 변환할 때

  • String -> Map -> 객체로 바꿔준다
  • String -> Map: jsonDecode 함수
  • Map -> 객체: 객체에 fromJson named 생성자를 구현해서 사용!

사용해보기!

-전체 코드

import 'dart:convert'; //라이브러리 호출

void main() {
  String jsonString = """
{
   "name": "이지원",
   "age": 20
	}
""";

  var jsonMap = jsonDecode(jsonString);
  User user = User.fromJson(jsonMap);
  print(user.toJson()); // {name: 이지원, age: 20}
}

class User {
  User({
    required this.name,
    required this.age,
  });
  String name;
  int age;

  User.fromJson(Map<String, dynamic> map)
      : this(
          name: map['name'],
          age: map['age'],
        );

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

 

 

 

1) JSON 형태의 '문자열', 네트워크로 주고 받는 데이터는 보통 이런 "문자열"형태로  

void main() {
  String jsonString = """
{
	"name": "이지원",
	"age": 20
	}
""";

 

 

2) jsonDecode는 JSON 문자열을 다트에서 쓸 수 있는 구조(Map/List)로 바꿈

  • 현재 JSON은 { }이므로 결과는 Map이 됨
  • jsonDecode 반환 타입은 상황에 따라 Map 수도, List 수도 있어서 보통 dynamic/var 받는 경우가 많음
  • jsonMap은 그냥 Map이라서 jsonMap['name'] 이런 식으로 매번 꺼내야 하지만, 보통 user.name, user.age처럼 명확한 객체로 다루는 게 훨씬 편하고 안전함
 var jsonMap = jsonDecode(jsonString);
  User user = User.fromJson(jsonMap);
  print(user.toJson()); // {name: 이지원, age: 20}
}

 

3) User 클래스는 앱 안에서 “유저 데이터”를 다루는 설계도

 

이게 없을 시

  • 데이터가 전부 Map<String, dynamic>으로 떠다니고
  • 키 오타('naem') 나면 런타임에서 터지고
  • 어디서 어떤 데이터가 들어오는지 추적이 어려워짐

User가 있으면:

  • user.name처럼 자동완성 됨
  • 타입이 고정돼서 실수 줄어듦
  • 코드가 읽기 쉬워짐
class User {
  User({
    required this.name,
    required this.age,
  });
  String name;
  int age;

 

4) 이 Map으로 User를 만들어줘”라는 특수 생성자

 

  • map['name'] → name 필드에 넣고
  • map['age'] → age 필드에 넣어서
  • 결국 User(name: ..., age: ...) 일반 생성자를 호출해 객체를 완성함

this를 쓰는 이유?

 

  • “초기화는 한 곳에서만” 하게 만들어서 코드 중복을 줄인다.
  • 즉, User를 만드는 규칙을 한 군데로 통일하는 거야.

 

 

 User.fromJson(Map<String, dynamic> map)
      : this(
          name: map['name'],
          age: map['age'],
        );

 

5) toJson은 반대로 User 객체 → Map(JSON 형태)로 변환(직렬화)

 

  • 서버로 보낼 때는 객체(User)를 그대로 못 보냄
  • 보낼 수 있는 건 보통 JSON 형태(Map → jsonEncode → String)

 

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