From 724c94eedddc539045abf7c6d74ef3f2a67e647e Mon Sep 17 00:00:00 2001 From: iwannacat Date: Tue, 27 May 2025 21:29:37 +0900 Subject: [PATCH 1/2] =?UTF-8?q?keyword:=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EC=B4=88=EC=95=88=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...14\353\223\234\354\240\225\353\246\254.md" | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 "keyword/Chapter09/\355\202\244\354\233\214\353\223\234\354\240\225\353\246\254.md" diff --git "a/keyword/Chapter09/\355\202\244\354\233\214\353\223\234\354\240\225\353\246\254.md" "b/keyword/Chapter09/\355\202\244\354\233\214\353\223\234\354\240\225\353\246\254.md" new file mode 100644 index 0000000..60a90e5 --- /dev/null +++ "b/keyword/Chapter09/\355\202\244\354\233\214\353\223\234\354\240\225\353\246\254.md" @@ -0,0 +1,119 @@ +- 서버 + - 서버란 무엇이고, 어떤 역할을 할까요? + + 서버(Server)는 클라이언트로부터 요청(Request)을 받아 이를 처리한 후 응답(Response)을 반환하는 컴퓨터 또는 프로그램입니다. 주로 데이터 저장, 처리, 공유 등의 역할을 합니다. + + - 현실에서 서버와 유사한 역할을 하는 예시는 무엇이 있을까요? + - 도서관 사서 + + 우리가 책(데이터)를 요청하면 사서(서버)는 책을 찾아서 전달해준다. + + - 쿠팡 + + 우라 물건(데이터)를 주문하면 쿠팡은 물건을 전해준다. + +- 서버와 클라이언트 + - 서버와 클라이언트는 일반적으로 1:1, 1:N, N:M 관계 중 어떤 관계를 가지고 있을까요? + - 위의 문장의 답을 찾고, 아래 문장을 완성해보세요. + - 서버는 다수의 클라이언트가 접근한다. + - 즉 서버와 클라이언트는 일반적으로 1:N의 관계다. + - 서버와 클라이언트의 통신 구조를 식당 예시와 연결하여 정리하고 스터디에서 본인이 정리한 예시를 공유해 보세요. + (식당에는 손님, 점원, 주방장, 냉장고가 있습니다.) + - 손님: 클라이언트 (요청자) + - 점원: API 서버 (중간에서 요청을 전달하고 응답을 다시 전달함) + - 주방장: 데이터베이스 서버 또는 내부 로직 처리자 + - 냉장고: 저장된 데이터 (데이터베이스) + + 식당에서 손님이 점원에게 음식을 요청하면, 점원은 주방장에게 전달하고 요리가 완성되면 손님에게 전달합니다. 이와 유사하게 클라이언트는 서버에 요청을 보내고, 서버는 요청을 처리한 후 응답을 보냅니다. + +- 서버와 클라이언트 간의 통신 + - 서버와 클라이언트가 정보를 주고 받으려면 먼저 어떤 일을 해야할까요? + - 정보를 주고받기 위해서는 먼저 **서버와 클라이언트가 연결을 설정**해야 하며, 주로 URL과 포트를 기반으로 접속합니다. + - API 서버와 소통하기 위해 필요한 정보들을 담고있는 문서는 무엇일까요? + (Hint: ‘API’라는 단어와 ‘문서’라는 단어를 함께 검색해보세요!) + + API 문서(API Documentation) + +- 서버와 클라이언트 간의 통신 방식 - HTTP Protocol + - HTTP Protocol에서 정보를 주고받기 위한 중요한 구성요소 2가지는 무엇일까요? + - Request + + 클라이언트가 서버에 보내는 메시지로, 요청 방식(method), URL, 헤더(header), 본문(body) 등으로 구성됨 + + - Response + + 서버가 클라이언트의 요청에 대해 응답하는 메시지로, 상태 코드(status code), 헤더(header), 본문(body) 등을 포함 + + + - HTTP 통신은 연결을 계속 유지하고 있을까요? 유지한다면 어떻게 유지할 수 있는지, 유지할 수 없다면 왜 유지할 수 없는지 찾아보세요. (Hint: State) + + **HTTP 통신은 기본적으로 연결을 유지하지 않는다. (Stateless)** + + 서버는 클라이언트의 이전 요청 상태를 저장하지 않으며, 각 요청은 독립적으로 처리됩니다. 따라서 기본적으로 연결을 유지하지 않으며 상태 정보를 저장하려면 별도의 기술이 필요합니다. 연결 유지가 필요한 경우는 다음과 같이 해결할 수 있습니다. + + - 쿠키(cookie)와 세션(session): 클라이언트 상태를 서버 또는 클라이언트에 저장 + - 토큰 기반 인증(JWT 등): 매 요청마다 토큰을 헤더에 포함하여 상태 유지 대체 + - HTTP persistent connection (Keep-Alive): 일정 시간 동안 동일 연결을 재사용 + - HTTP Protocol에서는 Method를 통해 어떤 동작을 하고싶은지 나타낼 수 있습니다. + 주요 Method 5가지는 무엇이 있을까요? + - GET: 리소스를 조회하기 위한 요청. 서버의 상태나 데이터를 변경하지 않음 + - POST: 서버에 데이터를 생성(등록) 요청 + - PUT: 리소스를 전체 수정 + - DELETE: 리소스를 삭제 + - PATCH: 리소스를 부분 수정 + - 데이터를 주고받을 때 주로 사용하는 방식에 대해 알아보세요. + - Query Parameter (또는 Query String): URL에 `?key=value` 형식으로 붙는 데이터. + + ex) `/users?name=John` + + - Path Variable: URL 경로의 일부로서 식별자 등을 포함. 예: /users/123 + - Body: 요청의 본문에 포함되는 데이터로, POST, PUT, PATCH 요청 시 주로 사용 + - Header: 요청 또는 응답의 부가 정보. 인증 정보(Authorization), 콘텐츠 타입(Content-Type) 등이 포함됨 + - HTTP에서 데이터를 주고받을 때는 서로 이해할 수 있는 특정 형식으로 진행해야 합니다. + 아래의 형식들에 대해 조사해보세요. + - JSON(JavaScript Object Notation) + + 텍스트 기반의 경량 데이터 교환 형식으로 키-값 쌍으로 구성되어 사람이 읽기 쉬움 + + - XML(eXtensible Markup Language) + + 태그 기반의 데이터 표현 방식으로, 데이터 구조가 명확하지만 무겁고 복잡할 수 있음 + + - HTTPS란 무엇이고, HTTP와 어떤 차이가 있을까요? + + **HTTP에 보안 계층(SSL/TLS)을 추가한 프로토콜** + + . HTTP는 데이터를 암호화하지 않지만, HTTPS는 데이터를 암호화하여 네트워크 상에서 제3자에 의해 읽히거나 변조되지 않도록 보호합니다. 이 때문에 금융, 로그인 등 민감한 정보를 다루는 웹사이트는 HTTPS를 사용해야 합니다. + + + +- API + - API란 무엇일까요? (Restful API가 무엇인지도 함께 정리해 주세요.) + - API(Application Programming Interface) + + 소프트웨어 간 상호작용을 위한 인터페이스로 ****외부 프로그램이 특정 기능을 사용할 수 있도록 함수, 명세 등을 제공한다. + + - Restful API + + HTTP 기반의 API 설계 원칙 중 하나로 자원의 URI를 통해 요청을 주고받으며, 상태(State)를 서버에 저장하지 않는다. + + +- Android에서 HTTP 통신하기 + - Android에서 HTTP 통신을 위해서는 외부 라이브러리를 사용해야 편리하게 진행할 수 있습니다. + 그 중 대표적인 라이브러리 Retrofit2에 대해서 찾아보세요. + + Retrofit2는 Android에서 HTTP 통신을 쉽게 할 수 있도록 도와주는 라이브러리다. 인터페이스 기반으로 API 요청을 정의하며, Gson 등의 변환기를 통해 데이터를 객체로 쉽게 처리할 수 있다. + + - Retrofit2를 실제로 Android App 내에서 사용하기 위해서 만들어야 하는 요소 3가지는 무엇이 있을까요? + - API 인터페이스 파일 (Service) + - 서버와 통신할 메서드를 정의하는 인터페이스 + - 예: @GET("/users"), @POST("/login") 등 + - Retrofit 객체 생성 + - baseUrl, converter(GsonConverterFactory 등), OkHttpClient 등을 설정하여 인스턴스를 생성 + - 데이터 모델 클래스 + - 서버에서 주고받는 JSON 데이터를 Kotlin/Java 객체로 변환하기 위한 클래스 \ No newline at end of file From 1dd3567b464d4a06b055dfa4ff57cbfe1abad7f2 Mon Sep 17 00:00:00 2001 From: iwannacat Date: Wed, 25 Jun 2025 03:21:13 +0900 Subject: [PATCH 2/2] =?UTF-8?q?mission:=20=EB=84=A4=ED=8A=B8=ED=89=88?= =?UTF-8?q?=ED=81=AC=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/flo/NetWork/AuthResponse.kt | 13 ++ .../flo/NetWork/AuthRetrofitInterface.kt | 15 ++ .../com/example/flo/NetWork/AuthService.kt | 71 ++++++ .../com/example/flo/NetWork/NetworkModule.kt | 19 ++ .../java/com/example/flo/NetWork/Result.kt | 8 + .../main/java/com/example/flo/data/User.kt | 18 ++ .../com/example/flo/ui/login/LoginActivity.kt | 94 ++++++++ .../com/example/flo/ui/login/LoginView.kt | 8 + .../flo/ui/notifications/SearchFragment.kt | 29 +++ .../example/flo/ui/siginup/SignUpActivity.kt | 70 ++++++ .../com/example/flo/ui/siginup/SignUpView.kt | 8 + .../Flo/app/src/main/res/drawable/ic_back.png | Bin 0 -> 2754 bytes .../main/res/drawable/selector_navi_home.xml | 5 + .../main/res/drawable/selector_navi_match.xml | 5 + .../res/drawable/selector_navi_mypage.xml | 5 + .../res/drawable/selector_navi_search.xml | 5 + .../main/res/drawable/udemy_softsquard.png | Bin 0 -> 16142 bytes .../src/main/res/layout/activity_login.xml | 175 +++++++++++++++ .../src/main/res/layout/activity_signup.xml | 206 ++++++++++++++++++ .../src/main/res/layout/fragment_search.xml | 21 ++ 20 files changed, 775 insertions(+) create mode 100644 mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthResponse.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthRetrofitInterface.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthService.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/NetWork/NetworkModule.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/NetWork/Result.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/data/User.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginActivity.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginView.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/ui/notifications/SearchFragment.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpActivity.kt create mode 100644 mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpView.kt create mode 100644 mission/Flo/app/src/main/res/drawable/ic_back.png create mode 100644 mission/Flo/app/src/main/res/drawable/selector_navi_home.xml create mode 100644 mission/Flo/app/src/main/res/drawable/selector_navi_match.xml create mode 100644 mission/Flo/app/src/main/res/drawable/selector_navi_mypage.xml create mode 100644 mission/Flo/app/src/main/res/drawable/selector_navi_search.xml create mode 100644 mission/Flo/app/src/main/res/drawable/udemy_softsquard.png create mode 100644 mission/Flo/app/src/main/res/layout/activity_login.xml create mode 100644 mission/Flo/app/src/main/res/layout/activity_signup.xml create mode 100644 mission/Flo/app/src/main/res/layout/fragment_search.xml diff --git a/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthResponse.kt b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthResponse.kt new file mode 100644 index 0000000..39d565c --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthResponse.kt @@ -0,0 +1,13 @@ +package com.example.flo.NetWork + +import com.google.gson.annotations.SerializedName + +data class AuthResponse( + @SerializedName("isSuccess") val isSuccess: Boolean, + @SerializedName("code") val code: Int, + @SerializedName("message") val message: String, + @SerializedName("result") val result: Result? + +) + + diff --git a/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthRetrofitInterface.kt b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthRetrofitInterface.kt new file mode 100644 index 0000000..8f7be35 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthRetrofitInterface.kt @@ -0,0 +1,15 @@ +package com.example.flo.NetWork + +import com.example.flo.data.User +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.POST + +interface AuthRetrofitInterface { + @POST("/users") + fun signUp(@Body user: User): Call + + @POST("/users/login") + fun login(@Body user: User): Call + +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthService.kt b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthService.kt new file mode 100644 index 0000000..b6f1642 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/NetWork/AuthService.kt @@ -0,0 +1,71 @@ +package com.example.flo.NetWork + +import android.util.Log +import com.example.flo.data.User +import com.example.flo.ui.login.LoginView +import com.example.udemy_android_template.ui.siginup.SignUpView +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class AuthService { + private lateinit var signUpView: SignUpView + private lateinit var loginView: LoginView + + fun setSignUpView(signUpView: SignUpView) { + this.signUpView = signUpView + } + + fun setLoginView(loginView: LoginView) { + this.loginView = loginView + } + + fun signUp(user: User) { + + val signUpService = getRetrofit().create(AuthRetrofitInterface::class.java) + + signUpService.signUp(user).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful && response.code() == 200) { + val signUpResponse: AuthResponse = response.body()!! + + Log.d("SIGNUP-RESPONSE", signUpResponse.toString()) + + when (val code = signUpResponse.code) { + 1000 -> signUpView.onSignUpSuccess() + 2016, 2017 -> { + signUpView.onSignUpFailure() + } + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + //실패처리 + } + }) + } + + + fun login(user: User) { + val loginService = getRetrofit().create(AuthRetrofitInterface::class.java) + + + loginService.login(user).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful && response.code() == 200) { + val loginResponse: AuthResponse = response.body()!! + + when (val code = loginResponse.code) { + 1000 -> loginView.onLoginSuccess(code,loginResponse.result!! ) + else -> loginView.onLoginFailure() + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + //실패처리 + } + }) + } +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/NetWork/NetworkModule.kt b/mission/Flo/app/src/main/java/com/example/flo/NetWork/NetworkModule.kt new file mode 100644 index 0000000..d636361 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/NetWork/NetworkModule.kt @@ -0,0 +1,19 @@ +package com.example.flo.NetWork + + +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit + +const val BASE_URL = "http://3.35.121.185" + +fun getRetrofit(): Retrofit { + + val retrofit = Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + return retrofit +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/NetWork/Result.kt b/mission/Flo/app/src/main/java/com/example/flo/NetWork/Result.kt new file mode 100644 index 0000000..7056c92 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/NetWork/Result.kt @@ -0,0 +1,8 @@ +package com.example.flo.NetWork + +import com.google.gson.annotations.SerializedName + +data class Result( + @SerializedName("userIdx") val userIdx: Int, + @SerializedName("jwt") val jwt: String +) diff --git a/mission/Flo/app/src/main/java/com/example/flo/data/User.kt b/mission/Flo/app/src/main/java/com/example/flo/data/User.kt new file mode 100644 index 0000000..534309e --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/data/User.kt @@ -0,0 +1,18 @@ +package com.example.flo.data + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.gson.annotations.SerializedName + +@Entity(tableName = "UserTable") +data class User( + @SerializedName(value = "email") + var email : String, + @SerializedName(value = "password") + var password : String, + @SerializedName(value = "name") + var name : String +){ +@PrimaryKey(autoGenerate = true) +val id : Int = 0 +} diff --git a/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginActivity.kt b/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginActivity.kt new file mode 100644 index 0000000..22aa6eb --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginActivity.kt @@ -0,0 +1,94 @@ +package com.example.udemy_android_template.ui.login + +import android.content.Intent +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.flo.MainActivity +import com.example.flo.NetWork.AuthService +import com.example.flo.NetWork.Result +import com.example.flo.ui.login.LoginView +import com.example.flo.data.User +import com.example.flo.databinding.ActivityLoginBinding +import com.example.udemy_android_template.ui.siginup.SignUpActivity + + +class LoginActivity : AppCompatActivity(), LoginView { + lateinit var binding: ActivityLoginBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.loginSignUpTv.setOnClickListener { + startActivity(Intent(this, SignUpActivity::class.java)) + } + + binding.loginSignInBtn.setOnClickListener { + login() + } + } + + + + private fun login() { + if (binding.loginIdEt.text.toString().isEmpty() || binding.loginDirectInputEt.text.toString().isEmpty()) { + Toast.makeText(this, "이메일을 입력해주세요.", Toast.LENGTH_SHORT).show() + return + } + + if (binding.loginPasswordEt.text.toString().isEmpty()) { + Toast.makeText(this, "비밀번호를 입력해주세요.", Toast.LENGTH_SHORT).show() + return + } + + val authService = AuthService() + authService.setLoginView(this) + + authService.login(getUser()) + } + + private fun getUser(): User { + val email = binding.loginIdEt.text.toString() + "@" + binding.loginDirectInputEt.text.toString() + val password = binding.loginPasswordEt.text.toString() + + return User(email = email, password = password, name = "") + } + + private fun startMainActivity() { + val intent = Intent(this, MainActivity::class.java) + startActivity(intent) + } + + private fun saveJwt(jwt: Int) { + val spf = getSharedPreferences("auth" , MODE_PRIVATE) + val editor = spf.edit() + + editor.putInt("jwt", jwt) + editor.apply() + } + + private fun saveJwt2(jwt: String) { + val spf = getSharedPreferences("auth2" , MODE_PRIVATE) + val editor = spf.edit() + + editor.putString("jwt", jwt) + editor.apply() + } + + + + override fun onLoginSuccess(code : Int, result : Result) { + when(code) { + 1000 -> { + saveJwt2(result.jwt) + startMainActivity() + + } + } + } + + override fun onLoginFailure() { + } +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginView.kt b/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginView.kt new file mode 100644 index 0000000..4cf7a93 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/ui/login/LoginView.kt @@ -0,0 +1,8 @@ +package com.example.flo.ui.login + + +import com.example.flo.NetWork.Result +interface LoginView { + fun onLoginSuccess(code : Int, result : Result) + fun onLoginFailure() +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/ui/notifications/SearchFragment.kt b/mission/Flo/app/src/main/java/com/example/flo/ui/notifications/SearchFragment.kt new file mode 100644 index 0000000..e5f03e7 --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/ui/notifications/SearchFragment.kt @@ -0,0 +1,29 @@ +package com.example.flo.ui.notifications + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.example.flo.databinding.FragmentSearchBinding + +class SearchFragment : Fragment() { + + private var _binding: FragmentSearchBinding? = null + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentSearchBinding.inflate(inflater, container, false) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpActivity.kt b/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpActivity.kt new file mode 100644 index 0000000..8c66f3f --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpActivity.kt @@ -0,0 +1,70 @@ +package com.example.udemy_android_template.ui.siginup + +import android.os.Bundle +import android.util.Log + +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.flo.NetWork.AuthService +import com.example.flo.data.User +import com.example.flo.databinding.ActivitySignupBinding + + +class SignUpActivity : AppCompatActivity() , SignUpView{ + + lateinit var binding: ActivitySignupBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivitySignupBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.signUpSignUpBtn.setOnClickListener { + signUp() + } + } + + private fun getUser(): User { + val email: String = + binding.signUpIdEt.text.toString() + "@" + binding.signUpDirectInputEt.text.toString() + val name: String = binding.signUpNameEt.text.toString() + val pwd: String = binding.signUpPasswordEt.text.toString() + + return User(email, pwd, name) + } + + + + private fun signUp() { + if (binding.signUpIdEt.text.toString() + .isEmpty() || binding.signUpDirectInputEt.text.toString().isEmpty() + ) { + Toast.makeText(this, "이메일 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show() + return + } + + if (binding.signUpPasswordEt.text.toString() != binding.signUpPasswordCheckEt.text.toString()) { + Toast.makeText(this, "비밀번호가 일치하지 않습니다.", Toast.LENGTH_SHORT).show() + return + } + + val authService = AuthService() + authService.setSignUpView(this) + + authService.signUp(getUser()) + + Log.d("SIGNUP-ACT/ASYNC", "Hello, FLO") + } + + override fun onSignUpLoading() { + TODO("Not yet implemented") + } + + override fun onSignUpSuccess() { + finish() + } + + override fun onSignUpFailure() { + //실패처리 + } +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpView.kt b/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpView.kt new file mode 100644 index 0000000..4b3a5cc --- /dev/null +++ b/mission/Flo/app/src/main/java/com/example/flo/ui/siginup/SignUpView.kt @@ -0,0 +1,8 @@ +package com.example.udemy_android_template.ui.siginup + +interface SignUpView { + fun onSignUpLoading() + fun onSignUpSuccess() + fun onSignUpFailure() + //fun onSignUpFailure(code: Int, message: String) +} \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/drawable/ic_back.png b/mission/Flo/app/src/main/res/drawable/ic_back.png new file mode 100644 index 0000000000000000000000000000000000000000..aafa5a63c7e3457dd2b7341256f6c79a8e2726c7 GIT binary patch literal 2754 zcmeHJ`BxKH6rRLJS)^D+5P{Ox4G>1b)5cUGse*t&u*|OE%VVk3q^L7_kH=_Hu-oAc20|JA;BS%qUsIf=l zjvhNsJ9#SpY{E~8$rmoBUP{Ygve=w!S=VpmqvKS5#agC>4szetqy;d4>2< zbxnQ4y(%952X=!b1mv(kNe<6GMS9kxw;Lz~M-}2X^W8)JFrE0To>`n+;5bSLK zjn@w?y-#BqNfcvo#8s!Xg)N?*DIWP`&Y8!h9-&XRXs^0xZ;`P0(zS{Lm-$=MGNc=N zq+eU77rXD{b`OtlK8cey#q|}}30#H8<-$YFTOaw5Lv8E; z%B0@kj|`=CKM^5L$x6ZEMSY~0B2ocutOmtVK1zm{^^)%4g0Eq3F;sgKjkZlN_9lT) zW@Pz(#HP}aqtxBikyNSr(}a3nzD{@J_XSA9FK|W=DXj#!Wt~LeW=2%)N0g`9Y$U>{ z69KCy80F#q6QQjDvrLONmn->g@ahI8Bd`tK%Uoh)Uoh1 zm11mIHpk(&eyUR3I>4-)buR10S6Pou;qdJ4`_C@LKS0c8!?`zyeF%Q4VPT8$jN`cc zHpMhLR@LZ>WdL@?D)H!h{N4c2OqzaG^ApI)k?&7f|6*|NR8wsgW2{jAsBZ*SRX%IJ z+0zJ#{Bs{x2jGzSZ8iT@>%))7BR`HNM^{^nn@;oS?=0=Ao4kozd1SlUVoj&19c1Sr z)W04JWB3f($bEz%U?vT?w-0=!sx-QtKpWZJX)5R@4kouBP&F{?%kf9L#~kxAX!6YG zEJ2NeL#=dHHSmS6RnnonfwZBz_U$T3s|X*rX>?z|uSzoE07+W=+zIl=xW(xLo?v0R zz(BC*vfxa+*2DG-OMuC4|F||&_w?!hZKj&q()pP0`}Iw=b)^%f%Tfg0$G)^Y>T(W! z6&u7s=VJ@JQIdn_eZgx4z1HY0!)$bCF)q z(&jLX8QZ#*qbBgSRvn(qYHY%~yyH39`+^_Ak)yS&H~meLWg%SvI+=@dcp1|Zy<<6Z zP7u|QEd1bP^vu3Ej2UQLi8&wP3aH$SWFEJFuk{?^2q;5l)+{YY!ttP^T7k(a{C1-l zxR6y?@0nOPFvdQU+RtH1Xv_ljiT=6hX$@w80a|2oK3cDyjfSaemQ#Y|c#1xsn(K(* z*rXnt=3exiW^XCjho!th}r^;^Z>TQn*mIEJiV$<{-fT&*{vZ41DTtEkrAk%x?}@zZ>|LF`2d&Q! zh(UE-u_~e08C&t`&f)rjqIg(8kRaQ*;2bQ2|D=?{Nz>* literal 0 HcmV?d00001 diff --git a/mission/Flo/app/src/main/res/drawable/selector_navi_home.xml b/mission/Flo/app/src/main/res/drawable/selector_navi_home.xml new file mode 100644 index 0000000..3ed18be --- /dev/null +++ b/mission/Flo/app/src/main/res/drawable/selector_navi_home.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/drawable/selector_navi_match.xml b/mission/Flo/app/src/main/res/drawable/selector_navi_match.xml new file mode 100644 index 0000000..f32483d --- /dev/null +++ b/mission/Flo/app/src/main/res/drawable/selector_navi_match.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/drawable/selector_navi_mypage.xml b/mission/Flo/app/src/main/res/drawable/selector_navi_mypage.xml new file mode 100644 index 0000000..3bad2a1 --- /dev/null +++ b/mission/Flo/app/src/main/res/drawable/selector_navi_mypage.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/drawable/selector_navi_search.xml b/mission/Flo/app/src/main/res/drawable/selector_navi_search.xml new file mode 100644 index 0000000..34fa8a2 --- /dev/null +++ b/mission/Flo/app/src/main/res/drawable/selector_navi_search.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/drawable/udemy_softsquard.png b/mission/Flo/app/src/main/res/drawable/udemy_softsquard.png new file mode 100644 index 0000000000000000000000000000000000000000..5339fdd7e1425a6b370e2f58ecefd056fbe301e8 GIT binary patch literal 16142 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 literal 0 HcmV?d00001 diff --git a/mission/Flo/app/src/main/res/layout/activity_login.xml b/mission/Flo/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..c9167a0 --- /dev/null +++ b/mission/Flo/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/layout/activity_signup.xml b/mission/Flo/app/src/main/res/layout/activity_signup.xml new file mode 100644 index 0000000..659207d --- /dev/null +++ b/mission/Flo/app/src/main/res/layout/activity_signup.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mission/Flo/app/src/main/res/layout/fragment_search.xml b/mission/Flo/app/src/main/res/layout/fragment_search.xml new file mode 100644 index 0000000..b842786 --- /dev/null +++ b/mission/Flo/app/src/main/res/layout/fragment_search.xml @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file