Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/jstak/kakao #88

Merged
merged 16 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.hh2.katj.history.component

import com.hh2.katj.history.model.entity.SearchLocationHistory
import com.hh2.katj.history.repository.LocationHistoryRepository
import com.hh2.katj.user.model.entity.User
import com.hh2.katj.util.model.RoadAddress
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional

@Component
class LocationHistoryManager(
private val locationHistoryRepository: LocationHistoryRepository,
) {

@Transactional
fun addLocationHistory(user: User, keyword: String, roadAddress: RoadAddress): SearchLocationHistory {
val history = SearchLocationHistory(user = user, keyword = keyword, roadAddress = roadAddress)
return locationHistoryRepository.save(history)
}
Comment on lines +15 to +19
Copy link
Contributor

Choose a reason for hiding this comment

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

성향 차이일것 같은데요, 코틀린이여서 굳이 필요 없을것 같기도 한대
저는 return 시 결괏값을 따로 지정해서 보내줘야 보기 편한것 같다고 생각이 들어서요.
예를 들면 val findLocationHistory = locationHistoryRepository.save(history), return findLocationHistory 같이요.
리턴값이 명확하게 적혀 있으니 괜찮을것 같긴 한데..

Copy link
Member Author

Choose a reason for hiding this comment

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

저도 좀 고민했던 점인데 일단 인텔리제이에서 밑줄 생기는게 신경쓰여서... ㅎㅎ 그리고 return 하기전에 추가로 해야되는 작업이 있으면 그때 바꾸면 되지 않을까 싶어서 이런식으로 했습니다.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.hh2.katj.history.controller

import com.hh2.katj.history.model.dto.RequestLocationHistory
import com.hh2.katj.history.model.dto.ResponseLocationHistory
import com.hh2.katj.history.service.LocationHistoryService
import com.hh2.katj.user.service.UserService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RequestMapping("/location")
@RestController
class LocationHistoryController(
private val locationHistoryService: LocationHistoryService,
private val userService: UserService,
) {

@PostMapping
fun saveLocation(@RequestBody request: RequestLocationHistory): ResponseEntity<ResponseLocationHistory> {
val user = userService.findByUserId(userId = request.userId)
val response = locationHistoryService.saveLocationHistory(user, request.keyword)
return ResponseEntity.ok(response)
}
Comment on lines +20 to +25
Copy link
Contributor

Choose a reason for hiding this comment

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

전 이렇게 userId가 필요할 경우 request에 user정보가 있더라도 @RequestParam 으로 따로 받게 했는데
도메인별로 좀 나누고자 했던 마음도 있던것 같아요. 어떤게 더 나을지 의견 나누고 싶습니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

post 라서 그냥 body에 넣으면 될 것 같았는데 생각해보니까 pathvariable이나 requestparam으로 쓰는게 맞는것 같네요

Copy link
Contributor

Choose a reason for hiding this comment

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

아 현준님께서는 제 코드 보시고 reuqestbody 값에서 꺼내 쓰면 되지 않냐고 물어보여서 어떤게 나을지 잘 모르겟어서요..
내일 허재 코치님께 여쭈어봐도 괜찮을것 같습니다!


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.hh2.katj.history.model.dto

data class RequestLocationHistory(
val userId: Long,
val keyword: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.hh2.katj.history.model.dto

import com.hh2.katj.util.model.RoadAddress

data class ResponseLocationHistory(
val userId: Long,
val roadAddress: RoadAddress,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.hh2.katj.history.model.entity

import com.hh2.katj.history.model.dto.ResponseLocationHistory
import com.hh2.katj.user.model.entity.User
import com.hh2.katj.util.model.BaseEntity
import com.hh2.katj.util.model.RoadAddress
import jakarta.persistence.*

@Entity
class SearchLocationHistory(
user: User,
roadAddress: RoadAddress,
keyword: String,
) : BaseEntity() {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false,
foreignKey = ForeignKey(ConstraintMode.NO_CONSTRAINT)
)
var user = user
protected set

@Embedded
@Column(nullable = false)
var roadAddress = roadAddress
protected set

@Column(nullable = false)
var keyword = keyword
protected set

fun toResponseDto(): ResponseLocationHistory {
return ResponseLocationHistory(
userId = user.id,
roadAddress = roadAddress,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.hh2.katj.history.repository

import com.hh2.katj.history.model.entity.SearchLocationHistory
import org.springframework.data.jpa.repository.JpaRepository

interface LocationHistoryRepository : JpaRepository<SearchLocationHistory, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.hh2.katj.history.service

import com.hh2.katj.history.component.KakaoApiManager
import com.hh2.katj.history.component.LocationHistoryManager
import com.hh2.katj.history.model.dto.ResponseLocationHistory
import com.hh2.katj.user.model.entity.User
import com.hh2.katj.util.exception.failWithMessage
import org.springframework.stereotype.Service

@Service
class LocationHistoryService(
private val locationHistoryManager: LocationHistoryManager,
private val kakaoApiManager: KakaoApiManager,
) {

fun saveLocationHistory(user: User, keyword: String): ResponseLocationHistory {
val response = kakaoApiManager.requestAddressSearch(keyword)

checkNotNull(response) {
failWithMessage("")
}

val roadAddress = response.documents[0].roadAddress

return locationHistoryManager.addLocationHistory(user, keyword, roadAddress).toResponseDto()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

service에서 user 뿐만 아니라 다른 도메인 관련 객체 사용시

  1. 넘어온 객체 그대로 사용
  2. 넘어온 객체의 id로 db에서 조회해서 해당 객체 사용
    저는 주로 2번을 쓰는데요, 1번 사용 하더라도 Service 계층으로 넘어왔을 때 user에 대한 검증이 한번 더 이루어진 상태에서 사용하면 더 안전할것 같은 생각이 들어요.

Copy link
Member Author

Choose a reason for hiding this comment

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

controller에서 user service로 find하고 넘기게끔 해놓았는데 그냥 다 service 계층에서 처리하는게 맞는건가 고민이되긴 하네요

Copy link
Contributor

Choose a reason for hiding this comment

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

저는 controller에서는 api 호출 / 응답 에만 초점을 두고 싶어서 serivce 계층에서 처리하는걸로 했거든요 ㅎㅎ
처음에 즐겨찾기 만들때 userRepository를 통해 user를 확인해야 하니 component에서 user검증을 진행 했는데 그건 아닌것 같아 service 계층으로 모두 옮겨서 진행했습니다!

15 changes: 15 additions & 0 deletions src/main/kotlin/com/hh2/katj/util/config/RestTemplateConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.hh2.katj.util.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.client.RestTemplate


@Configuration
class RestTemplateConfig {

@Bean
fun restTemplate(): RestTemplate {
return RestTemplate()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.hh2.katj.history.service

import com.hh2.katj.history.repository.LocationHistoryRepository
import com.hh2.katj.user.model.entity.Gender
import com.hh2.katj.user.model.entity.User
import com.hh2.katj.user.model.entity.UserStatus
import com.hh2.katj.user.repository.UserRepository
import com.hh2.katj.user.service.UserService
import com.hh2.katj.util.model.RoadAddress
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestConstructor

@SpringBootTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
class LocationHistoryServiceTest(
private val locationHistoryRepository: LocationHistoryRepository,
private val locationHistoryService: LocationHistoryService,
private val userRepository: UserRepository,
) {

@AfterEach
fun tearUp() {
userRepository.deleteAllInBatch()
locationHistoryRepository.deleteAllInBatch()
}

@Test
fun `검색어를 통해 위치정보를 찾고 이력을 저장한다`() {
// given
val roadAddress = RoadAddress(
addressName = "서울 관악구 법원단지5가길 76",
buildingName = "대명아트빌",
mainBuildingNo = "76",
region1depthName = "서울",
region2depthName = "관악구",
region3depthName = "신림동",
roadName = "법원단지5가길",
subBuildingNo = "",
undergroundYn = "N",
longitude = "126.923157313768",
latitude = "37.4764786774284",
zoneNo = "08852",
)

val user = User(
name = "탁지성",
phoneNumber = "01032535576",
email = "[email protected]",
gender = Gender.MALE,
status = UserStatus.ACTIVE,
roadAddress = roadAddress,
)

// when
val saveUser = userRepository.save(user)
val response = locationHistoryService.saveLocationHistory(saveUser, keyword = "법원단지5가길 76")

// then
assertThat(response.roadAddress.addressName).isEqualTo(roadAddress.addressName)
}

}