일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- CRUD
- llm연동
- Nan
- selenium
- 브랜치관리전략
- Github action
- rest api
- springframework
- 깃플로우
- 자바스크립트기초
- 자바스크립트
- 개발자튜토리얼
- gitflow
- 백엔드개발
- springboot크롤링
- springboot 크롤링
- restful
- github
- spring
- 모던 자바스크립트
- 회원관리
- 깃허브
- SpringBoot
- modelcontextprotocol
- mcp
- mcpserver
- 네이버 크롤링
- CI/CD
- SQLD
- 스프링부트
Archives
- Today
- Total
JUNEee
[Spring Boot] rest api 스프링부트 회원관리 기능 구현하기! (CRUD) 본문
반응형
CRUD 란?
CRUD 란 Create, Read, Update, Delete 의 앞글자를 딴 개념으로 대부분의 시스템이 데이터를 처리할 때 기본적으로 제공하는 핵심 기능을 의미한다.
본 블로그에서는 CRUD를 각각
- C (Create) : 회원가입
R (Read) : 회원조회
U (Update) : 회원정보 수정
D (Delete) : 회원정보 삭제
로 구현해볼 예정이다.
시작하기 전 준비하기
회원관리 기능을 구현하기 전 사전 준비작업이 필요하다.
먼저 사용할 기술스택은 다음과 같다
- Spring Boot
- MySQL
- Spring JPA
- Spring Security
- Swagger
- 먼저 MySQL, Spring JPA, Spring Security, Swagger 사용을 위해 의존성을 추가해주어야 한다
현재 추가된 의존성은 다음과 같다//build.gradle implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j'
- MySQL 연결
//application.properties #mysql spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/crud spring.datasource.username= spring.datasource.password= spring.jpa.hibernate.ddl-auto=update
- Security 설정 (security를 사용하는 이유는 회원가입 시 패스워드 필드를 해싱하기 위함임)
기본적으로 모든 api 경로를 허용해주었다. 또한 패스워드 필드를 해싱하기 위해 필요한 BCryptPasswordEncoder 객체를 의존성 주입받기 위하여 bean으로 등록해주었다.//SecurityConfig @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .anyRequest().permitAll()); return http.build(); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
- 프로젝트 구조
crud ├── CrudApplication.java // 메인 애플리케이션 클래스 ├── config │ └── SecurityConfig.java // 보안 설정 클래스 ├── controller │ └── Controller.java // 요청을 처리하는 컨트롤러 ├── dto │ ├── FindDto.java // 사용자 조회용 DTO │ ├── LoginDto.java // 로그인용 DTO │ ├── SignUpDto.java // 회원가입용 DTO │ └── UpdateDto.java // 사용자 정보 수정용 DTO ├── entity │ └── UserEntity.java // 사용자 엔티티 클래스 ├── repository │ └── Repository.java // 데이터베이스 접근 인터페이스 └── service └── Service.java
회원 JPA 엔터티 생성
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@Builder
@Table(name ="사용자")
public class UserEntity {
@Id
@Column(length = 255)
private String id;
@Column(length = 255)
private String name;
@Column(length = 255)
private String password;
}
회원 JPA 레파지토리 생성
public interface Repository extends JpaRepository<UserEntity, String> {
boolean existsById(String id);
}
[1] 회원가입 구현
controller
@PostMapping("/signup") public ResponseEntity<?> signUp(@RequestBody SignUpDto signUpDto) { try { String signUpResponse = service.signUp(signUpDto); return ResponseEntity.ok().body(signUpResponse); } catch (RuntimeException e) { return ResponseEntity.badRequest().body(e.getMessage()); } }
Dto
public class SignUpDto { private String id; private String name; private String password; public UserEntity toEntity() { return UserEntity.builder() .id(this.id) .name(this.name) .password(this.password) .build(); } }
Service
public String signUp(SignUpDto signUpDto) { if(repository.existsById(signUpDto.getId())) { log.info("이미 가입된 유저입니다."); throw new RuntimeException("이미 가입된 유저입니다."); } signUpDto.setPassword(hash.encode(signUpDto.getPassword())); repository.save(signUpDto.toEntity()); return "회원가입 성공"; }
DB
[2] 회원조회 구현
controller
@GetMapping("/{id}") public ResponseEntity<?> findById(@PathVariable String id) { System.out.println(id); try { FindDto user = service.findById(id); return ResponseEntity.ok().body(user); } catch (RuntimeException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } } @GetMapping("/all") public ResponseEntity<?> findAll() { List<FindDto> users = service.findAll(); return ResponseEntity.ok().body(users); }
Dto
@Getter @Setter @Builder public class FindDto { private String id; private String name; }
Service
public List<FindDto> findAll() { List<UserEntity> users = repository.findAll(); return users.stream() .map(user -> FindDto.builder() .id(user.getId()) .name(user.getName()) .build()) .toList(); } public FindDto findById(String id) { UserEntity user = repository.findById(id).orElse(null); if(user == null) { log.info("해당 ID의 유저가 없습니다."); throw new RuntimeException("해당 ID의 유저가 없습니다."); } else { log.info("유저 정보 조회 성공"); return FindDto.builder() .id(user.getId()) .name(user.getName()) .build(); } }
[3] 회원수정 구현
- controller
@PatchMapping("/{id}") public ResponseEntity<?> update(@PathVariable String id, @RequestBody UpdateDto updateDto) { try { String updateResponse = service.update(id, updateDto); return ResponseEntity.ok().body(updateResponse); } catch (RuntimeException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } }
- Dto
@Getter @Setter public class UpdateDto { private String name; private String password; }
- Service
public String update(String id, UpdateDto updateDto) { if(!repository.existsById(id)) { log.info("해당 ID의 유저가 없습니다."); throw new RuntimeException("해당 ID의 유저가 없습니다."); } else { UserEntity user = repository.findById(id).orElse(null); user.setName(updateDto.getName()); user.setPassword(hash.encode(updateDto.getPassword())); repository.save(user); return "유저 정보 업데이트 성공"; } }
[4] 회원삭제 구현
- controller
@DeleteMapping("/{id}") public ResponseEntity<?> delete(@PathVariable String id) { try { String deleteResponse = service.delete(id); return ResponseEntity.ok().body(deleteResponse); } catch (RuntimeException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } }
- Dto
@Getter @Setter public class UpdateDto { private String name; private String password; }
- Service
public String update(String id, UpdateDto updateDto) { if(!repository.existsById(id)) { log.info("해당 ID의 유저가 없습니다."); throw new RuntimeException("해당 ID의 유저가 없습니다."); } else { UserEntity user = repository.findById(id).orElse(null); user.setName(updateDto.getName()); user.setPassword(hash.encode(updateDto.getPassword())); repository.save(user); return "유저 정보 업데이트 성공"; } }
[5] 로그인 구현
controller
@PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginDto loginDto) { try { String LoginResponse = service.login(loginDto); return ResponseEntity.ok().body(LoginResponse); } catch (RuntimeException e) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage()); } }
Dto
@Getter @Setter public class LoginDto { private String id; private String password; }
Service
public String login(LoginDto loginDto) { if(!repository.existsById(loginDto.getId())) { log.info("가입된 유저가 없습니다."); throw new RuntimeException("가입된 유저가 없습니다."); } UserEntity user = repository.findById(loginDto.getId()).orElse(null); if(hash.matches(loginDto.getPassword(), user.getPassword())) { log.info("로그인 성공"); return "로그인 성공"; } else { log.info("비밀번호가 일치하지 않습니다."); throw new RuntimeException("비밀번호가 일치하지 않습니다."); } }
구현 결과
api 테스트는 postman 으로 진행하겠다.
- 회원가입
- 회원조회
- 회원정보 수정
- 회원정보 삭제
- 로그인
반응형
'BE > 스프링' 카테고리의 다른 글
[Spring Boot] REST Api 란 무엇일까? (1) | 2025.05.22 |
---|---|
[Spring Boot] Github Actions 를 활용한 CI/CD 파이프라인 구축(개념) (0) | 2025.04.17 |
[Spring Boot] MCP(Model Context Protocol) 기본 개념 및 테스트(1) (0) | 2025.04.04 |
[Spring Boot] selenium 을 사용한 네이버 플레이스 리뷰 크롤링(2) (0) | 2025.03.30 |
[Spring Boot] selenium 을 사용한 네이버 플레이스 리뷰 크롤링(1) (4) | 2025.03.29 |