Skip to content

Commit 775b49d

Browse files
committed
[REFACTOR] Service, Impl 구조로 변경 및 ResponseEntity로 감싸는 거 제거
1 parent 67e6ab3 commit 775b49d

4 files changed

Lines changed: 241 additions & 242 deletions

File tree

‎src/main/java/fitfit/domain/member/controller/MemberRestController.java‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import fitfit.domain.member.dto.MemberRequestDTO;
66
import fitfit.domain.member.dto.MemberResponseDTO;
77
import fitfit.domain.member.entity.Member;
8-
import fitfit.domain.member.service.MemberCommandUseCase;
8+
import fitfit.domain.member.service.MemberCommandService;
99
import fitfit.domain.token.service.MemberTokenCommandUseCase;
1010
import fitfit.global.apiPayload.ApiResponse;
1111
import fitfit.global.enums.Provider;
@@ -17,7 +17,6 @@
1717
import jakarta.validation.Valid;
1818
import lombok.RequiredArgsConstructor;
1919
import lombok.extern.slf4j.Slf4j;
20-
import org.springframework.http.ResponseEntity;
2120
import org.springframework.web.bind.annotation.*;
2221

2322
@Slf4j
@@ -27,7 +26,7 @@
2726
@Tag(name = "Member", description = "회원 관련 API")
2827
public class MemberRestController {
2928

30-
private final MemberCommandUseCase memberCommandUseCase;
29+
private final MemberCommandService memberCommandService;
3130
private final MemberTokenCommandUseCase memberTokenService;
3231
private final KakaoOidcService kakaoOidcService;
3332

@@ -39,15 +38,15 @@ public class MemberRestController {
3938
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "유효하지 않은 ID Token 입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
4039
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "카카오 토큰 검증 도중 에러 발생", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
4140
})
42-
public ResponseEntity<ApiResponse<MemberResponseDTO.KkoOAuth2LoginResponse>> kkoOAuth2Login (@Valid @RequestBody MemberRequestDTO.KkoOAuth2LoginRequest request) {
41+
public ApiResponse<MemberResponseDTO.KkoOAuth2LoginResponse> kkoOAuth2Login (@Valid @RequestBody MemberRequestDTO.KkoOAuth2LoginRequest request) {
4342
// id_token 검증 후 멤버 데이터 추출
4443
MemberDataDTO.MemberData kakaoMemberData = kakaoOidcService.verifyAndParseIdToken(request);
4544

4645
// id_token 에서 추출한 데이터를 통해 멤버 조회 OR 생성
47-
Member findOrCreateMember = memberCommandUseCase.findOrCreateMember(kakaoMemberData, Provider.KAKAO);
46+
Member findOrCreateMember = memberCommandService.findOrCreateMember(kakaoMemberData, Provider.KAKAO);
4847

4948
// 토큰 생성 및 응답
50-
return ResponseEntity.ok(ApiResponse.onSuccess(memberTokenService.generateKkoLoginToken(findOrCreateMember)));
49+
return ApiResponse.onSuccess(memberTokenService.generateKkoLoginToken(findOrCreateMember));
5150
}
5251

5352
@PostMapping("/agreements")
@@ -61,10 +60,10 @@ public ResponseEntity<ApiResponse<MemberResponseDTO.KkoOAuth2LoginResponse>> kko
6160
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "존재하지 않는 약관입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
6261
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "필수 약관에 동의하지 않았습니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
6362
})
64-
public ResponseEntity<ApiResponse<MemberResponseDTO.TermAgreementResponse>> termAgreement(
63+
public ApiResponse<MemberResponseDTO.TermAgreementResponse> termAgreement(
6564
@RequestHeader(value = "Authorization", required = false) String authorization,
6665
@Valid @RequestBody MemberRequestDTO.TermAgreementRequest request) {
67-
return ResponseEntity.ok(ApiResponse.onSuccess(memberCommandUseCase.termAgreement(authorization, request)));
66+
return ApiResponse.onSuccess(memberCommandService.termAgreement(authorization, request));
6867
}
6968

7069
@PatchMapping("/signup")
@@ -77,10 +76,10 @@ public ResponseEntity<ApiResponse<MemberResponseDTO.TermAgreementResponse>> term
7776
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "존재하지 않는 회원입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
7877
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "회원 필수 정보가 누락되었습니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
7978
})
80-
public ResponseEntity<ApiResponse<MemberResponseDTO.MemberSignupResponse>> signup(
79+
public ApiResponse<MemberResponseDTO.MemberSignupResponse> signup(
8180
@RequestHeader(value = "Authorization", required = false) String authorization,
8281
@Valid @RequestBody MemberRequestDTO.MemberSignupRequest request) {
83-
return ResponseEntity.ok(ApiResponse.onSuccess(memberCommandUseCase.memberSignup(authorization, request)));
82+
return ApiResponse.onSuccess(memberCommandService.memberSignup(authorization, request));
8483
}
8584

8685
@PostMapping("/nickname/check")
@@ -90,9 +89,9 @@ public ResponseEntity<ApiResponse<MemberResponseDTO.MemberSignupResponse>> signu
9089
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "Bad Request, 잘못된 요청 형식", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
9190
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "409", description = "이미 사용 중인 닉네임입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
9291
})
93-
public ResponseEntity<ApiResponse<String>> checkNickname(@Valid @RequestBody MemberRequestDTO.NicknameCheckRequest request) {
94-
memberCommandUseCase.checkNickname(request.getNickname());
95-
return ResponseEntity.ok(ApiResponse.onSuccess("사용 가능한 닉네임입니다."));
92+
public ApiResponse<String> checkNickname(@Valid @RequestBody MemberRequestDTO.NicknameCheckRequest request) {
93+
memberCommandService.checkNickname(request.getNickname());
94+
return ApiResponse.onSuccess("사용 가능한 닉네임입니다.");
9695
}
9796
}
9897

Lines changed: 5 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -1,224 +1,15 @@
11
package fitfit.domain.member.service;
22

3-
import fitfit.domain.member.converter.MemberConverter;
43
import fitfit.domain.member.dto.MemberDataDTO;
54
import fitfit.domain.member.dto.MemberRequestDTO;
65
import fitfit.domain.member.dto.MemberResponseDTO;
76
import fitfit.domain.member.entity.Member;
8-
import fitfit.domain.member.mapping.MemberTerm;
9-
import fitfit.domain.member.repository.MemberRepository;
10-
import fitfit.domain.member.repository.MemberTermRepository;
11-
import fitfit.domain.term.entity.Term;
12-
import fitfit.domain.term.repository.TermRepository;
13-
import fitfit.domain.token.provider.JwtProvider;
14-
import fitfit.domain.token.repository.MemberTokenRepository;
15-
import fitfit.global.apiPayload.code.status.ErrorStatus;
16-
import fitfit.global.apiPayload.exception.handler.MemberHandler;
17-
import fitfit.global.apiPayload.exception.handler.TermHandler;
18-
import fitfit.global.enums.MemberStatus;
197
import fitfit.global.enums.Provider;
20-
import lombok.RequiredArgsConstructor;
21-
import lombok.extern.slf4j.Slf4j;
22-
import org.springframework.stereotype.Service;
23-
import org.springframework.transaction.annotation.Transactional;
248

25-
import java.util.List;
26-
27-
28-
@Slf4j
29-
@Service
30-
@RequiredArgsConstructor
31-
public class MemberCommandService implements MemberCommandUseCase{
32-
33-
private final MemberRepository memberRepository;
34-
private final JwtProvider jwtProvider;
35-
private final MemberTokenRepository memberTokenRepository;
36-
private final MemberTermRepository memberTermRepository;
37-
private final TermRepository termRepository;
38-
39-
private static final String DEFAULT_BODY_IMG_URL = "https://fitfit-profile-img.s3.ap-northeast-2.amazonaws.com/default_body_img.jpg";
40-
41-
@Override
42-
@Transactional
43-
public Member findOrCreateMember(MemberDataDTO.MemberData memberData, Provider provider) {
44-
return memberRepository.findByProviderId(memberData.getSub())
45-
.orElseGet(() -> {
46-
// 새 멤버 생성
47-
Member createdMember = memberRepository.save(MemberConverter.toMember(memberData, provider));
48-
49-
return createdMember;
50-
});
51-
}
52-
53-
@Override
54-
@Transactional
55-
public MemberResponseDTO.TermAgreementResponse termAgreement(String authorization, MemberRequestDTO.TermAgreementRequest request) {
56-
// JWT 토큰 검증 및 멤버 ID 추출
57-
Long memberId = jwtProvider.getMemberIdAndValidateToken(authorization);
58-
59-
// 회원 조회
60-
Member findMember = memberRepository.findById(memberId)
61-
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
62-
63-
// 약관 동의 처리
64-
processTermAgreement(findMember, request);
65-
66-
// 회원 상태 AGREE로 변경
67-
findMember.updateStatus(MemberStatus.AGREE);
68-
memberRepository.save(findMember);
69-
70-
// 응답 반환
71-
return MemberConverter.toTermAgreementResponse(findMember);
72-
}
73-
74-
/**
75-
* 약관 동의 처리를 담당하는 메서드
76-
*/
77-
private void processTermAgreement(Member member, MemberRequestDTO.TermAgreementRequest request) {
78-
List<Long> agreeTermIdList = request.getAgreeTermIdList();
79-
List<Long> disagreeTermIdList = request.getDisagreeTermIdList();
80-
81-
// 필수 약관 동의 검증
82-
if (!validateRequiredTerms(agreeTermIdList)) {
83-
throw new TermHandler(ErrorStatus.REQUIRED_TERM_NOT_AGREED);
84-
}
85-
86-
// 동의한 약관 처리
87-
processAgreedTerms(member, agreeTermIdList);
88-
89-
// 미동의한 약관 처리
90-
processDisagreedTerms(member, disagreeTermIdList);
91-
}
92-
// 필수 약관 동의 여부 검증
93-
private boolean validateRequiredTerms(List<Long> agreeTermIdList) {
94-
if (agreeTermIdList == null) return false;
95-
List<Term> requiredTerms = termRepository.findByIsRequiredTrue();
96-
for (Term term : requiredTerms) {
97-
if (!agreeTermIdList.contains(term.getId())) {
98-
return false;
99-
}
100-
}
101-
return true;
102-
}
103-
104-
/**
105-
* 동의한 약관들을 처리하는 메서드
106-
*/
107-
private void processAgreedTerms(Member member, List<Long> agreeTermIdList) {
108-
for (Long termId : agreeTermIdList) {
109-
Term term = getTermOrThrow(termId);
110-
updateMemberTermAgreement(member, term, true);
111-
}
112-
}
113-
114-
/**
115-
* 미동의한 약관들을 처리하는 메서드
116-
*/
117-
private void processDisagreedTerms(Member member, List<Long> disagreeTermIdList) {
118-
// null 처리
119-
if (disagreeTermIdList == null) return;
120-
for (Long termId : disagreeTermIdList) {
121-
Term term = getTermOrThrow(termId);
122-
updateMemberTermAgreement(member, term, false);
123-
}
124-
}
125-
126-
/**
127-
* 약관을 조회하거나 예외를 발생시키는 메서드
128-
*/
129-
private Term getTermOrThrow(Long termId) {
130-
return termRepository.findById(termId)
131-
.orElseThrow(() -> new TermHandler(ErrorStatus.TERM_NOT_FOUND));
132-
}
133-
134-
/**
135-
* 멤버-약관 동의 상태를 업데이트하는 메서드
136-
*/
137-
private void updateMemberTermAgreement(Member member, Term term, boolean isAgree) {
138-
memberTermRepository.findByMemberAndTerm(member, term)
139-
.ifPresentOrElse(
140-
mt -> mt.updateIsAgree(isAgree),
141-
() -> {
142-
MemberTerm newMemberTerm = MemberConverter.toMemberTerm(member, term, isAgree);
143-
memberTermRepository.save(newMemberTerm);
144-
}
145-
);
146-
}
147-
148-
@Override
149-
@Transactional
150-
public MemberResponseDTO.MemberSignupResponse memberSignup(String authorization, MemberRequestDTO.MemberSignupRequest request) {
151-
// JWT 토큰 검증 및 멤버 ID 추출
152-
Long memberId = jwtProvider.getMemberIdAndValidateToken(authorization);
153-
154-
// 회원 조회
155-
Member findMember = memberRepository.findById(memberId)
156-
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
157-
158-
// 회원가입 처리
159-
processMemberSignup(findMember, request);
160-
161-
// 응답 반환
162-
return MemberConverter.toMemberSignupResponse(findMember);
163-
}
164-
165-
/**
166-
* 회원가입 처리를 담당하는 메서드
167-
* 단일책임원칙에 따라 회원가입 로직을 분리
168-
*/
169-
private void processMemberSignup(Member member, MemberRequestDTO.MemberSignupRequest request) {
170-
// 필수 추가 정보 검증
171-
if (!validateAdditionalInfo(request)) {
172-
throw new MemberHandler(ErrorStatus.INVALID_MEMBER_INFO);
173-
}
174-
175-
// 추가 정보 저장
176-
updateMemberInfo(member, request);
177-
178-
// 회원 상태 ACTIVE로 변경
179-
member.updateStatus(MemberStatus.ACTIVE);
180-
memberRepository.save(member);
181-
}
182-
183-
// 추가 정보 필수 입력값 검증
184-
private boolean validateAdditionalInfo(MemberRequestDTO.MemberSignupRequest request) {
185-
return request.getNickname() != null &&
186-
request.getName() != null &&
187-
request.getHeight() != null &&
188-
request.getWeight() != null &&
189-
request.getPhoneNumber() != null &&
190-
request.getGender() != null &&
191-
request.getBirth() != null;
192-
}
193-
194-
@Override
195-
@Transactional(readOnly = true)
196-
public void checkNickname(String nickname) {
197-
if (memberRepository.existsByNickname(nickname)) {
198-
throw new MemberHandler(ErrorStatus.NICKNAME_ALREADY_EXISTS);
199-
}
200-
}
201-
202-
/**
203-
* 회원 정보를 업데이트하는 메서드
204-
*/
205-
private void updateMemberInfo(Member member, MemberRequestDTO.MemberSignupRequest request) {
206-
member.updateNickname(request.getNickname());
207-
member.updateName(request.getName());
208-
member.updateWeight(request.getWeight());
209-
member.updateHeight(request.getHeight());
210-
member.updatePhoneNumber(request.getPhoneNumber());
211-
member.updateBirth(request.getBirth());
212-
member.updateGender(request.getGender());
213-
if (request.getStyleList() != null) {
214-
member.updatePreferredStyle(request.getStyleList());
215-
}
216-
if (request.getFullBodyImgUrl() != null) {
217-
member.updateFullBodyImgUrl(request.getFullBodyImgUrl());
218-
} else {
219-
member.updateFullBodyImgUrl(DEFAULT_BODY_IMG_URL);
220-
}
221-
222-
}
9+
public interface MemberCommandService {
10+
Member findOrCreateMember(MemberDataDTO.MemberData memberData, Provider provider);
11+
MemberResponseDTO.TermAgreementResponse termAgreement(String authorization, MemberRequestDTO.TermAgreementRequest request);
12+
MemberResponseDTO.MemberSignupResponse memberSignup(String authorization, MemberRequestDTO.MemberSignupRequest request);
22313

14+
void checkNickname(String nickname);
22415
}

0 commit comments

Comments
 (0)