ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,27 @@
+package codesquad.answer;
+
+import codesquad.response.Result;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+public class ApiAnswerController {
+
+    private final AnswerService answerService;
+
+    @PostMapping("/questions/{question-id}/answers")
+    public Result<ResponseAnswerDto> create(@PathVariable("question-id") Long questionId, @RequestBody RequestAnswerDto requestAnswerDto, HttpSession session) {
+        return answerService.create(questionId, requestAnswerDto, session);
+    }
+
+    @DeleteMapping("/questions/{question-id}/answers/{answer-id}")
+    public Result<ResponseAnswerDto> remove(@PathVariable("question-id") Long questionId,
+                                            @PathVariable("answer-id") Long answerId, HttpSession session) {
+        return answerService.remove(questionId, answerId, session);
+    }
+}

리뷰: create메서드는 성공, 실패 여부없이 Result 를 반환하기 때문에 200 OK가 나갈 것이라고 생각합니다!
@@ -55,6 +55,7 @@ captures/
 .idea/caches
 
 # Keystore files
+keystore.properties
 # Uncomment the following line if you do not want to check your keystore files in.
 #*.jks
 
@@ -100,3 +101,6 @@ $RECYCLE.BIN/
 # Windows shortcuts
 *.lnk
 
+app/src/main/java/kr/co/connect/boostcamp/livewhere/ui/bookmark/
+app/src/main/java/kr/co/connect/boostcamp/livewhere/ui/search/
+app/src/main/res/layout-v26/

리뷰: #82 작업이 어떤건지 히스토리가 없어서 왜 추가되었는지 모르겠는데

1) 보안과 관련되어 공유되지 않아야 하는 파일
2) 개인별 환경설정 파일
3) 캐시 파일
4) 쓰레기 파일

등의 사유가 아니라면 .gitignore에 들어가는게 부적절해 보입니다.
해당 폴더를 git에서 제거하려다 편법을 쓴게 아닐까 추측이 되는데 올바르지 못한 방법인거 같아요.
@@ -1,21 +1,54 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="kr.co.connect.boostcamp.livewhere">
-
+          xmlns:tools="http://schemas.android.com/tools" package="kr.co.connect.boostcamp.livewhere">
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <application
-            android:allowBackup="true"
-            android:icon="@mipmap/ic_launcher"
+            android:name=".LiveApplication"
+            android:allowBackup="false"
+            android:icon="@drawable/icon_logo"
+            android:roundIcon="@drawable/icon_logo"
             android:label="@string/app_name"
-            android:roundIcon="@mipmap/ic_launcher_round"
             android:supportsRtl="true"
             android:theme="@style/AppTheme">
-        <activity android:name=".MainActivity">
+
+        <uses-library android:name="org.apache.http.legacy"
+                      android:required="false"/>
+
+        <meta-data
+                android:name="com.google.android.geo.API_KEY"
+                android:value="@string/key_street_view"/>
+        <activity android:name=".ui.main.SplashActivity"
+                  android:theme="@style/SplashTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
 
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <activity android:name=".ui.login.LoginActivity">
+
+        </activity>
+        <activity android:name=".ui.main.HomeActivity">
+        </activity>
+        <activity android:name=".ui.detail.DetailActivity"
+                  android:windowSoftInputMode="adjustResize">
+
+        </activity>
+        <activity android:name=".ui.map.MapActivity"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW"/>
+
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".ui.map.StreetMapActivity"
+                  android:screenOrientation="portrait">
+        </activity>
+
     </application>
 
 </manifest>
\ No newline at end of file

리뷰: `android:screenOrientation` 속성이 일부 Activity에만 적용되어 있는데 의도하신게 아니라 빠트리신거 같네요
@@ -0,0 +1,45 @@
+package kr.co.connect.boostcamp.livewhere
+
+import android.content.Context
+import androidx.multidex.MultiDex
+import androidx.multidex.MultiDexApplication
+import com.bumptech.glide.Glide
+import com.crashlytics.android.Crashlytics
+import com.facebook.stetho.Stetho
+import com.naver.maps.map.NaverMapSdk
+import io.fabric.sdk.android.Fabric
+import kr.co.connect.boostcamp.livewhere.di.appModules
+import org.koin.android.ext.android.startKoin
+
+
+// FIXME MultiDex 이슈가 발생할 여지가 충분하기때문에 gradle과 Application클래스에서 Multidex 환경을 구성해주세요
+class LiveApplication : MultiDexApplication() {
+    override fun onCreate() {
+        super.onCreate()
+        //debug변수를 놓고 debug 인지 캐치함.
+        if (BuildConfig.isDebug) {
+            Stetho.initializeWithDefaults(this)
+        }
+        startKoin(this, appModules)
+        //Firebase Crashlytics
+        Fabric.with(this, Crashlytics())
+        NaverMapSdk.getInstance(this).client = NaverMapSdk.NaverCloudPlatformClient(BuildConfig.NaverClientId)
+    }
+
+    //application class에서 MultiDex 사용
+    override fun attachBaseContext(base: Context?) {
+        super.attachBaseContext(base)
+        MultiDex.install(this)
+    }
+
+
+    override fun onLowMemory() {
+        super.onLowMemory()
+        Glide.get(this).clearMemory()
+    }
+
+    override fun onTrimMemory(level: Int) {
+        super.onTrimMemory(level)
+        Glide.get(this).trimMemory(level)
+    }
+}
\ No newline at end of file

리뷰: https://github.com/boostcamp-3rd/android_teamC/pull/8/files#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R21
이미 multidex 설정되어 있습니다.
불필요한 주석이 남아있는건 코드를 읽는데 어려움을 주니 제거해주세요.
@@ -0,0 +1,45 @@
+package kr.co.connect.boostcamp.livewhere
+
+import android.content.Context
+import androidx.multidex.MultiDex
+import androidx.multidex.MultiDexApplication
+import com.bumptech.glide.Glide
+import com.crashlytics.android.Crashlytics
+import com.facebook.stetho.Stetho
+import com.naver.maps.map.NaverMapSdk
+import io.fabric.sdk.android.Fabric
+import kr.co.connect.boostcamp.livewhere.di.appModules
+import org.koin.android.ext.android.startKoin
+
+
+// FIXME MultiDex 이슈가 발생할 여지가 충분하기때문에 gradle과 Application클래스에서 Multidex 환경을 구성해주세요
+class LiveApplication : MultiDexApplication() {
+    override fun onCreate() {
+        super.onCreate()
+        //debug변수를 놓고 debug 인지 캐치함.
+        if (BuildConfig.isDebug) {
+            Stetho.initializeWithDefaults(this)
+        }
+        startKoin(this, appModules)
+        //Firebase Crashlytics
+        Fabric.with(this, Crashlytics())
+        NaverMapSdk.getInstance(this).client = NaverMapSdk.NaverCloudPlatformClient(BuildConfig.NaverClientId)
+    }
+
+    //application class에서 MultiDex 사용
+    override fun attachBaseContext(base: Context?) {
+        super.attachBaseContext(base)
+        MultiDex.install(this)
+    }
+
+
+    override fun onLowMemory() {
+        super.onLowMemory()
+        Glide.get(this).clearMemory()
+    }
+
+    override fun onTrimMemory(level: Int) {
+        super.onTrimMemory(level)
+        Glide.get(this).trimMemory(level)
+    }
+}
\ No newline at end of file

리뷰: 동작이 자명한 코드라 주석이 불필요해 보입니다.
@@ -0,0 +1,40 @@
+package kr.co.connect.boostcamp.livewhere.api
+
+import io.reactivex.Single
+import kr.co.connect.boostcamp.livewhere.model.HouseResponse
+import kr.co.connect.boostcamp.livewhere.model.PlaceResponse
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Query
+
+interface Api {
+    @GET("house/search/info")
+    fun getHouseDetail(
+        @Query("address") address: String
+    ): Single<Response<List<Any>>>
+
+    @GET("house/search/infos")
+    fun getDetail(
+        @Query("address") address: String
+    ): Single<Response<HouseResponse>>
+
+    @GET("place/search/infos")
+    fun getPlace(
+        @Query("lat") lat: String,
+        @Query("lng") lng: String,
+        @Query("radius") radius: String,
+        @Query("category") category: String
+    ): Single<Response<PlaceResponse>>
+
+    @GET("house/search/find/infos")
+    fun getDetailWithAddress(
+        @Query("address") address: String
+    ): Single<Response<HouseResponse>>
+
+    @POST("")
+    fun postReview(
+        @Query("nickname") nickname: String, @Query("id") id: String, @Query("contents") contents: String
+    ): Single<Response<Any>>
+
+}
\ No newline at end of file

리뷰: 어떠한 자원도 가리키고 있지 않다면 RESTful 하지 않습니다.
올바르지 못한 설계입니다.
@@ -0,0 +1,20 @@
+package kr.co.connect.boostcamp.livewhere.api
+
+import io.reactivex.Observable
+import kr.co.connect.boostcamp.livewhere.BuildConfig
+import kr.co.connect.boostcamp.livewhere.model.TmapResponse
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Query
+
+interface TmapApi {
+    @GET("tmap/pois")
+    fun getAddress(
+        @Query("searchKeyword") searchKeyword: String,
+        @Query("appKey") appKey: String = BuildConfig.TmapApiKey,
+        @Query("count") count: String = "10",
+        @Query("areaLLCode") code: String = "11"
+    ): Observable<Response<TmapResponse>>
+
+
+}
\ No newline at end of file

리뷰: `10`, `11`은 어떤 기준으로 정해진 default 값인지 알 방법이 없습니다.
상수로 빼내고 변수명에 의미를 담는건 어떨까요?
@@ -0,0 +1,20 @@
+package kr.co.connect.boostcamp.livewhere.api
+
+import io.reactivex.Observable
+import kr.co.connect.boostcamp.livewhere.BuildConfig
+import kr.co.connect.boostcamp.livewhere.model.TmapResponse
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Query
+
+interface TmapApi {
+    @GET("tmap/pois")
+    fun getAddress(
+        @Query("searchKeyword") searchKeyword: String,
+        @Query("appKey") appKey: String = BuildConfig.TmapApiKey,
+        @Query("count") count: String = "10",
+        @Query("areaLLCode") code: String = "11"
+    ): Observable<Response<TmapResponse>>
+
+
+}
\ No newline at end of file

리뷰: Retrofit으로 구현되는데 Observable일 필요가 없습니다. Http니까요.
@@ -0,0 +1,19 @@
+package kr.co.connect.boostcamp.livewhere.api
+
+import io.reactivex.Single
+import kr.co.connect.boostcamp.livewhere.BuildConfig
+import kr.co.connect.boostcamp.livewhere.model.ReverseGeo
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Headers
+import retrofit2.http.Query
+
+interface ReverseGeoApi {
+    @Headers("Authorization: KakaoAK " + BuildConfig.KakaoServiceKey)
+    @GET("geo/coord2address.json")
+    fun getAddress(
+        @Query("y") latitude: String,
+        @Query("x") longitude: String,
+        @Query("input_coord") inputCoord: String
+    ): Single<Response<ReverseGeo>>
+}
\ No newline at end of file

리뷰: gps 좌표 정보인걸로 보이는데 String이 맞나요?
@@ -0,0 +1,12 @@
+package kr.co.connect.boostcamp.livewhere.data.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "recent_search")
+data class RecentSearchEntity(
+    @PrimaryKey var text: String,
+    @ColumnInfo(name = "Longitude") var longitude: String,
+    @ColumnInfo(name = "Latitude") var latitude: String
+)
\ No newline at end of file

리뷰: 다른 테이블의 컬럼들은 소문자로 시작하는 snake case를 사용하고 있습니다.
통일이 필요해보여요
@@ -0,0 +1,13 @@
+package kr.co.connect.boostcamp.livewhere.di
+
+
+val appModules = arrayListOf(
+    apiModule
+    , loginModule
+    , sharedModule
+    , databaseModule
+    , homeModule
+    , mapModule
+    , reverseGeoApiModule
+    , detailModule
+)

리뷰: 다른 코드들과 전혀 다른 code format인데 통일이 필요해 보입니다.
@@ -0,0 +1,24 @@
+package kr.co.connect.boostcamp.livewhere.di
+
+import androidx.room.Room
+import kr.co.connect.boostcamp.livewhere.data.database.AppDataBase
+import org.koin.android.ext.koin.androidContext
+import org.koin.dsl.module.module
+
+const val DATABASE_NAME = "mdatabase.db"
+
+val databaseModule = module {
+    single("databaseModule") {
+        Room.databaseBuilder(androidContext(), AppDataBase::class.java, DATABASE_NAME)
+            .fallbackToDestructiveMigration()
+            .build()
+    }
+
+    single("bookmarkDAO") {
+        get<AppDataBase>().bookmarkDao()
+    }
+
+    single("recentSearchDAO") {
+        get<AppDataBase>().recentSearchDao()
+    }
+}
\ No newline at end of file

리뷰: 이 모듈에 정의된 3가지 injection들은 named inject가 필요한가요?
불필요해보입니다.
@@ -3,7 +3,10 @@
   <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <title>React App</title>
+    <meta name="description" content="Web site created using create-react-app"/>
+    <link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
+    <title>Westagram</title>
   </head>
   <body>
     <div id="root"></div>

리뷰: description은 없어도 되지 않을까요? 잘 모르겠습니다 ㅎㅎ
@@ -0,0 +1,50 @@
+import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+
+class LoginJaeyoung  extends React.Component {
+    constructor () {
+        super();
+        this.state = {
+            id: '',
+            pw : '',
+        };
+    }
+
+    handleInput = (e) => {
+        const { name,value} = e.target;
+        this.setState({
+            [name]: value
+        })
+    }
+    
+    goToMain = () => {
+        this.props.history.push('/main-jaeyoung')
+    }
+
+
+    render () {
+        const { handleInput } = this
+        const isBtnAble = this.state.id.includes('@') && this.state.pw.length >= 5;
+
+
+        return (
+            <div className="loginContainer">
+                <div className="logoName">
+                    <h1>Instargram</h1>
+                </div>
+                <div className="loginInfo">
+                    <input type="text" name="id" onChange={handleInput} className="loginId" placeholder="전화번호, 사용자 이름 또는 이메일" />
+                    <input type="password" name="pw" onChange={handleInput} className="loginPs" placeholder="비밀번호"/>
+                    <button className="loginBt" onClick={this.goToMain} disabled={!isBtnAble}>로그인</button>
+                </div>
+                <div className="forgetPassword">
+                    <a href="https://www.naver.com/">비밀번호를 잊으셨나요?</a>
+                </div>
+            </div>
+        )
+    }
+}
+
+export default withRouter( LoginJaeyoung );
\ No newline at end of file

리뷰: https://www.notion.so/wecode/React-Refactoring-Check-List-aea297cf88ed4601b769e4b2c2cfd4e1#089493d6bfca438aa328226e327cff92
이 부분을 참고하면 하나의 메소드롤 묶을 수 있습니다.
@@ -0,0 +1,85 @@
+* {
+  box-sizing: border-box;
+}
+
+.loginContainer {
+  border: 2px solid #e6e6e6;
+  width: 350px;
+  height: 380px;
+  margin: 0 auto;
+  .logoName {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      h1 {
+          font-family: "Lobster", cursive;
+          width: 175px;
+          height: 52px;
+          text-align: center;
+          padding-top: 6px;
+      }
+  }
+  .loginInfo {
+      height: 213px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding-top: 10px;
+      .loginId {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }
+      .loginPs {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }    
+      .loginBt {
+        width: 268px;
+        height: 30px;
+        margin-top: 5px;
+        border-radius: 3px;
+        background-color: #2795f6;
+        color: #ffffff;
+        border-style: none;
+        
+        &:focus {
+            outline: none;
+        }
+        
+        &:disabled {
+             background-color: #b2dffc;
+         }
+    }
+  }
+  .forgetPassword{
+      display: flex;
+      justify-content: center;
+      margin-top: 20px;
+      a {
+          color: #043569; text-decoration: none;
+      }
+  }
+  
+  
+}

리뷰: 이 부분은 common.css에 있으면 좋을 것 같습니다.
@@ -0,0 +1,85 @@
+* {
+  box-sizing: border-box;
+}
+
+.loginContainer {
+  border: 2px solid #e6e6e6;
+  width: 350px;
+  height: 380px;
+  margin: 0 auto;
+  .logoName {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      h1 {
+          font-family: "Lobster", cursive;
+          width: 175px;
+          height: 52px;
+          text-align: center;
+          padding-top: 6px;
+      }
+  }
+  .loginInfo {
+      height: 213px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding-top: 10px;
+      .loginId {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }
+      .loginPs {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }    
+      .loginBt {
+        width: 268px;
+        height: 30px;
+        margin-top: 5px;
+        border-radius: 3px;
+        background-color: #2795f6;
+        color: #ffffff;
+        border-style: none;
+        
+        &:focus {
+            outline: none;
+        }
+        
+        &:disabled {
+             background-color: #b2dffc;
+         }
+    }
+  }
+  .forgetPassword{
+      display: flex;
+      justify-content: center;
+      margin-top: 20px;
+      a {
+          color: #043569; text-decoration: none;
+      }
+  }
+  
+  
+}

리뷰: font-family같은 속성은 width나 margin아래에 있으면 좋을 것 같습니다.
@@ -0,0 +1,85 @@
+* {
+  box-sizing: border-box;
+}
+
+.loginContainer {
+  border: 2px solid #e6e6e6;
+  width: 350px;
+  height: 380px;
+  margin: 0 auto;
+  .logoName {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      h1 {
+          font-family: "Lobster", cursive;
+          width: 175px;
+          height: 52px;
+          text-align: center;
+          padding-top: 6px;
+      }
+  }
+  .loginInfo {
+      height: 213px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding-top: 10px;
+      .loginId {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }
+      .loginPs {
+          width: 268px;
+          height: 38px;
+          margin-bottom: 5px;
+          padding-left: 10px;
+          border-radius: 3px;
+          border: 1px solid #efefef;
+          background: #fafafa;
+          color: #9c9c9c;
+          font-size: 14px;
+          &:focus {
+              outline-color: gray;
+            }
+      }    
+      .loginBt {
+        width: 268px;
+        height: 30px;
+        margin-top: 5px;
+        border-radius: 3px;
+        background-color: #2795f6;
+        color: #ffffff;
+        border-style: none;
+        
+        &:focus {
+            outline: none;
+        }
+        
+        &:disabled {
+             background-color: #b2dffc;
+         }
+    }
+  }
+  .forgetPassword{
+      display: flex;
+      justify-content: center;
+      margin-top: 20px;
+      a {
+          color: #043569; text-decoration: none;
+      }
+  }
+  
+  
+}

리뷰: 넘 디테일한 css 속성값 ..  재영님 노고에 경의를..👏🏻
@@ -0,0 +1,50 @@
+import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+
+class LoginJaeyoung  extends React.Component {
+    constructor () {
+        super();
+        this.state = {
+            id: '',
+            pw : '',
+        };
+    }
+
+    handleInput = (e) => {
+        const { name,value} = e.target;
+        this.setState({
+            [name]: value
+        })
+    }
+    
+    goToMain = () => {
+        this.props.history.push('/main-jaeyoung')
+    }
+
+
+    render () {
+        const { handleInput } = this
+        const isBtnAble = this.state.id.includes('@') && this.state.pw.length >= 5;
+
+
+        return (
+            <div className="loginContainer">
+                <div className="logoName">
+                    <h1>Instargram</h1>
+                </div>
+                <div className="loginInfo">
+                    <input type="text" name="id" onChange={handleInput} className="loginId" placeholder="전화번호, 사용자 이름 또는 이메일" />
+                    <input type="password" name="pw" onChange={handleInput} className="loginPs" placeholder="비밀번호"/>
+                    <button className="loginBt" onClick={this.goToMain} disabled={!isBtnAble}>로그인</button>
+                </div>
+                <div className="forgetPassword">
+                    <a href="https://www.naver.com/">비밀번호를 잊으셨나요?</a>
+                </div>
+            </div>
+        )
+    }
+}
+
+export default withRouter( LoginJaeyoung );
\ No newline at end of file

리뷰: target 보다는 직관적인 키네임으로 변경하면 좋을 것 같습니다.