Skip to content

Feature/15: 회원 관리 기능 DB와 연동 #17

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

Merged
merged 1 commit into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
Expand Up @@ -9,12 +9,16 @@
@Configuration
@Profile("!test")
public class WebMvcConfig implements WebMvcConfigurer {

/*
Copy link
Collaborator

Choose a reason for hiding this comment

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

사용하지 않는 기능은 주석처리를 하지않고, 지우는 것이 좋은 것 같아요. 나중에 필요하면, 다시 넣으면 되지 않을까요? :-)

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/profile/add", "/login", "/logout");
.excludePathPatterns(
"/profile/add",
"/login", "/logout");
}

*/
}
41 changes: 23 additions & 18 deletions app/src/main/java/org/example/domain/member/MemberController.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
package org.example.domain.member;

import jakarta.validation.Valid;
import org.example.domain.member.dto.MemberEditForm;
import org.example.domain.member.dto.MemberForm;
import lombok.RequiredArgsConstructor;
import org.example.domain.member.dto.request.MemberEditForm;
import org.example.domain.member.dto.request.MemberJoinForm;
import org.example.domain.member.dto.response.MemberDTO;
import org.example.domain.member.entity.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

@RestController
@RequestMapping("/profile")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;

@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}

// 회원가입
x
@PostMapping("/add")
public ResponseEntity<Member> memberAdd(@Valid @RequestBody MemberForm memberForm) {
public ResponseEntity<MemberDTO> memberAdd(@Valid @RequestBody MemberJoinForm memberForm) {
Member savedMember = memberService.addMember(memberForm);
return ResponseEntity.status(201).body(savedMember);
MemberDTO memberDTO = MemberDTO.createMemberDTO(savedMember);
return ResponseEntity.status(201).body(memberDTO);
Copy link
Collaborator

Choose a reason for hiding this comment

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

}

// 사용자 프로필 조회
@GetMapping("/{user_id}")
public ResponseEntity<Member> memberDetails(@PathVariable(value = "user_id") Long user_id) {
Member member = memberService.findMember(user_id);
return ResponseEntity.ok().body(member);
public ResponseEntity<MemberDTO> memberDetails(@PathVariable(value = "user_id") Long userId) {
Member member = memberService.findMember(userId);
MemberDTO memberDTO = MemberDTO.createMemberDTO(member);
return ResponseEntity.ok().body(memberDTO);
}

// 사용자 프로필 수정 폼에 초기 데이터 제공
@GetMapping("/{user_id}/edit")
public ResponseEntity<MemberDTO> memberModify(@PathVariable(value = "user_id") Long userId) {
Member member = memberService.findMember(userId);
MemberDTO memberDTO = MemberDTO.createMemberDTO(member);
return ResponseEntity.ok().body(memberDTO);
}
// 사용자 프로필 수정
@PutMapping("/{user_id}/edit")
public ResponseEntity<Member> memberModify(@PathVariable(value = "user_id") Long user_id, @Valid @RequestBody MemberEditForm memberEditForm) {
public ResponseEntity<MemberDTO> memberModify(@PathVariable(value = "user_id") Long user_id, @Valid @RequestBody MemberEditForm memberEditForm) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

경우에 따라 다를 수도 있지만, 이 컨트롤러에서는 DTO를 하나로 통일하는 것도 괜찮은 아이디어 같습니다.

Member updateMember = memberService.modifyMember(user_id, memberEditForm);
return ResponseEntity.ok().body(updateMember);
MemberDTO memberDTO = MemberDTO.createMemberDTO(updateMember);
return ResponseEntity.ok().body(memberDTO);
}
}
22 changes: 12 additions & 10 deletions app/src/main/java/org/example/domain/member/MemberRepository.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.example.domain.member;


import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.member.entity.Member;
import org.springframework.stereotype.Repository;
Expand All @@ -11,23 +13,27 @@
@Slf4j
@Repository
public class MemberRepository {
private ConcurrentHashMap<Long, Member> store = new ConcurrentHashMap<>();

@PersistenceContext
Copy link
Collaborator

Choose a reason for hiding this comment

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

오 ... 뭔가 JPA를 안쓰는 이유가 특별히 있는 것인가요? 아니면, 아직 JPA는 공부중이라 다른 걸 먼저 시도해 보신건가요?

private EntityManager em;

public Member save(Member member) {
log.debug("save: memberId={}", member.getId());
store.put(member.getId(), member);
em.persist(member);
return member;
}

public Member findById(Long id) {
return store.get(id);
return em.find(Member.class, id);
}

public List<Member> findAll() {
return new ArrayList<>(store.values());
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
return members;
}
public Optional<Member> findByEmail(String email) {
return findAll().stream().filter(m -> m.getEmail().equals(email)).findFirst();
Member member = em.createQuery("select m from Member m where m.email = :email", Member.class)
.setParameter("email", email).getSingleResult();
return Optional.ofNullable(member);
}

public Optional<Member> findByEmailAndPassword(String email, String password) {
Expand All @@ -41,8 +47,4 @@ public Optional<Member> findByEmailAndPassword(String email, String password) {

return Optional.empty();
}

public void clearStore() {
store.clear();
}
}
37 changes: 27 additions & 10 deletions app/src/main/java/org/example/domain/member/MemberService.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
package org.example.domain.member;

import org.example.domain.member.dto.MemberEditForm;
import org.example.domain.member.dto.MemberForm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.language.Language;
import org.example.domain.member.dto.request.MemberEditForm;
import org.example.domain.member.dto.request.MemberJoinForm;
import org.example.domain.member.dto.response.MemberDTO;
import org.example.domain.member.entity.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PutMapping;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Slf4j
public class MemberService {

private final MemberRepository memberRepository;

@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

// 회원가입
public Member addMember(MemberForm memberForm){
return memberRepository.save(Member.createMember(memberForm));
@Transactional
Copy link
Collaborator

Choose a reason for hiding this comment

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

save 할 때도 @transactional이 필요한 것인가요?

public Member addMember(MemberJoinForm memberForm){
Member member = Member.createMember(memberForm);

for(String lang : memberForm.getLearning()) {
Language language = Language.createLanguage(lang);
member.addLearning(language);
}

memberRepository.save(member); // language 도 함께 저장
return member;
}

// 사용자 프로필 조회
Expand All @@ -38,14 +48,21 @@ public Member findMember(Long user_id){

// 사용자 프로필 수정
@PutMapping("/{user_id}/edit")
Copy link
Collaborator

Choose a reason for hiding this comment

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

이 annotation은 여기에 적절하진 않은 것 같네요. :-)

@Transactional
public Member modifyMember(Long user_id, MemberEditForm memberEditForm){

Member member = memberRepository.findById(user_id);

if(member == null) {
throw new RuntimeException("존재하지 않는 사용자입니다.");
}
member.clearLearnings();

for (String lang : memberEditForm.getLearning()) {
Language language = Language.createLanguage(lang);
member.addLearning(language);
}
return member.editMember(memberEditForm);

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.example.domain.member.dto;
package org.example.domain.member.dto.request;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
Expand All @@ -21,7 +21,7 @@ public class MemberEditForm {
@Pattern(
regexp = "^(ko|en|ja|cn|fr|ar|es|ru)$",
message = "허용되지 않은 언어 코드입니다. (ko, en, ja, cn, fr, ar, es, ru만 허용)"
) private String native_lang;
) private String nativeLang;

@Size(min = 1, max = 5, message = "학습 언어는 1~5개까지 선택 가능합니다.") // 리스트 전체에 대한 검증
private List<@Pattern(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.example.domain.member.dto;
package org.example.domain.member.dto.request;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
Expand All @@ -11,7 +11,7 @@

@Data
@Builder
public class MemberForm {
public class MemberJoinForm {

@NotBlank(message = "이메일은 반드시 입력해야 합니다.")
@Email(message = "유효한 이메일 형식이 아닙니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.example.domain.member.dto.response;

import lombok.Builder;
import lombok.Data;
import org.example.domain.language.Language;
import org.example.domain.member.entity.Member;

import java.util.List;

@Data
@Builder
public class MemberDTO {
private Long id;
private String email;
private String username;
private String nationality;
private String nativeLang;
private String introduction;
private List<String> learnings;
private int follower;
private int following;
private int point;

public static MemberDTO createMemberDTO(Member member) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

MemberDTO를 생성하는 방법은 createMemberDTO인가요? Builder인가요?

List<Language> learnings = member.getLearnings();
List<String> languages = learnings.stream().map(Language::getLanguage).toList();

return MemberDTO.builder()
.id(member.getId())
.email(member.getEmail())
.username(member.getUsername())
.nationality(member.getNationality())
.nativeLang(member.getNativeLang())
.introduction(member.getIntroduction())
.learnings(languages)
.follower(member.getFollower())
.following(member.getFollowing())
.point(member.getPoint())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.example.domain.question.dto.request.CommentForm;
import org.example.domain.question.dto.request.QuestionCreateForm;
import org.example.domain.question.dto.request.QuestionEditForm;
import org.example.domain.question.entity.Comment;
import org.example.domain.comment.Comment;
import org.example.domain.question.entity.Question;
import org.example.domain.session.SessionConst;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@
import org.example.domain.question.dto.request.CommentForm;
import org.example.domain.question.dto.request.QuestionCreateForm;
import org.example.domain.question.dto.request.QuestionEditForm;
import org.example.domain.question.entity.Comment;
import org.example.domain.comment.Comment;
import org.example.domain.question.entity.Question;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

import static org.example.domain.question.entity.Comment.*;
import static org.example.domain.comment.Comment.*;

@Slf4j
@Service
Expand Down
1 change: 1 addition & 0 deletions app/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ spring:
jpa:
hibernate:
ddl-auto: update
show-sql: true
database-platform: org.hibernate.dialect.MySQLDialect
server:
port: 8081
Expand Down
Loading
Loading