인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

강민석님의 프로필 이미지
강민석

작성한 질문수

Flutter로 SNS 앱 만들기

사용자 정보, 게시글 정보를 Model 클래스로 관리 강의 관련 질문

해결된 질문

작성

·

312

·

수정됨

0

안녕하세요.

강의 잘 듣고 있습니다.

사용자 정보, 게시글 정보를 Model 클래스로 관리 강의 관련 질문 있습니다.

그 전 강의인 firestore에 게시글 정보 저장 강의 까지는 firestore database에 정상적으로 data가 올라갔습니다.

하지만, 사용자 정보, 게시글정보를 Model 클래스로 관리 강의에 따라 코드 작성 후

firestore database에 data가 올라가지 않습니다.

(storage는 잘 작동합니다.)

//feed_model.dart
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:collection/collection.dart';
import 'package:sns_clonecode/models/urser_model.dart';

class FeedModel {
  final String uid;
  final String feedId;
  final String desc;
  final List<String> imageUrls;
  final List<String> likes;
  final int commentCount;
  final int likeCount;
  final Timestamp creatAt;
  final UserModel writer;

  const FeedModel({
    required this.uid,
    required this.feedId,
    required this.desc,
    required this.imageUrls,
    required this.likes,
    required this.commentCount,
    required this.likeCount,
    required this.creatAt,
    required this.writer,
  });

  Map<String, dynamic> toMap({
    required DocumentReference<Map<String, dynamic>> userDocRef,
  }) {
    return {
      'uid': this.uid,
      'feedId': this.feedId,
      'desc': this.desc,
      'imageUrls': this.imageUrls,
      'likes': this.likes,
      'commentCount': this.commentCount,
      'likeCount': this.likeCount,
      'creatAt': this.creatAt,
      'writer': userDocRef,
    };
  }

  factory FeedModel.fromMap(Map<String, dynamic> map) {
    return FeedModel(
      uid: map['uid'],
      feedId: map['feedId'],
      desc: map['desc'],
      imageUrls: List<String>.from((map['imageUrls'])),
      likes: List<String>.from((map['likes'])),
      commentCount: map['commentCount'],
      likeCount: map['likeCount'],
      creatAt: map['creatAt'],
      writer: map['writer'],
    );
  }
}
//user_model.dart
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

class UserModel {
  final String uid;
  final String name;
  final String email;
  final String? profileImage;
  final int feedCount;
  final List<String> followers;
  final List<String> following;
  final List<String> likes;

  const UserModel({
    required this.uid,
    required this.name,
    required this.email,
    required this.profileImage,
    required this.feedCount,
    required this.followers,
    required this.following,
    required this.likes,
  });

  factory UserModel.init() {
    return UserModel(
      uid: '',
      name: '',
      email: '',
      profileImage: null,
      feedCount: 0,
      followers: [],
      following: [],
      likes: [],
    );
  }

//usermodle 이 가지고 있는 filed 변수로 가지고 있는 데이터들을 가지고 map 형태 데이터를 만들어 준다.
  Map<String, dynamic> toMap() {
    return {
      'uid': this.uid,
      'name': this.name,
      'email': this.email,
      'profileImage': this.profileImage,
      'feedCount': this.feedCount,
      'followers': this.followers,
      'following': this.following,
      'likes': this.likes,
    };
  }

//map 형태 데이터를 인자값을 전달 받아 usermolde 객체를 만들어 준다.
  factory UserModel.fromMap(Map<String, dynamic> map) {
    return UserModel(
      uid: map['uid'],
      name: map['name'],
      email: map['email'],
      profileImage: map['profileImage'],
      feedCount: map['feedCount'],
      followers: List<String>.from(map['followers']),
      following: List<String>.from(map['following']),
      likes: List<String>.from(map['likes']),
    );
  }
}

//feed_repository.dart

import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:sns_clonecode/models/feed_model.dart';
import 'package:sns_clonecode/models/urser_model.dart';
import 'package:sns_clonecode/utils/logger.dart';
import 'package:uuid/uuid.dart';

class FeedRepository {
  final FirebaseStorage firebaseStorage;
  final FirebaseFirestore firebaseFirestore;

  const FeedRepository({
    required this.firebaseFirestore,
    required this.firebaseStorage,
  });

  Future<void> uploadFeed({
    required List<String> files,
    required String desc,
    required String uid,

//feeds 컬렉션에 저장
//피드 각각이 문서
//이미지는 storage에 직접 저장하고 firestore에 접근할 수 있는 url 문자열로 받을 것이다.
//좋아요 수
//이 게시글에 달린 댓글의 수
//게시글을 작성한 날짜
//feeds에서 user의 정보를 바로 가져올 수 있게 reference 타입의 데이터를 저장한다.
  }) async {
//파이어스토어에 데이터 저장하기위해서
//문서 아이디는 겹치지 않는 고유한 값으로 만들어야 한다.

//a-z 알파벳
//0~9 숫자
//이 두가지를 조합해서 32글자의 고유한 값을 만들어 준다.
//32글자에 - 4개씩 들어가서 36글자가 된다.
//고유한 값을 만드는 방법 여러가지 version1 ....
//우리는 version1을 사용 (현재 시간을 기준으로 random값을 만들어 준다.)

    String feedId = Uuid().v1();

    //firestore 문서 참조
    DocumentReference<Map<String, dynamic>> feedDocRef =
        firebaseFirestore.collection('feeds').doc(feedId);

    DocumentReference<Map<String, dynamic>> userDocRef =
        firebaseFirestore.collection('users').doc(uid);

    //storage 참조
    Reference ref = firebaseStorage.ref().child('feeds').child(feedId);

    List<String> imageUrls = await Future.wait(files.map((e) async {
      //문자열 e는 이미지 파일에 접근할 수 있는 경로
      String imageId = Uuid().v1();
      TaskSnapshot taskSnapshot = await ref.child(imageId).putFile(File(e));
      return await taskSnapshot.ref.getDownloadURL();
    }).toList());

    DocumentSnapshot<Map<String, dynamic>> userSnapshot =
        await userDocRef.get();

    UserModel userModel = UserModel.fromMap(userSnapshot.data()!);

    FeedModel feedModel = FeedModel.fromMap({
      'uid': uid,
      'feedId': feedId,
      'desc': desc,
      'imageUrls': imageUrls,
      'likes': [],
      'likeCount': 0,
      'commentCount': 0,
      'createAt': Timestamp.now(),
      'writer': userModel,
    });

    await feedDocRef.set(feedModel.toMap(userDocRef: userDocRef));

    // await feedDocRef.set({
    //   'uid': uid,
    //   'feedId': feedId,
    //   'desc': desc,
    //   'imageUrls': imageUrls,
    //   'likes': [],
    //   'commentCount': 0,
    //   'likeCount': 0,
    //   'creatAt': Timestamp.now(),
    //   'writer': userDocRef,
    // });

    await userDocRef.update({
      'feedCount': FieldValue.increment(1),
    });
  }
}

바쁘실 텐데 질문 읽어주셔서 감사합니다.

답변 2

0

DEV MOO님의 프로필 이미지
DEV MOO
지식공유자

추가로 auth_repository.dart 의 signIn 함수 44행에 왜 로그아웃 하는지 모르겠다고 하셔서 설명 드립니다.

 

signInWithEmailAndPassword 함수를 호출하면 firebase 에 이메일이 등록되는 것과 동시에 자동으로 로그인이 됩니다.

 

이 앱은 이메일을 등록하고 메일 주소로 전송된 인증 링크를 클릭해야 회원가입이 완료되는 것이기에 이메일만 등록하고 인증 링크를 클릭하지 않은 사용자를 로그인 시켜서는 안되겠죠.

그래서 로그아웃 시키는 겁니다.

강민석님의 프로필 이미지
강민석
질문자

주석까지 답해주시니 감사합니다.

글 보고 잘 이해했습니다.

0

DEV MOO님의 프로필 이미지
DEV MOO
지식공유자

오타 였습니다.

feed_model.dart 56행의

creatAt: map['creatAt'] 을 createAt: map['createAt'] 으로 수정 해주세요.

 

그리고 동일한 오타가 다른 곳에서도 발견되었는데 수정 하시는게 좋을 것 같습니다.

위치는 feed_model.dart 의 16, 27, 42 행 입니다.

강민석님의 프로필 이미지
강민석
질문자

오!!!! 감사합니다.

잘 작동합니다.

(혹시 오타일까 오늘 하루 종일 강의와 github 돌려보며 확인 했지만 발견하지 못 했었는데, 정말 감사합니다~!~!~!)

강민석님의 프로필 이미지
강민석

작성한 질문수

질문하기