Spring Boot와 MongoDB를 공부하기 위해 사이드 프로젝트를 시작하려고 마음먹은 지 오래되었지만 막상 혼자서 공부하려니 너무 막연하고 주제도 못 정하고 있었습니다. 때문에 모든 사이트의 기본인 회원 관련 API부터 구현해보기로 마음먹고 첫발을 내딛습니다.
[기술 스택]
- Gradle 7.4.2
- Spring Boot 2.7.1
- openJDK 18.0.1.1
- mongoDB 4.4
(본문에서 다루는 모든 패키지는 com.kimmingyu.aws 하위에 선언하고 있기 때문에 본인의 프로젝트에 맞게 수정합니다.)
1. Gradle 필요 의존성 주입
- 아래 2개의 dependencies는 필수로 추가합니다.
- modelmapper를 사용하여 Object에서 Obejct로 값을 옮길때 번거롭게 getter, setter 사용지 않게 해 줍니다.
dependencies {
implementation group: 'org.modelmapper', name: 'modelmapper', version: '2.3.8'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
}
2. Member Model 생성
- model 패키지를 생성하고 하위에 Member Class를 만듭니다
- 위에서 추가한 mongodb starter를 활용하여 Document로 지정합니다.
package com.kimmingyu.aws.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "members")
public class Member {
@Id
private String id;
private String name;
private String email;
private String password;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Member{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", email='" + email + '\'' +
", password=" + password +
", phone=" + phone +
'}';
}
}
3. MemberDTO 생성하기
- dto 패키지를 만든 후, 하위에 MemberDTO Class를 생성합니다.
package com.kimmingyu.aws.dto;
public class MemberDTO {
private String id;
private String name;
private String email;
private String password;
private String phone;
public MemberDTO() {
}
public MemberDTO(String id, String name, String email, String password, String phone) {
this.id = id;
this.name = name;
this.email = email;
this.password = password;
this.phone = phone;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
4. MemberRepository Interface 생성하기
- repository 패키지를 생성한 후, 하위에 MongoRepository를 상속받은 MemberRepository Interface를 생성합니다.
package com.kimmingyu.aws.repository;
import com.kimmingyu.aws.model.Member;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface MemberRepository extends MongoRepository<Member, String> {
Member findByEmail(String email);
Member findByPhone(String phone);
List<Member> findAllByOrderByNameDesc();
}
5. MemberService Interface 생성하기
- Member관련 Service를 제공하기 위한 사전 명세서를 작성합니다.
- 꼭 구현해야 하는 기능들 (CRUD) 위주로 서술합니다.
package com.kimmingyu.aws.service;
import com.kimmingyu.aws.model.Member;
import java.util.List;
public interface MemberService {
List<Member> findAll();
Member findByEmail(String email);
Member findByPhone(String phone);
List<Member> findAllByOrderByNameDesc();
Member saveOrUpdateMember(Member member);
void deleteMemberById(String id);
}
6. MemberServiceImpl Class 생성하기
- 위의 MemberService Interface를 구현하여 정말 실제로 사용할 Service Class를 생성합니다.
- 위에서 명세만 하였던 기능들을 실제로 구현합니다.
package com.kimmingyu.aws.service.impl;
import com.kimmingyu.aws.model.Member;
import com.kimmingyu.aws.repository.MemberRepository;
import com.kimmingyu.aws.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberRepository memberRepository;
@Override
public List<Member> findAll() {
return memberRepository.findAll();
}
@Override
public Member findByEmail(String email) {
return memberRepository.findByEmail(email);
}
@Override
public Member findByPhone(String phone) {
return memberRepository.findByPhone(phone);
}
@Override
public List<Member> findAllByOrderByNameDesc() {
return memberRepository.findAllByOrderByNameDesc();
}
@Override
public Member saveOrUpdateMember(Member member) {
return memberRepository.save(member);
}
@Override
public void deleteMemberById(String id) {
memberRepository.deleteById(id);
}
}
7. ObjectMapperUtils Class 생성하기
- service 패키지 하위에 util패키지를 만듭니다. (각자 패키지 관리하는 형식으로 알아서 하시면 됩니다.)
- ModelMapper를 활용하여 각 객체 간 유연하게 값을 주고받을 수 있는 ObjectMapperUtils Class를 생성합니다.
package com.kimmingyu.aws.service.util;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class ObjectMapperUtils {
private static final ModelMapper modelMapper;
static {
modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
}
private ObjectMapperUtils() {
}
public static <D, T> D map(final T entity, Class<D> outClass) {
return modelMapper.map(entity, outClass);
}
public static <D, T> List<D> mapAll(final Collection<T> entityList, Class<D> outCLass) {
return entityList.stream()
.map(entity -> map(entity, outCLass))
.collect(Collectors.toList());
}
public static <S, D> D map(final S source, D destination) {
modelMapper.map(source, destination);
return destination;
}
}
8. MemberController 생성하기
- RestController 어노테이션을 사용하여 실제 Member를 컨트롤할 수 있는 Controller를 생성합니다.
- 위에서 생성 및 구현하였던 모든 기능들을 사용하여 사용 가능한 API를 만듭니다.
package com.kimmingyu.aws.controller;
import com.kimmingyu.aws.dto.MemberDTO;
import com.kimmingyu.aws.model.Member;
import com.kimmingyu.aws.service.impl.MemberServiceImpl;
import com.kimmingyu.aws.service.util.ObjectMapperUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/members")
public class MemberController {
@Autowired
private MemberServiceImpl memberService;
@GetMapping(value = "/")
public List<MemberDTO> getAllMembers() {
return ObjectMapperUtils.mapAll(memberService.findAll(), MemberDTO.class);
}
@GetMapping(value = "/byEmail/{email}")
public MemberDTO getMemberByEmail(@PathVariable("email") String email) {
return ObjectMapperUtils.map(memberService.findByEmail(email),MemberDTO.class);
}
@GetMapping(value = "/byPhone/{phone}")
public MemberDTO getMemberByPhone(@PathVariable("phone") String phone) {
return ObjectMapperUtils.map(memberService.findByPhone(phone),MemberDTO.class);
}
@GetMapping(value = "/orderByName")
public List<MemberDTO> findAllByOrderByNameDesc() {
return ObjectMapperUtils.mapAll(memberService.findAllByOrderByNameDesc(),MemberDTO.class);
}
@PostMapping(value = "/save")
public ResponseEntity<?> saveOrUpdateMember(@RequestBody MemberDTO memberDTO) {
// 이메일 체크
Member member = memberService.findByEmail(memberDTO.getEmail());
String responseMessage = "Member added success";
if(member != null && member.getId() != null && member.getId().length() > 0) {
responseMessage = "This Email already Exist";
} else {
memberService.saveOrUpdateMember(ObjectMapperUtils.map(memberDTO, Member.class));
}
return new ResponseEntity(responseMessage, HttpStatus.OK);
}
@PostMapping(value = "/delete/{email}")
public ResponseEntity<?> deleteMemberByEmail(@PathVariable String email) {
// 이메일 중복 체크
Member member = memberService.findByEmail(email);
String responseMessage = "Member Deleted success";
if(member != null && member.getId() != null && member.getId().length() > 0) {
memberService.deleteMemberById(memberService.findByEmail(email).getId());
} else {
responseMessage = "This Email Dose Not exist our Member List";
}
return new ResponseEntity(responseMessage, HttpStatus.OK);
}
}
9. PostMan을 사용하여 TEST 하기
- 본인은 API 개발할 때, PostMan을 주로 사용합니다.
- localhost:8080/members/ URL로 접근합니다.
- 멤버 추가 : [POST] localhost:8080/members/save
- 멤버 조회 :
- [GET] localhost:8080/members/
- [GET] localhost:8080/members/orderByName
'Spring Boot' 카테고리의 다른 글
RabbitMQ 활용하기 (8) | 2024.09.30 |
---|---|
스프링에서 TransactionManager에 대한 상세한 이해하기 (2) | 2024.09.24 |
Spring Boot에서 @Transactional 어노테이션이 작동하지 않을 때 해결 방법 (0) | 2024.09.24 |
Spring Boot에서 MongoDB 인덱스 자동증가 (autoincrement) 기능 구현하기 (0) | 2022.07.20 |
IntelliJ에서 Spring Boot 프로젝트 생성 및 실행하기 (1) | 2022.06.16 |