BackEnd/코틀린 스프링

[Kotlin Spring] 프로젝트 01. 회원 가입 만들기

세모 2024. 10. 28. 02:45

코틀린 프로젝트 2번째 시간입니다.

이번엔 간단하게 회원가입을 구현해 보겠습니다.


이 기록 겸 강의는 초보자 기준으로 작성이 되었고, 새로 시작하게 된 코틀린 스프링 유저에게 많은 도움이 될 수 있었다면 좋겠다는 마음으로 시작합니다.

틀린 부분이 있다면 알려주시면 감사하겠습니다.


시작하게 전에 먼저 간단하게 어떤 흐름으로 진행되는지 설명하겠습니다.

서버 흐름의 간략도

  • client(사용자) : api사용자를 의미하며 원하는 정보를 얻기 위해 서버에게 요청하는 사람을 의미합니다.
  • controller(컨트롤러) : api를 요청할때 진입되는 주소를 설정하고 어떤 방식으로 처리할지 정해주고 모든 처리가 끝난 데이터를 클라이언트 즉, 사용자에게 전달해 주는 역할을 합니다.
    • 쉽게 이해하기 위해 설명드리면 https://semolu.tistory.com/1이라는 주소가 있습니다.
    • 이를 현재주소로 변환 시 아래 표와 같은데요 여기서 endpoint를 설정하는 곳이 controller에서 진행됩니다
도메인 (아파트 주소)   endpoint(쉽게 동호수)
https://semolu.tistory.com /1
OO시 OO구 OO동 OO아파트 1호
  • dto(디티오) : 데이터 전송 객체라고 부르는 객체입니다. 사용자가 요청 시 서버로 같이 보내는 정보라고 이야기할 수 있습니다. 쉽게 예를 들면 로그인 시 아이디 비밀번호를 서버로 보낼 때 정보를 담는 곳이라고 볼 수 있습니다.
  • service(서비스) : 말 그대로 서비스 로직입니다. 컨트롤러에서 지정한 서비스 로직으로 넘어와서 지정된 일을 수행합니다.
  • repository(레파지토리) : 데이터 베이스에 접근하는 메서드들을 사용하기 위한 집합을 모아둔 곳이라고 볼 수 있습니다. 예를 들어 회원가입을 할 땐 정보를 저장하는 save, 회원탈퇴는 정보를 지우는 delete, 등등 어떻게 처리할지 수정하는 곳입니다.
  • entity(엔티티) : 데이터 베이스에 저장되는 테이블이자 스프링에서 사용될 객체라고 볼 수 있습니다. 쉽게 설명드리면 각 팀에 이름과 전화번호 사번 등등의 정보가 있는 엑셀 표라고 보면 됩니다 
  • DB(데이터 베이스) : 데이터 베이스는 정보의 표가 담기는 프로그램입니다. 주로 SQL과 NoSQL로 나뉩니다.

이제부터 개발을 시작하도록 하겠습니다.

src > main > kotlin > 프로젝트이름 > member 생성

상단에 기능을 하기 위해서 controller, dto, entity, repository, service를 만들어줍니다.

먼저 dto를 보겠습니다

data class MemberDtoRequset(
    val id: Long?,
    val loginId: String,
    val password: String,
    val name: String,
    val email: String,
    val area: String,
)

회원 가입 시 받을 정보를 구성합니다.

  • id : 각 회원당 회원번호를 부여합니다. 따로 받지 않을 예정이기에 숫자 타입 중 큰 Long을 이용하고, ?를 붙어 null을 허용합니다.
  • loginId : 로그인 아이디를 받습니다.
  • password : 비밀번호를 받습니다.
  • name : 이름이나 닉네임을 받습니다.
  • email : 이메일을 받습니다 추후 이메일 인증이나 비밀번호 초기화에서 사용 가능합니다.
  • area : 지역을 받습니다.

다음은 entity입니다.

@Entity
@Table(
    uniqueConstraints = [
        UniqueConstraint(name = "uk_member_login_id", columnNames = ["loginId"])
    ]
)
class Member(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null,

    @Column(nullable = false, length = 30, updatable = false)
    val loginId: String,

    @Column(nullable = false, length = 100)
    val password: String,

    @Column(nullable = false, length = 10)
    val name: String,

    @Column(nullable = false, length = 30)
    val email: String,

    @Column(nullable = false, length = 10)
    val area: Area,
)

아까 받은 정보들을 데이터 베이스에 넣기 위해 틀을 짜줍니다.

@Entity로 스프링에게 이 부분이 entity에 해당한다고 알려줍니다.

여기서 Id는 자동으로 값을 넣어주는데요 IDENTITY 말고 AUTO를 사용할 수 있지만 IDENTITY를 사용하는 이유는 auto의 경우 한계가 있기 때문입니다.

그 이외엔 길이제한, 빈 값이 가능한지를 나타내줍니다.


repository입니다.

interface MemberRepository : JpaRepository<Member, Long>{
    fun findByLoginId(LoginId: String): Member?
}

interface를 사용하게 되는데 dependencies를 통해 의존성이 주입이 되어 JPA를 활용한 레파지토리를 생성했습니다.

여기에 회원가입 시 중복된 아이디를 받지 않기 위해 검사를 위한 findByLoginId를 만들어 줬습니다.

말 그대로 괄호 안에 들어온 아이디를 기준으로 해당하는 객체가 있는지 확인합니다. 있다면 그 객체를 없다면 null을 보낼 수 있도록 ?를 넣어줍니다.


service입니다.

@Transactional
@Service
class MemberService(
    private val memberRepository: MemberRepository,
) {
    /**
     * 회원가입
     */
    fun signUp(memberDtoRequest: MemberDtoRequest): String{
        var member: Member? = memberRepository.findByLoginId(memberDtoRequest.loginId)
        if(member != null){
            return "이미 등록된 ID 입니다."
        }

        member = Member(
       		null,
            memberDtoRequest.loginId,
            memberDtoRequest.password,
            memberDtoRequest.name,
            memberDtoRequest.email,
            memberDtoRequest.area
        )
        
        memberRepository.save(member)

        return "회원 가입 완료"
    }
}

실질적으로 실행하게 될 회원가입 로직입니다.

@Service를 사용해 서비스 로직이라는 걸 알려줍니다.

@Transaction을 사용하는데요 쉽게 데이터베이스 관리를 일관성 있도록 유지시켜 줘서 안정적인 작업이 가능하게 해주는 친구입니다.

여기서 memberDtoRequest에서 받아온 정보로 member 객체를 찾아보고 있다면 이미 등록된 ID라는 걸 알려주고 없다면 객체에 담아 Repository를 이용해 저장해 주고 완료되었음을 보내줍니다.


마지막 controller입니다.

@RestController
@RequestMapping("/member")
class MemberController(
    private val memberService: MemberService
) {
    /**
     * 회원 가입
     */
    @PostMapping("/signup")
    fun signUp(@RequestBody memberDtoRequest: MemberDtoRequest): String{
        val resultMsg : String = memberService.signUp(memberDtoRequest)
        return resultMsg
    }
}

@RestController로 스프링에게 Controller라는 것을 알려줍니다.

@RequestMapping("/member")를 이용해 해당 class에 있는 모든 컨트롤러 펑션의 엔드포인트 앞부분엔 /member가 추가됩니다.

@PostMapping으로 회원가입에 대한 로직을 받아주고, 받은 정보들을 서비스 로직으로 보내 작업을 실행하고 모든 작업이 
끝나면 사용자에게 resultMsg을 보내줍니다.


이렇게 간단하게 회원가입을 만들어 봤는데요.

아직 모자란 부분이 많습니다.

  1. 비밀번호 암호화
  2. 로그인 및 다른 기능들
  3. 정형화되지 않은 Dto값들을 처리할 방법
  4. 그 이외의 것들

이 부족한 부분을 참고해서 진행하면서 진행해보려고 합니다.

해당 프로젝트는 앞으로 배포까지 진행될 예정입니다.

 

궁금하시거나 오류 나는 부분이 있다면 알려주세요.

알고 있는 부분이라면 도움을 드리겠습니다.

 

부족한글 읽어주셔서 감사합니다.

 

피드백은 언제든 환영입니다.