[Project] springboot - schedule 활용한 신고 기능
Categories: Project
📌 개인적인 공간으로 공부를 기록하고 복습하기 위해 사용하는 블로그입니다.
정확하지 않은 정보가 있을 수 있으니 참고바랍니다 :😸
[틀린 내용은 댓글로 남겨주시면 복받으실거에요]
신고기능 구현
게시판이다 보니 스팸이나 욕설 등을 달아 다른 회원들에게 불쾌감을 줄 수 있는 글이나 댓글을 달 수 도 있기 때문에
게시글과 댓글에 신고 기능을 구현하기로 했다.,
기본적으로 내가 생각한 신고의 조건은
- 회원은 자기 자신을 신고할 수 없어야 한다.
- 프론트에서 아예 신고 버튼이 나오지 않게 할 수 있거나
- 백에서 자신을 신고했을 때 예외처리 할 수 있다.
- 이미 신고는 되었으나 신고가 승인 되지 않은 경우
- 무분별한 신고글이 쌓이지 않도록 이미 신고를 당한 컨텐츠는 같은 사유로 신고되었다는 메세지 남기게 하기.
- 이미 한 번 관리자가 승인을 거절했다면 같은 이유로 신고를 할 경우
- 이 게시글에 대한 신고는 이미 거절되었으니 추가 사유가 있다면 다른 사유로 신고해주세요 라고 알리기.
- 신고 승인시에는 게시글은 삭제되고, 사용자는 관리자의 기준에 따라 계정이 정지된다.
1️⃣ 사용자가 신고 버튼을 눌렀을 때
게시글과 댓글에 모두 신고가 가능하므로 게시글 신고 할 때는 댓글을 null을 받고, 댓글 신고에는 게시글을 null로 받도록 구현했다.
- 해당 컨텐츠의 member와 신고한 member가 같을 경우 예외 던지기
-
해당 컨텐츠에 신고 내역 유무와 신고 상태 확인.
- 해당 컨텐츠의 신고 내역 확인
- 해당 컨텐츠의 신고 상태 확인
- 해당 컨텐츠의 신고 내역 확인
- 컨텐츠를 report에 set 하기.
2️⃣ 관리자가 신고 목록을 보고 신고 승인을 눌렀을 때
- 게시글과 댓글 신고로 조건을 나눈 다음에 해당 컨텐츠를 작성한 member는 요청한 일 수만큼 ban 시키고,
해당 컨텐츠는 삭제 되도록 구현하고 report의 상태도 승인되었다고 변경. - 만약 관리자가 거절을 누르거나 해당 컨텐츠가 없다면 report는 거절상태로 변경
- 상기 조건에 부합하지 않는다면 잘못된 요청으로 예외 던지도록 구현했다.
처음에 member상태를 변경할 때 setBanMember 메서드 만들어서 memberStatus와 banexpiration 적용 했는데
어떻게 ban을 풀어줄까 생각하다가 Scheduling을 적용했다.
신고 로직에 대해서도 원래 이렇게 구현하는 것이 맞나 조금 의구심이 드는데,
세상에 다양한 사람들이 많아서 무분별한 신고를 막기 위해서 신고가 거절 된 글이라면 관리자가 확인한 글이니까
신고 거절된 글은 신고를 못 누르게 구현했다…이건 나중에 잘못된 로직이라 생각되면 변경할 예정이다.
계정정지 회원 - Scheduling 활용하기
계정 정지된 회원의 경우 ban 상태를 풀어줘야 하는데 이걸 어떻게 구현할까 하다가 구글링 해보니 자동으로 상태를 변경해 주기 위해서는
- scheduling
- batch
- DB 기반 - 로그인 시도 시에 ban 상태를 확인 후에 로그인을 승인해주는 형태
- 메세지 큐를 활용할 수 있다고 한다.
내가 생각하기에는 실시간으로 정지계정을 풀어 줄 필요가 딱히 없고
일정한 시간 간격으로 여러 계정을 처리하여 확인 할 수 있는 Scheduling이 적합하다고 생각하였고
시스템 리소스도 효율적으로 사용할 수 있어서 Scheduling을 선택하였다.
다만 걸리는 점은 실시간으로 처리를 해줄 수 없다는 것인데
만약 우리 서비스가 우리 삶에 밀접하고 실시간으로 연동되어야 하는 서비스인 카카오톡 같은 것이라면 DB 기반이나 메세지 큐를 선택했을 것 같은데
그런 것은 아니므로 간단하고 효율적으로 구현할 수 있는 Scheduling으로 구현하였다.
SpringStartApplication에 @EnableScheduling 필요
1
2
3
4
5
6
7
8
@EnableScheduling
@SpringBootApplication
public class SpringStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringStartApplication.class, args);
}
}
@scheduled 애너테이션을 메서드에 선언하면 실행 가능
- **실행주기** : cron / fixedDelay / fixedRate 로 설정 가능
- @Scheduled(cron = “ 0 * 1 * * * ”)
- 정해진 시간마다 동작하게 할 수 있다. (예, 매주 월요일 오전 9시에 실행해야 할 경우. )
- 일정이 중요한 작업에 적합하다.
- “*(초) * (분) * (시) * (일) * (월) *(요일)” 순
1 2 3 4 5 6
초 : 0~59 <br> 분 : 0~59 <br> 시 : 0~23 <br> 일 : 1~31 <br> 월 : 1~12 <br> 요일 : 1~7 (1: 월요일 ~ 7: 일요일)
- @Scheduled(fixedDelay= 5000)
- 이전 작업이 완료된 시점부터 일정 시간 후에 다음 작업이 시작됩니다. 작업 간에 일정한 간격을 유지하면서 실행할 때 적합하다,
- fixedDelay= 5000이라고 했을 때는 작업이 완료된 후 5초가 지나면 다음 작업이 수행된다.
- @Scheduled(fixedRate = 43200000)
- 단위 ms
- 정해 놓은 주기로 작동한다.
- Spring 스케줄러의 경우 싱글스레드이기 때문에 @Scheduled 작업이 여러 개 발생시 제 시간에 작동하지 않을 수 있다. 이를 방지 하기 위해서는 멀티스레드로 구현해야 한다.
-
나는 프로젝트에서는 12시간 마다 작동하도록 구현했다. 코드는 아래와 같음.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public void setBanMember(Member member) { Member findMember = findVerifiedMember(member.getMemberId()); findMember.setMemberStatus(Member.MemberStatus.BAN); findMember.setBanExpiration(LocalDateTime.now().plusDays(7)); memberRepository.save(findMember); } @Scheduled(fixedRate = 43200000) //12시간마다 public void manageBanMemberStatus() { List<Member> banMembers = memberRepository.findByMemberStatus(Member.MemberStatus.BAN); for(Member confirmMemberStatus : banMembers) { if(confirmMemberStatus.getBanExpiration() != null && confirmMemberStatus.getBanExpiration().isBefore(LocalDateTime.now())) { confirmMemberStatus.setMemberStatus(Member.MemberStatus.ACTIVE); confirmMemberStatus.setBanExpiration(null); memberRepository.save(confirmMemberStatus); } } }
-
scheduled 애너테이션 있는 메서드는 매개변수를 가질 수 없음.
처음에는 member를 매개변수로 넣으려고 했는데 인텔리제이에서 알아서 막아주었다.
찾아보니 매개변수를 가질 수 없다고 하여 위처럼 신고가 승인되었을 때
memberStatus와 BanExpiration를 변경하는 메서드를 구현했고 (setBanMember 메서드) scheduled 적용한 메서드로 12시간마다 정지 상태 회원의 ban기간을 확인한 다음, 지났다면 active로 변경하게 메서드를 구현하였다.ban 시킨다음 기간이 지났을 때 확인해보면 active 상태로 변경되었고, Ban_Expiration 도 null 로 변경되었다.
Leave a comment