{"id":4622,"date":"2026-02-20T18:32:33","date_gmt":"2026-02-20T09:32:33","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=4622"},"modified":"2026-02-23T12:00:16","modified_gmt":"2026-02-23T03:00:16","slug":"project-swift-reactexample7","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/02\/20\/project-swift-reactexample7\/","title":{"rendered":"[Swift]GET,POST,PATCH,PUT(MacOS)"},"content":{"rendered":"\n<p>\u2b50\ufe0f ReactExample7 &#8211; server + swift<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc544\ub798\ub294 GET,POST,PATCH,PUT\uc744 Swift\uc5d0\uc11c \uad6c\ud604\ud55c \uc608\uc81c\uc785\ub2c8\ub2e4.<br>Below is an example of implementing GET, POST, PATCH, and PUT in Swift.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ub9ac\uc561\ud2b8\ub85c \uad6c\ud604\ud55c \uc608\uc81c\ub294 \uc544\ub798\uc5d0 \ub9c1\ud06c\ub41c \ud3ec\uc2a4\ud2b8\ub97c \ucc38\uc870\ud558\uc138\uc694<br>For an example implemented with React, please refer to the post linked below.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-freelifemakers-org wp-block-embed-freelifemakers-org\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"oIzRvgv1WB\"><a href=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/02\/18\/vitereact-example7\/\">[Vite+React]GET,POST,PATCH,PUT(MacOS)<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&#8220;[Vite+React]GET,POST,PATCH,PUT(MacOS)&#8221; &#8212; freelifemakers.org\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/02\/18\/vitereact-example7\/embed\/#?secret=GOJaPfl2fq#?secret=oIzRvgv1WB\" data-secret=\"oIzRvgv1WB\" width=\"560\" height=\"315\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb Nodejs Express Server(Backend)<\/p>\n\n\n\n<p>\u2714\ufe0fServer.js<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require(\"express\");\nconst app = express();\nconst PORT = 3000;\n\napp.use(express.json());\n\n\/\/ \uac00\uc0c1\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \/ Virtual Database\nlet users = &#91;{ id: \"1\", name: \"V\", age: 20, nickname: \"Cyberpunk2077\" }];\n\n\/\/ GET: \ud2b9\uc815 \uc720\uc800 \uc870\ud68c \/ Specific user inquiry\napp.get(\"\/users\/:id\", (req, res) =&gt; {\n  const user = users.find((u) =&gt; u.id === req.params.id);\n  user\n    ? res.json(user)\n    : res.status(404).json({ message: \"\uc720\uc800 \uc5c6\uc74c\/No user\" });\n});\n\n\/\/ POST: \uc0c8\ub85c\uc6b4 \uc720\uc800 \uc0dd\uc131 \/ Create new user\napp.post(\"\/users\", (req, res) =&gt; {\n  const newUser = { id: String(users.length + 1), ...req.body };\n  users.push(newUser);\n  res.status(201).json(newUser);\n});\n\n\/\/ PATCH: \ub370\uc774\ud130\uc758 '\uc77c\ubd80'\ub9cc \uc218\uc815 (\uae30\uc874 \ub370\uc774\ud130 \uc720\uc9c0)\n\/\/ Modify only 'part' of the data (keep existing data)\napp.patch(\"\/users\/:id\", (req, res) =&gt; {\n  const index = users.findIndex((u) =&gt; u.id === req.params.id);\n  if (index !== -1) {\n    \/\/ \uae30\uc874 \uac12 + \ubc14\ub010 \uac12 \ud569\uce58\uae30 \/ Merge existing value + changed value\n    users&#91;index] = { ...users&#91;index], ...req.body };\n    res.json(users&#91;index]);\n  } else {\n    res.status(404).json({ message: \"\uc720\uc800 \uc5c6\uc74c\/No user\" });\n  }\n});\n\n\/\/ PUT: \ub370\uc774\ud130 '\uc804\uccb4'\ub97c \uad50\uccb4 (\ubcf4\ub0b4\uc9c0 \uc54a\uc740 \ud544\ub4dc\ub294 \uc0ac\ub77c\uc9d0)\n\/\/ Replace 'all' data (unsent fields disappear)\napp.put(\"\/users\/:id\", (req, res) =&gt; {\n  const index = users.findIndex((u) =&gt; u.id === req.params.id);\n  if (index !== -1) {\n    \/\/ \uae30\uc874 \ub0b4\uc6a9 \ubb34\uc2dc\ud558\uace0 \ub36e\uc5b4\uc4f0\uae30 \/ Ignore existing content and overwrite\n    users&#91;index] = { id: req.params.id, ...req.body };\n    res.json(users&#91;index]);\n  } else {\n    res.status(404).json({ message: \"\uc720\uc800 \uc5c6\uc74c\/No user\" });\n  }\n});\n\n\/\/ DELETE: \ub370\uc774\ud130 \uc0ad\uc81c \/ data deletion\napp.delete(\"\/users\/:id\", (req, res) =&gt; {\n  users = users.filter((u) =&gt; u.id !== req.params.id);\n  res.json({ message: `User ${req.params.id} \uc0ad\uc81c \uc644\ub8cc \/ Deletion complete` });\n});\n\napp.listen(PORT, () =&gt; console.log(`Server: http:\/\/localhost:${PORT}`));\n<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb Swift(Frontend)<\/p>\n\n\n\n<p>\u2714\ufe0f ContentView<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nimport SwiftUI\n\n\/\/ \ub370\uc774\ud130 \ubaa8\ub378 \uc815\uc758 \/ Data model definition\nstruct User: Codable, Identifiable {\n    let id: Int?\n    var name: String?\n    var age: Int?\n    var nickname: String?\n}\n\nstruct MessageResponse: Codable {\n    let message: String\n}\n\nstruct ContentView: View {\n    @State private var userId: String = \"1\"\n        @State private var userData: User? = nil\n        @State private var log: String = \"\"\n        \n        \/\/ \uc11c\ubc84 \uae30\ubcf8 URL \/ Server Base URL\n        let baseURL = \"http:\/\/localhost:3000\/users\"\n\n        var body: some View {\n            ScrollView {\n                VStack(alignment: .leading, spacing: 20) {\n                    Text(\"HTTP Methods Playground\")\n                        .font(.title).bold()\n\n                    TextField(\"User ID\", text: $userId)\n                        .textFieldStyle(RoundedBorderTextFieldStyle())\n                        .keyboardType(.numberPad)\n\n                    \/\/ \ubc84\ud2bc \uadf8\ub8f9 \/ Button Group\n                    VStack(spacing: 10) {\n                        HStack {\n                            methodButton(\"GET (\uc870\ud68c\/Search)\", color: Color(.systemGray5)) { getUser() }\n                            methodButton(\"POST (\uc0dd\uc131\/Creation)\", color: Color(red: 0.8, green: 1, blue: 0.8)) { createUser() }\n                        }\n                        HStack {\n                            methodButton(\"PATCH (\uc77c\ubd80\uc218\uc815\/modifications)\", color: Color(red: 1, green: 0.95, blue: 0.8)) { patchUser() }\n                            methodButton(\"PUT (\uc804\uccb4\uad50\uccb4\/replacement)\", color: Color(red: 1, green: 0.8, blue: 0.8)) { putUser() }\n                        }\n                        methodButton(\"DELETE (\uc0ad\uc81c\/Deletion)\", color: Color(.systemGray6)) { deleteUser() }\n                    }\n\n                    HStack(alignment: .top, spacing: 20) {\n                        \n                        \/\/ \ud604\uc7ac \ub370\uc774\ud130 \uc0c1\uc138 \/ Current Data State\n                        VStack(alignment: .leading) {\n                            Text(\"\ud604\uc7ac \ub370\uc774\ud130 \uc0c1\uc138 \/ Current data details\").font(.headline)\n                            if let user = userData {\n                                VStack(alignment: .leading) {\n                                    Text(\"ID: \\(user.id ?? 0)\")\n                                    Text(\"\uc774\ub984\/Name: \\(user.name ?? \"\uc5c6\uc74c\/none\")\")\n                                    Text(\"\ub098\uc774\/Age: \\(user.age != nil ? \"\\(user.age!)\" : \"\uc5c6\uc74c\/none\")\")\n                                    Text(\"\ub2c9\ub124\uc784\/Nickname: \\(user.nickname ?? \"\uc5c6\uc74c\/none\")\")\n                                }\n                                .padding()\n                                .border(Color.blue)\n                            } else {\n                                Text(\"\uc870\ud68c\ub41c \ub370\uc774\ud130\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.\/No data was retrieved.\")\n                            }\n                        }\n                        .frame(maxWidth: .infinity, alignment: .leading)\n\n                        \/\/ \uc11c\ubc84 \uc6d0\ubcf8 \uc751\ub2f5 \/ Server original response(Raw JSON)\n                        VStack(alignment: .leading) {\n                            Text(\"\uc11c\ubc84 \uc751\ub2f5 \/ server response\").font(.headline)\n                            Text(log)\n                                .font(.system(.caption, design: .monospaced))\n                                .padding()\n                                .frame(maxWidth: .infinity, alignment: .leading)\n                                .background(Color(.systemGray6))\n                        }\n                        .frame(maxWidth: .infinity, alignment: .leading)\n                    }\n                }\n                .padding()\n            }\n}\n\n    \/\/ MARK: - HTTP Methods\n    func getUser() {\n       performRequest(url: \"\\(baseURL)\/\\(userId)\", method: \"GET\")\n    }\n\n    func createUser() {\n       let body: &#91;String: Any] = &#91;\"name\": \"NewUser\", \"age\": 30, \"nickname\": \"SilverHand\"]\n       performRequest(url: baseURL, method: \"POST\", body: body)\n    }\n\n    func patchUser() {\n       let body: &#91;String: Any] = &#91;\"nickname\": \"Johnny\"]\n       performRequest(url: \"\\(baseURL)\/\\(userId)\", method: \"PATCH\", body: body)\n    }\n\n    func putUser() {\n       \/\/ PUT\uc740 \ubcf4\ud1b5 \ub9ac\uc18c\uc2a4 \uc804\uccb4\ub97c \uac08\uc544\ub07c\uc6b0\ubbc0\ub85c nickname\uc744 \uc0dd\ub7b5\ud558\uba74 null\uc774 \ub420 \uac00\ub2a5\uc131\uc744 \uc2dc\ubbac\ub808\uc774\uc158\ud569\ub2c8\ub2e4.\n       \/\/ Since PUT usually replaces the entire resource, omitting nickname simulates the possibility that it will be null.\n       let body: &#91;String: Any] = &#91;\"name\": \"John\", \"age\": 25]\n       performRequest(url: \"\\(baseURL)\/\\(userId)\", method: \"PUT\", body: body)\n    }\n\n    func deleteUser() {\n        Task {\n            \/\/ Task\ub97c \ud1b5\ud574 \uba54\uc778 \uc561\ud130\uc640 \ube44\ub3d9\uae30 \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc5f0\uacb0\n            \/\/ Connect the main actor and the asynchronous context through Task\n\n            guard let url = URL(string: \"\\(baseURL)\/\\(userId)\") else { return }\n            var request = URLRequest(url: url)\n            request.httpMethod = \"DELETE\"\n            \n            do {\n                let (data, _) = try await URLSession.shared.data(for: request)\n                let decoded = try JSONDecoder().decode(MessageResponse.self, from: data)\n                \n                \/\/ UI \uc5c5\ub370\uc774\ud2b8\ub294 \uba54\uc778 \uc2a4\ub808\ub4dc\uc5d0\uc11c\n                \/\/ UI updates are done on the main thread\n                await MainActor.run {\n                    self.userData = nil\n                    self.log = decoded.message\n                }\n            } catch {\n                print(\"Error: \\(error)\")\n            }\n        }\n    }\n\n    \/\/ MARK: - Helper Methods\n    \n    \/\/ \uc11c\ubc84\uc5d0 \uc694\uccad \/ Request to server\n    func performRequest(url urlString: String, method: String, body: &#91;String: Any]? = nil) {\n        guard let url = URL(string: urlString) else { return }\n        var request = URLRequest(url: url)\n        request.httpMethod = method\n            \n        if let body = body {\n          request.addValue(\"application\/json\", forHTTPHeaderField: \"Content-Type\")\n          request.httpBody = try? JSONSerialization.data(withJSONObject: body)\n        }\n\n        URLSession.shared.dataTask(with: request) { data, response, error in\n            guard let data = data else { return }\n                    \n            \/\/ UI \uc5c5\ub370\uc774\ud2b8\ub294 \uba54\uc778 \uc2a4\ub808\ub4dc\uc5d0\uc11c\n            \/\/ UI updates are done on the main thread\n            DispatchQueue.main.async {\n              self.log = String(data: data, encoding: .utf8) ?? \"\"\n              if let decodedUser = try? JSONDecoder().decode(User.self, from: data) {\n                 self.userData = decodedUser\n              } else {\n                 self.userData = nil\n              }\n            }\n        }.resume()\n    }\n\n    func methodButton(_ title: String, color: Color, action: @escaping () -> Void) -> some View {\n      Button(action: action) {\n        Text(title)\n            .font(.caption)\n            .padding(10)\n            .frame(maxWidth: .infinity)\n            .background(color)\n            .foregroundColor(.black)\n            .cornerRadius(5)\n      }\n    }\n}\n\n#Preview {\n    ContentView()\n}\n<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc2a4\ud06c\ub9b0\uc0f7\/ScreenShot<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"509\" height=\"1024\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/02\/swift-Example7-509x1024.png\" alt=\"\" class=\"wp-image-4731\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/02\/swift-Example7-509x1024.png 509w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/02\/swift-Example7-149x300.png 149w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/02\/swift-Example7-400x805.png 400w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/02\/swift-Example7.png 662w\" sizes=\"auto, (max-width: 509px) 100vw, 509px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\u2b50\ufe0f ReactExample7 &#8211; server + swift \ud83d\udc49\ud83c\udffb \uc544\ub798\ub294 GET,POST,PATCH,PUT\uc744 Swift\uc5d0\uc11c \uad6c\ud604\ud55c \uc608\uc81c\uc785\ub2c8\ub2e4.Below is an example of implementing GET, POST, PATCH, and PUT in Swift. \ud83d\udc49\ud83c\udffb \ub9ac\uc561\ud2b8\ub85c \uad6c\ud604\ud55c \uc608\uc81c\ub294 \uc544\ub798\uc5d0 \ub9c1\ud06c\ub41c \ud3ec\uc2a4\ud2b8\ub97c \ucc38\uc870\ud558\uc138\uc694For an example implemented with React, please refer to the post linked below. \ud83d\udc49\ud83c\udffb Nodejs Express Server(Backend) \u2714\ufe0fServer.js \ud83d\udc49\ud83c\udffb Swift(Frontend) \u2714\ufe0f ContentView \ud83d\udc49\ud83c\udffb \uc2a4\ud06c\ub9b0\uc0f7\/ScreenShot<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,1],"tags":[],"class_list":["post-4622","post","type-post","status-publish","format-standard","hentry","category-swift","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/4622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=4622"}],"version-history":[{"count":17,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/4622\/revisions"}],"predecessor-version":[{"id":4733,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/4622\/revisions\/4733"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=4622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=4622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=4622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}