oxdjww 2023. 5. 16. 11:40
728x90
반응형

기술스택

> Front

    > React

> Back

    > SpringBoot

    > MariaDB

> Server

    > Cloudtype

 

학부 과정 중 소프트웨어프로젝트 과목에서 개발한 '학교 내부 길찾기 및 공강 스터디룸 예약 매칭 서비스' 이다.

 

본 글에서는 필자가 구현한 SpringBoot기반 Join, Login 및 배포과정을 다루었다.

 

1. start.spring.io

1. SpringBoot starter를 통해 파일을 만들어준다.

 

2. .zip 파일이 생성되면 압축해제 후 본인이 편한 디렉토리에 놓아준다.

... 저는 뭐가 많네요.. 본인이 생성하신 zip파일 압축해제하시면 됩니다

 

2. Join & Login API

본 프로젝트는 홈 화면이 로그인화면 이므로 MemberController를 통해 이를 구현해주었다.

그 외 회원가입이 되어있지 않아 회원가입 페이지로 이동하면 read()에서 처리해준다

@RequiredArgsConstructor
@RestController
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/")
    public Long login(@RequestBody MemberLoginVO memberLoginVO) {
        String email = memberLoginVO.getEmail();
        String password = memberLoginVO.getPassword();

        Member member = memberService.findByEmail(email);
        if (member != null && member.getPassword().equals(password)) {
            // 로그인 성공
            return member.getId();
        } else {
            // 로그인 실패
            return null;
        }
}
    @PostMapping("/join")
    public Long create(@RequestBody Member member) {
        return memberService.save(member);
    }

    @GetMapping("/member/{id}")
    public Member read(@PathVariable Long id) {

        return memberService.findById(id);
    }

    @PostMapping("/member/{id}/update")
    public Long update(@PathVariable Long id, @RequestBody Member member) {
        return memberService.update(id, member);
    }

    @PostMapping("/member/{id}/delete")
    public Long delete(@PathVariable Long id) {
        memberService.delete(id);
        return id;
    }
}

회원정보를 저장하는 Member Entity

> Primary key는 id, 그 외 update, setPW 메서드도 구현하였다.

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Member {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String email;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String password;

    @Builder
    public Member(String email, String name, String password) {
        this.email=email;
        this.name=name;
        this.password=password;
    }

    public void update(String email, String name, String password) {
        this.email=email;
        this.name=name;
        this.password=password;
    }

    public void setPassword(String password) {
        this.password=password;
    }
}

로그인 폼을 담당하는 MemberLoginVO

@Getter
@Setter
public class MemberLoginVO {
    public MemberLoginVO() {

    }

    public MemberLoginVO(String email, String password) {
        this.email = email;
        this.password = password;
    }
    private String email;

    private String password;
}

SpringDataJPA담당하는 repository

> SpringDataJPA가 자동으로 지원해주지 않는 findByEmail은 따로 구현해주었다

public interface MemberJpaRepository extends JpaRepository<Member,Long> {
    Optional<Object> findByEmail(String email);
}

CRUD 지원하는 MemberService

@Service
@RequiredArgsConstructor
public class MemberService {
    private final MemberJpaRepository memberJpaRepository;

    @Transactional
    public Long save(Member member) {
        return memberJpaRepository.save(member).getId();
    }

    @Transactional
    public Long update(Long id, Member member) {
        Member currentMember = findById(id);
        currentMember.update(member.getEmail(), member.getName(), member.getPassword());
        return id;
    }

    @Transactional
    public void delete(Long id) {
        Member member = findById(id);
        memberJpaRepository.delete(member);
    }

	@Transactional
    public Member findById(Long id) {
        return memberJpaRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
    }

    @Transactional
    public Member findByEmail(String email) {
        return (Member) memberJpaRepository.findByEmail(email)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
    }
}

3. Cloudtype 배포

https://app.cloudtype.io/

 

모두의 플랫폼팀, 클라우드타입

클라우드타입은 클라우드 기반 애플리케이션을 빠르게 개발하고 배포할 수 있는 클라우드 애플리케이션 플랫폼입니다.

cloudtype.io

회원가입 후 좌측 배너의 '+' 버튼으로 새 프로젝트를 생성해준다.

파란색 + 버튼을 클릭 후, 본인이 배포하고자 하는 템플릿인 SpringBoot를 선택해주었다.

배포하고자 하는 repo를 선택하면 되는데

이 때 사전작업이 필요하다

 

본인 github repository를 하나 생성해서 내부에 소스코드를 넣어준다

이렇게 디렉토리를 구성하면 되는데, 본인은 디렉토리 구조가 'red_test/privacy/소스코드' 여서 추가설정이 필요했다.

원래는 '레포지토리/소스코드' 이렇게 넣어주면 된다...

어떤 추가설정이 필요했는지는 바로 설명하겠다...

 

어쨌든 배포하고자하는 repository를 선택한 후, 다음과 같은 팝업이 뜬다.

 

java는 프로젝트에 알맞는 jdk version을 설정해주면 된다. 

이 때, mariaDB를 이용했기에 환경변수(Environment variables)를 설정해준다

ㅇ

mariadb이므로 port는 3306, 사용자하고자 하는 db username, pw를 입력해주면 된다.

그리고 배포하면 된다!

 

하지만..

본인은 레포지토리에 바로 소스코드가 있지 않고 privacy서브디렉토리 안에 있기에 서브 디렉토리 옵션을 추가해주었다.

배포가 안 돼서 구글링 후 서브 디렉토리 옵션을 걸어주었다.

그 후 재배포 했더니 성공적으로 배포된다!

 

MariaDB 서버는 다른 백엔드 팀원이 올려놔서 편하게 진행할 수 있었다.

이제 프론트 배포하고 연동하면 된다..😇

 

SSUPOWER 화이팅..!!

 

오류사항이나 지적은 댓글로 남겨주시면 감사하겠습니다!

 

+ 프론트 배포 후 연동 성공!

 

+ 중복 email로 회원가입 시 처리

@PostMapping("/join")
public Long create(@RequestBody Member member) {
    if(validateDuplicateMember(member)) {    //중복회원 검사
        return memberService.save(member);
    }else {
        return null;
    }
}

private boolean validateDuplicateMember(Member member) {
    if(memberJpaRepository.findByEmail(member.getEmail())
            .isPresent()){
        return false;
    }else return true;
}

+ react로 local test를 할 때

    @CrossOrigin(origins = "http://localhost:3000")

    이 필요하다고 한다..

+ Client(front)가 접근가능하도록 접근헤더도 추가해주어야 한다고 한다..

   .exposedHeaders("access-control-allow-origin")

 

728x90
반응형