Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Mark-In/Sources/Data/DTOs/LinkDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// LinkDTO.swift
// Mark-In
//
// Created by 이정동 on 4/20/25.
//

import Foundation

struct LinkDTO: Codable {
var id: String
var url: String
var title: String?
var thumbnailUrl: String?
var faviconUrl: String?
var createdBy: Date
var lastAccessedAt: Date?
var folderId: String?

init(_ link: Link) {
self.id = link.id
self.url = link.url
self.title = link.title
self.thumbnailUrl = link.thumbnailUrl
self.faviconUrl = link.faviconUrl
self.createdBy = link.createdBy
self.lastAccessedAt = link.lastAccessedAt
self.folderId = link.folderId
}
Comment on lines +20 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 로직은 레파지토리로 이전되는게 좋을 것 같아요


func toEntity() -> Link {
Link(
id: self.id,
url: self.url,
title: self.title,
thumbnailUrl: self.thumbnailUrl,
faviconUrl: self.faviconUrl,
createdBy: self.createdBy,
lastAccessedAt: self.lastAccessedAt,
folderId: self.folderId
)
}
}
Comment on lines +9 to +43
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entity -> DTO 타입 변환, DTO -> Entity 타입 변환을 DTO 타입을 통해서만 이루어질 수 있도록 init 메서드와 toEntity() 메서드를 정의했습니다.

86 changes: 86 additions & 0 deletions Mark-In/Sources/Data/Repositories/LinkRepositoryImpl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// LinkRepositoryImpl.swift
// Mark-In
//
// Created by 이정동 on 4/21/25.
//

import Foundation

import FirebaseFirestore

struct LinkRepositoryImpl: LinkRepository {

typealias VoidCheckedContinuation = CheckedContinuation<Void, any Error>

private let db = Firestore.firestore()

func createLink(_ link: Link) async throws -> Link {
/// 1. Link 문서 참조 생성
// TODO: 후에 testUser를 실제 로그인 된 유저로 변경 예정
let linkDocRef = db.collection("users/testUser/links").document()

/// 2. Entity를 DTO로 변환 및 새로 생성된 문서 ID를 프로퍼티에 저장
var linkDTO = LinkDTO(link)
linkDTO.id = linkDocRef.documentID
Comment on lines +24 to +25

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makeDTO 메서드 내부에서 처리하도록 변경하면 좋을 것 같아요~


/// 3. Firestore에 추가
try await withCheckedThrowingContinuation { (continuation: VoidCheckedContinuation) in
do {
try linkDocRef.setData(from: linkDTO) { error in
if let error { continuation.resume(throwing: error) }
else { continuation.resume(returning: ()) }
}
} catch {
continuation.resume(throwing: error)
}
}

Comment on lines +27 to +38
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async로 작성된 setData(from:) 메서드가 존재하지 않았기 때문에 콜백함수를 비동기 함수로 전환시켰습니다

/// 4. DocumentID 업데이트 된 LinkEntity로 리턴
return linkDTO.toEntity()
}

func fetchAllLinks() async throws -> [Link] {
/// 1. Links 컬렉션 참조 생성
// TODO: 후에 testUser를 실제 로그인 된 유저로 변경 예정
let linkColRef = db.collection("users/testUser/links")

/// 2. 컬렉션의 모든 문서 가져오기
let snapshot = try await linkColRef.getDocuments()

/// 3. 문서를 DTO로 변환 후 다시 Entity로 변환
return snapshot.documents.compactMap {
try? $0.data(as: LinkDTO.self).toEntity()
}
}

func updateLink(_ link: Link) async throws {
/// 1. Link 문서 참조 생성
// TODO: 후에 testUser를 실제 로그인 된 유저로 변경 예정
let linkDocRef = db.document("users/testUser/links/\(link.id)")

/// 2. Entity를 DTO로 변환
let linkDTO = LinkDTO(link)

/// 3. 업데이트
try await withCheckedThrowingContinuation { (continuation: VoidCheckedContinuation) in
do {
try linkDocRef.setData(from: linkDTO) { error in
if let error { continuation.resume(throwing: error) }
else { continuation.resume(returning: ()) }
}
} catch {
continuation.resume(throwing: error)
}
}
}

func deleteLink(_ link: Link) async throws {
/// 1. Link 문서 참조 생성
// TODO: 후에 testUser를 실제 로그인 된 유저로 변경 예정
let linkDocRef = db.document("users/testUser/links/\(link.id)")

/// 2. Link 삭제
try await linkDocRef.delete()
}
}
19 changes: 19 additions & 0 deletions Mark-In/Sources/Domain/Entities/Link.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Link.swift
// Mark-In
//
// Created by 이정동 on 4/20/25.
//

import Foundation

struct Link {
Copy link

@f-lab-barry f-lab-barry Apr 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct WriteLink {
  var url: String
  var title: String?
  var thumbnailUrl: String?
  var faviconUrl: String?
  var lastAccessedAt: Date?
  var folderId: String?
}

create(from writeLink: WriteLink) -> Link {
  let doc = "users/testUser/links".document()
  makeDTO(writeLink)
}

같은 도메인 어떤 context(문맥)안에 있느냐에 따라 완전히 다름

var id: String = ""
var url: String
var title: String?
var thumbnailUrl: String?
var faviconUrl: String?
var createdBy: Date = .now
var lastAccessedAt: Date?
var folderId: String?
}
Comment on lines +9 to +19
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id 프로퍼티를 옵셔널타입 대신 기본값을 설정해 주었습니다.
link를 firebase에 추가한 시점에 id값이 생성되고, 그 이후부터는 필수적으로 id가 존재하기 때문에 옵셔널이 아닌 기본값을 넣어주었습니다.
createdBy 프로퍼티는 생성 시점을 나타내기 위해 기본 값을 현재 날짜로 넣어주었습니다.

15 changes: 15 additions & 0 deletions Mark-In/Sources/Domain/Interfaces/LinkRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// LinkRepository.swift
// Mark-In
//
// Created by 이정동 on 4/20/25.
//

import Foundation

protocol LinkRepository {
func createLink(_ link: Link) async throws -> Link
func fetchAllLinks() async throws -> [Link]
func updateLink(_ link: Link) async throws
func deleteLink(_ link: Link) async throws
}
Loading