๐Ÿ’ป ๊ฐœ๋ฐœ/iOS

[iOS / SwiftUI] ์Šคํฌ๋กค, ๋ฌดํ•œ์œผ๋กœ ์ฆ๊ฒจ์š”~ (LazyVStack์œผ๋กœ ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ํ•˜๊ธฐ)

2022. 11. 28. 00:34
๋ชฉ์ฐจ
  1. 1. Model
  2. 2. ViewModel
  3. 3. WebService
  4. 4. View

์˜ค๋Š˜์€ ScrollView์™€ LazyVStack์„ ํ™œ์šฉํ•˜์—ฌ SwiftUI์—์„œ ๋ฌดํ•œ ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

์‚ฌ์‹ค, LazyVStack์ด ์กฐ๊ธˆ ์ƒ์†Œํ•  ์ˆ˜ ์žˆ๋‹ค. 

LazyVStack์€ ๋ง ๊ทธ๋Œ€๋กœ Lazyํ•˜๊ฒŒ VStack์„ ๊ทธ๋ฆฐ๋‹ค๋Š” ๋А๋‚Œ์œผ๋กœ,

VStack์œผ๋กœ ๋ณด์—ฌ์ค„ ํ•ญ๋ชฉ์ด ์‹ค์ œ๋กœ UI์— ๋ณด์—ฌ์งˆ ๋•Œ ๋ Œ๋”๋ง์„ ์ง„ํ–‰ํ•˜๋Š” View์ด๋‹ค.

Apple Developer Docs

 

 

Apple Developer Documentation

 

developer.apple.com

 

๊ทธ๋ ‡๋‹ค๋ฉด ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ VStack๊ณผ๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ์„๊นŒ?

 

ํ‰์†Œ์— ์‚ฌ์šฉํ•˜๋˜ VStack์€ ๋ทฐ๊ฐ€ ๋ณด์—ฌ์งˆ ๋•Œ(onAppear) ๋ชจ๋“  ํ•ญ๋ชฉ์„ ๋ Œ๋”๋งํ•œ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ScrollView + VStack ์กฐํ•ฉ์œผ๋กœ List๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค๋ฉด ์ดˆ๊ธฐ์— ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์†Œ๋ชจํ•˜๊ฒŒ ๋œ๋‹ค.

 

์ ์€ ๊ฐœ์ˆ˜์˜ ๊ฐ„๋‹จํ•œ ํ•ญ๋ชฉ๋“ค์„ ํ‘œ์‹œํ•  ๊ฒฝ์šฐ์—๋Š” ์ƒ๊ด€์ด ์—†์ง€๋งŒ,

๋งŽ์€ ๊ฐœ์ˆ˜์˜ ํ•ญ๋ชฉ๋“ค์„ ํ‘œ์‹œํ•  ๊ฒฝ์šฐ์—๋Š” ์ ์ ˆํ•˜์ง€ ๋ชปํ•œ ๋ฐฉ๋ฒ•์ผ ๊ฒƒ์ด๋‹ค.

 

๊ฐ€๋ น, ์ค‘๊ณ ๊ฑฐ๋ž˜ ํ”Œ๋žซํผ ์•ฑ์ด ์žˆ๋Š”๋ฐ ์•ฑ์„ ์ผฐ์„ ๋•Œ ํŠน์ • ์นดํ…Œ๊ณ ๋ฆฌ์— ์žˆ๋Š” ๋ชจ๋“  ํ•ญ๋ชฉ์„ ๊ฐ€์ ธ์˜จ๋‹ค๊ณ  ํ•ด๋ณด์ž.

์—„์ฒญ๋‚œ ๋ฆฌ์†Œ์Šค๋ฅผ ์†Œ๋ชจํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. (์‚ฌ์šฉ์ž์˜ ์…€๋ฃฐ๋Ÿฌ ๋ฐ์ดํ„ฐ๋‚˜, CPU ํ˜น์€ RAM๊ณผ ๊ฐ™์€ ์ž์›์ด ๋  ์ˆ˜ ์žˆ๋‹ค.)

 

๊ทธ๋ž˜์„œ ์ดˆ๊ธฐ์—๋Š” 10๊ฐœ, ํ˜น์€ 20๊ฐœ์™€ ๊ฐ™์ด ์ ์€ ๊ฐœ์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋งŒ ๋ณด์—ฌ์ฃผ๊ณ 

๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์ด ๋ณด์—ฌ์ง€๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์ธ ๋ฌดํ•œ ์Šคํฌ๋กค ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

์‹ค์ œ๋กœ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ๊ทธ ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

onAppear์— print๋ฅผ ๋‹ฌ์•„์ฃผ๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.

ํ‰์†Œ์— ์‚ฌ์šฉํ•˜๋˜ VStack์€ View๊ฐ€ ๋ณด์—ฌ์งˆ ๋•Œ ๋ชจ๋“  ํ•ญ๋ชฉ์ด ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. (์‹ค์ œ๋กœ๋Š” ๋ณด์—ฌ์ง€์ง€ ์•Š๋”๋ผ๋„)

VStack

 

LazyVStack์€ View๊ฐ€ ๋ณด์—ฌ์งˆ ๋•Œ ๋ชจ๋“  ํ•ญ๋ชฉ์ด ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๊ณ , ์‹ค์ œ๋กœ ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ๋งŒ ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

LazyVStack

 

๋˜ํ•œ ์ž์ฃผ ์“ฐ๋Š” List ์—ญ์‹œ Lazyํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. (List๋ฅผ ์• ์šฉํ•˜๋„๋ก ํ•˜์ž)

List

๊ทธ๋Ÿผ ์ด์ œ ๋ณธ๋ก ์œผ๋กœ ๋“ค์–ด๊ฐ€์„œ, ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋ฌดํ•œ์Šคํฌ๋กค์„ ์–ด๋–ค ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

 

์šฐ์„  ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ์ด๋ ‡๊ฒŒ ์žก์•˜๊ณ , MVVM ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

 

1. Model

์šฐ์„  Model์˜ ๊ฒฝ์šฐ, API๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๋ฐ›์•„์˜ค๋Š” Json์˜ ๊ตฌ์กฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ตฌํ˜„ํ•ด์คฌ๋‹ค.

import Foundation

struct Lecture: Codable {
    let pagination: Pagination
    let results: [Result]
}

struct Pagination: Codable {
    let count: Int
    let numPages: Int
    let next: URL
    
    enum CodingKeys: String, CodingKey {
        case count
        case numPages = "num_pages"
        case next
    }
}

struct Result: Codable, Identifiable {
    let id: UUID = UUID() // List๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด identifiable ์ถ”๊ฐ€
    let name: String
    let media: Media
    let teachers: String
    let shortDesc: String
    let startDisplay: String
    
    enum CodingKeys: String, CodingKey {
        case name
        case teachers
        case media
        case shortDesc = "short_description"
        case startDisplay = "start_display"
    }
}

struct Media: Codable {
    let image: ImagePerSize
}

struct ImagePerSize: Codable {
    let raw: URL
    let small: URL
    let large: URL
}

 

์‚ฌ์šฉํ•œ API์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ์•„๋ž˜ ๋งํฌ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๊ตญ๊ฐ€ํ‰์ƒ๊ต์œก์ง„ํฅ์›_K-MOOC_๊ฐ•์ขŒ์ •๋ณดAPI

ํ•œ๊ตญํ˜• ์˜จ๋ผ์ธ ๊ณต๊ฐœ๊ฐ•์ขŒ(K-MOOC)์˜ ๊ฐ•์ขŒ ๋ชฉ๋ก API ๋ฐ ๊ฐ•์ขŒ ์„ธ๋ถ€ ์ •๋ณด API ์ œ๊ณต

www.data.go.kr

 

2. ViewModel

ViewModel์—์„œ๋Š” Lecture๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ @Published๋กœ ์ •์˜ํ–ˆ๋‹ค.

๋˜ํ•œ ์•ฑ์„ ์ฒ˜์Œ ์ผฐ์„ ๋•Œ ๊ฐ•์ขŒ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ์™€ ์Šคํฌ๋กค์„ ๋๊นŒ์ง€ ๋‚ด๋ ธ์„ ๋•Œ ์ถ”๊ฐ€์ ์œผ๋กœ ๊ฐ•์ขŒ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ–ˆ๋‹ค.

import Foundation

class LectureViewModel: ObservableObject {
    @Published var items: [Result] = []
    private var nextURL: String = ""
    private var APIKEY: String = ""
    
    init() {}
    
    // ์•ฑ์„ ์ฒ˜์Œ ์ผฐ์„ ๋•Œ ๊ฐ•์ขŒ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ
    func getLecturesOnServer() async throws {
        let responseData: Lecture = try await WebService.shared.loadJson("https://apis.data.go.kr/B552881/kmooc/courseList?serviceKey=\(APIKEY)&Page=1&Org=FUNMOOC&Mobile=1")
 
        DispatchQueue.main.async {
            self.items = responseData.results
            self.nextURL = "\(responseData.pagination.next)"
        }
    }
    
    // ์Šคํฌ๋กค์„ ๋๊นŒ์ง€ ๋‚ด๋ ธ์„ ๋•Œ ์ถ”๊ฐ€์ ์œผ๋กœ ๊ฐ•์ขŒ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ
    func getLecturesOnServerAtFinishedScroll() async throws {
        let responseData: Lecture = try await WebService.shared.loadJson(nextURL)
        
        // ๊ธฐ์กด ๊ฐ•์ขŒ ๋ชฉ๋ก์— ์ƒˆ๋กœ ๊ฐ€์ ธ์˜จ ๊ฐ•์ขŒ ๋ชฉ๋ก์„ ์ถ”๊ฐ€
        DispatchQueue.main.async {
            self.items += responseData.results
            self.nextURL = "\(responseData.pagination.next)"
        }
    }
}

ํ”„๋กœํผํ‹ฐ ์ค‘์— nextURL์˜ ๊ฒฝ์šฐ, json์—์„œ ๋‹ค์Œ ๊ฐ•์ขŒ ๋ชฉ๋ก์— ํ•ด๋‹นํ•˜๋Š” URL์„ ๋„˜๊ฒจ์ฃผ๋Š”๋ฐ ์ด๋ฅผ ํ™œ์šฉํ–ˆ๋‹ค. 

 

3. WebService

WebService์—์„œ๋Š” API๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•ด์คฌ๋‹ค.

import Foundation

class WebService {
    static let shared = WebService()
    
    // json์„ Tํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋กœ ๋””์ฝ”๋”ฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ
    func loadJson<T: Decodable>(_ url: String) async throws -> T {
        do {
            let url = URL(string: url)!
            let (data, _) = try await URLSession.shared.data(from: url)
            return try JSONDecoder().decode(T.self, from: data)
        } catch {
            fatalError("Unable to parse data : \(error)")
        }
    }
}

ํƒ€์ž…์— ์ƒ๊ด€์—†์ด ํ•ด๋‹น ํด๋ž˜์Šค์™€ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๋„ค๋ฆญ์„ ์ ์šฉํ–ˆ๋‹ค.

 

4. View

ViewModel์—์„œ @Published๋กœ ์ •์˜ํ•œ items๋ฅผ ํ™œ์šฉํ–ˆ๊ณ ,

์•ฑ์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋Š” items์— ์–ด๋– ํ•œ ๋ฐ์ดํ„ฐ๋„ ๋“ค์–ด์žˆ์ง€ ์•Š๊ธฐ์—, ์ด ๋•Œ๋Š” ProgressBar๊ฐ€ ๋ณด์—ฌ์ง€๋„๋ก ํ–ˆ๋‹ค.

 

๋˜ํ•œ ๋™์‹œ์— API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฐ•์ขŒ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•˜์˜€๊ณ 

๊ฐ•์ขŒ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์„ฑ๊ณตํ•˜๋ฉด items์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๊ฒŒ ๋˜๊ณ , ์ดํ›„์—๋Š” ProgressBar๊ฐ€ ์‚ฌ๋ผ์ง€๋„๋ก ํ–ˆ๋‹ค.

 

ViewModel, ์•„๋‹ˆ ObservableObject๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ด๋Ÿฌํ•œ ํ˜•ํƒœ์˜ ์•ฑ์„ ์ •๋ง ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. (SwiftUI ์งฑ์งฑ!! ๐Ÿ˜€)

import SwiftUI

struct LectureListView: View {
    @EnvironmentObject var lectureVM: LectureViewModel
    @State private var num: Int = 0
    
    var body: some View {
        if lectureVM.items.isEmpty {
            ProgressView()
            // ์•ฑ์„ ์ฒ˜์Œ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋งŒ ProgressView๋ฅผ ๋ณด์—ฌ์คŒ
                .task {
                    do {
                        try await lectureVM.getLecturesOnServer()
                    } catch (let error) {
                        print("Unable to get data : \(error)")
                    }
                }
        } else {
            ScrollView {
                LazyVStack {
                    ForEach(lectureVM.items) { item in
                        LectureItemView(lecture: item)
                            .onAppear {
                                guard let index = lectureVM.items.firstIndex(where: { $0.id == item.id }) else { return }
                                
                                if index % 10 == 9 {
                                    Task {
                                        do {
                                            try await lectureVM.getLecturesOnServerAtFinishedScroll()
                                        } catch (let error) {
                                            print("Unable to get data : \(error)")
                                        }
                                    }
                                    
                                }
                            }
                    }
                }
            }
            .navigationTitle("K-MOOC ๊ฐ•์ขŒ ๋ชฉ๋ก")
        }
        
    }
}

์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ LazyVStack์€ ํŠน์ • ์•„์ดํ…œ์ด UI์— ๊ทธ๋ ค์งˆ ํƒ€์ด๋ฐ์— ๋ Œ๋”๋ง์„ ์ง„ํ–‰ํ•œ๋‹ค.

 

์ด๋ฅผ ํ™œ์šฉํ•ด์„œ ๋ถˆ๋Ÿฌ์˜จ ๊ฐ•์ขŒ ๋ชฉ๋ก์—์„œ ๋งˆ์ง€๋ง‰ ๊ฐ•์ขŒ๊ฐ€ ๋ณด์—ฌ์ง€๋ฉด,

์ƒˆ๋กญ๊ฒŒ ๊ฐ•์ขŒ ๋ชฉ๋ก์„ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

 

๊ฐ•์ขŒ ๋ชฉ๋ก์„ ๋ณด์—ฌ์ฃผ๋Š” ScrollView์—์„œ ํ•˜๋‚˜์˜ ๊ฐ•์ขŒ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” View์ธ, LectureItemView๋Š” ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋‹ค.

import SwiftUI

struct LectureItemView: View {
    var lecture: Result
    
    var body: some View {
        HStack {
            AsyncImage(url: lecture.media.image.small) { image in
                image
                    .resizable()
                
            } placeholder: {
                ProgressView()
                .frame(width: 140)
            }
            .scaledToFill()
            .frame(width: 140)
            .clipped()
            .cornerRadius(8)
            
            VStack(alignment: .leading) {
                Text(lecture.name)
                    .font(.body)
                    .fontWeight(.bold)
                
                Spacer()
                
                Text(lecture.teachers)
                    .font(.footnote)
                    .lineLimit(1)
                
                Spacer()
                
                Text(lecture.startDisplay)
                    .font(.footnote)
            }
            .padding(4)
            
            Spacer()
        }
        .padding(8)
    }
}

 

์‹ค์ œ ๊ตฌํ˜„ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ž!

๋งˆ์ง€๋ง‰ ๊ฐ•์ขŒ๊ฐ€ ๋ณด์—ฌ์งˆ ๋•Œ API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ 10๊ฐœ์˜ ๊ฐ•์ขŒ๋ฅผ ๋” ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค!

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐Ÿ’ป ๊ฐœ๋ฐœ > iOS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[iOS / SwiftUI] MapKit, ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋„๋กœ๋ช… ์ฃผ์†Œ ๋ณ€ํ™˜ํ•˜๊ธฐ  (2) 2022.12.20
[iOS / SwiftUI] OnAppear, OnDisappear๋Š” ์–ธ์ œ ํ˜ธ์ถœ๋ ๊นŒ?  (2) 2022.12.01
[iOS / Swift] Swift ๋ฌธ์ž์—ด ์ •๋ณตํ•˜๊ธฐ (aka 'Character')  (0) 2022.11.03
[iOS / SwiftUI] ๋‹ค์–‘ํ•œ ์ƒํƒœ ํ”„๋กœํผํ‹ฐ๋“ค์„ ์•Œ์•„๋ณด์ž!  (0) 2022.10.24
[iOS / SwiftUI] ํ‚ค๋ณด๋“œ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์•„์š”...๐Ÿ˜ฉ  (0) 2022.10.21
  1. 1. Model
  2. 2. ViewModel
  3. 3. WebService
  4. 4. View
'๐Ÿ’ป ๊ฐœ๋ฐœ/iOS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [iOS / SwiftUI] MapKit, ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋„๋กœ๋ช… ์ฃผ์†Œ ๋ณ€ํ™˜ํ•˜๊ธฐ
  • [iOS / SwiftUI] OnAppear, OnDisappear๋Š” ์–ธ์ œ ํ˜ธ์ถœ๋ ๊นŒ?
  • [iOS / Swift] Swift ๋ฌธ์ž์—ด ์ •๋ณตํ•˜๊ธฐ (aka 'Character')
  • [iOS / SwiftUI] ๋‹ค์–‘ํ•œ ์ƒํƒœ ํ”„๋กœํผํ‹ฐ๋“ค์„ ์•Œ์•„๋ณด์ž!
kodo_o
kodo_o
iOS ๊ฟ€์žผ!
kodo_o
๐ŸŽ๐Ÿ
kodo_o
์ „์ฒด
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (149)
    • ๐Ÿ”จ ํ”„๋กœ์ ํŠธ (0)
      • TP 1 (0)
      • WhiteHCCTV (0)
      • FootPrint (0)
    • ๐Ÿ’ป ๊ฐœ๋ฐœ (63)
      • iOS (30)
      • Android (6)
      • Kotlin (4)
      • Flutter (9)
      • Node.js (5)
      • Architecture (1)
      • ์˜ค๋Š˜์˜ ์‚ฝ์งˆ (7)
      • ์—๋Ÿฌ์™€์˜ ๋™์นจ (1)
    • โœ๏ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (6)
      • Graph (6)
      • String (0)
      • Sort (0)
    • โœ๏ธ ์ฝ”ํ…Œ ์ค€๋น„ (44)
      • Math (1)
      • Implementation (3)
      • String (3)
      • Brute Force (5)
      • Back Tracking (7)
      • Greedy (0)
      • Dynamic Programming (13)
      • Binary Search (1)
      • DFS, BFS (5)
      • Shortest Path (2)
      • Two Pointer (4)
      • MST (0)
    • ๐Ÿ“š CS (6)
      • Operating System (6)
    • โ›น๏ธ ๋ผ์ดํ”„ (30)
      • 2020 ๊ฒจ์šธ๋ฐฉํ•™ ๋ชจ๊ฐ์ฝ”(๊ฐœ์ธ) (12)
      • 2021 ์—ฌ๋ฆ„๋ฐฉํ•™ ๋ชจ๊ฐ์ฝ”(๊ฐœ์ธ) (6)
      • ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ (1)
      • ํšŒ๊ณ  (10)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ๊นƒํ—ˆ๋ธŒ

์ธ๊ธฐ ๊ธ€

์ตœ๊ทผ ๊ธ€

์ตœ๊ทผ ๋Œ“๊ธ€

hELLO ยท Designed By ์ •์ƒ์šฐ.
kodo_o
[iOS / SwiftUI] ์Šคํฌ๋กค, ๋ฌดํ•œ์œผ๋กœ ์ฆ๊ฒจ์š”~ (LazyVStack์œผ๋กœ ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ํ•˜๊ธฐ)
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”

๋‹จ์ถ•ํ‚ค

๋‚ด ๋ธ”๋กœ๊ทธ

๋‚ด ๋ธ”๋กœ๊ทธ - ๊ด€๋ฆฌ์ž ํ™ˆ ์ „ํ™˜
Q
Q
์ƒˆ ๊ธ€ ์“ฐ๊ธฐ
W
W

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€

๊ธ€ ์ˆ˜์ • (๊ถŒํ•œ ์žˆ๋Š” ๊ฒฝ์šฐ)
E
E
๋Œ“๊ธ€ ์˜์—ญ์œผ๋กœ ์ด๋™
C
C

๋ชจ๋“  ์˜์—ญ

์ด ํŽ˜์ด์ง€์˜ URL ๋ณต์‚ฌ
S
S
๋งจ ์œ„๋กœ ์ด๋™
T
T
ํ‹ฐ์Šคํ† ๋ฆฌ ํ™ˆ ์ด๋™
H
H
๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด
Shift + /
โ‡ง + /

* ๋‹จ์ถ•ํ‚ค๋Š” ํ•œ๊ธ€/์˜๋ฌธ ๋Œ€์†Œ๋ฌธ์ž๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ‹ฐ์Šคํ† ๋ฆฌ ๊ธฐ๋ณธ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.