일기앱 프로젝트 캘린더 기능지원

안민기·2023년 11월 14일

팀으로 진행중인 일기 어플 프로젝트에서 처음으로 복잡한 로직을 구현하는 일이 생겼다.

지금까지는 JPA를 써서 단순한 CRUD만 구현하면 되는 문제였으나 이제는 서비스단에서 로직을 구현해야 할 일이 생겼다.

목적

이런식으로 일기를 쓴 날에 그날의 감정이 이모티콘으로 나오고 이모티콘을 클릭하면 작성했던 일기로 이동한다.

우선 일기 엔티티의 변수(칼럼)들은 다음과 같다
Diary.java (Entity)의 일부

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
       
    private String content;
    private Integer empathy;
    private String emotion;
    private Boolean is_comm;
    private Boolean is_share;
    
    @Column(name = "user_id")
    private Long userId;
    private String author;
    
    @CreatedDate
    @Column(name = "created_at")
    public LocalDateTime CreatedAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    public LocalDateTime updatedAt;
    
    

id는 일기의 고유값, content는 일기의 내용, empathy는 공감 횟수, emotion은 감정, is_comm, is_share은 댓글과 보이기 설정, user_id는 작성한 유저의 고유 값, author은 스프링시큐리티의 인증을 위한 칼럼이다. CreatedAt과 updatedAt은 작성 일시, 수정 일시이다.

이 중 캘린더에서 프론트에 전달해야 할 것은 id(클릭 시 이동을 위해), emotion(감정 이모티콘 표현을 위해) 그리고 CreatedAt의 day 부분이다.

CalenderResponse.java (DTO)

@Setter
@Getter
public class CalendarResponse {
	Long id;
	Integer day;
	String emotion;
	
	public CalendarResponse(Long id, Integer day, String emotion)
	{
		this.id = id;
		this.day = day;
		this.emotion = emotion;
		System.out.println(emotion);
	}
	
	public CalendarResponse(CalendarResponse res)
	{
		this.id = res.getId();
		this.day = res.getDay();
		this.emotion = res.getEmotion();
	}
}

id, day, emotion을 설정하고 내부 로직을 위한 생성자, 그리고 response 시 변환을 위한 생성자를 만들었다.

CalendarInfo.java (DTO)

@Getter
@Setter
public class CalendarInfo {
	private List<Diary> ids;
	private LocalDateTime date;
	
	public CalendarInfo(LocalDateTime date)
	{
		this.date = date;
	}
}

CalendarResponse로 보내주기 전 가공을 위한 DTO를 하나 더 생성했다.

이제 서비스단에서 다음 함수들을 구현했다.

 
    public List<Diary> findByMonth(LocalDateTime date, String author)
    {
    	List<Diary> data = diaryRepository.findByUserId(Long.parseLong(author));
    	List<Diary> result = new ArrayList<Diary>();
    	
    	int i;
    	for(i=0; i<data.size(); i++)
    	{
    		if(data.get(i).getCreatedAt().getMonth() == date.getMonth())
    		{
    			if(data.get(i).getCreatedAt().getYear() == date.getYear())
    			{
    				result.add(data.get(i));
    			}
    		}
    	}
    	return result;
    }

스프링 시큐리티에서 .getName()을 호출할 시 user_id를 string으로 전달하게 해놨다. author 파라미터로 이 값을 받고 PathVariable로 전달된 Date값을 date 파라미터로 전달받는다.

해당 함수는 유저가 전달 받은 Date 값과 같은 연도와 달에 쓴 Diary를 전부 반환해주는 함수이다.

    
    public CalendarInfo setCalendar(LocalDateTime date, String author)
    {
    	CalendarInfo cal = new CalendarInfo(date);
    	List<Diary> calCon = findByMonth(date, author);
    	
    	cal.setIds(calCon);
    	return cal;
    } 

그렇게 반환받은 Diary의 List에서 필요한 정보만 추출하여 CalenderInfo로 반환해주는 함수이다.

   public List<CalendarResponse> getCalendar(CalendarInfo info)
    {
    	List<CalendarResponse> res = new ArrayList<CalendarResponse>();
    	Integer day;
    	String emotion;
    	Long id;
    	
    	int i;
    	for(i=0; i<info.getIds().size(); i++)
    	{
    		day = info.getIds().get(i).getCreatedAt().getDayOfMonth();
    		emotion = info.getIds().get(i).getEmotion();
    		id = info.getIds().get(i).getId();
    		
    		res.add(new CalendarResponse(id, day, emotion));	
    	}
    	return res;
    }
    

마지막으로 CalendarRepsonse의 배열을 통해 찾아낸 달의 필요한 정보를 저장하여 반환하는 함수이다.

CalendarController.java (Controller)

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/calendars")
public class CalendarController {
    private final DiaryService diaryService;

    
    @Operation (summary = "캘린더 정보를 받아오는 기능")
    @GetMapping("/date/{date}")
    public ResponseEntity<List<CalendarResponse>> getCalender(
    		@PathVariable(value="date") @DateTimeFormat(pattern="yyyy-MM-dd'T'HH:mm:ss") LocalDateTime date, Principal principal) {
    	CalendarInfo info = diaryService.setCalendar(date, principal.getName());
    	
    	List<CalendarResponse> res = diaryService.getCalendar(info)
    			.stream()
    			.map(CalendarResponse::new)
    			.toList();
    	
    	return ResponseEntity.ok()
    			.body(res);
    }
}

이제 컨트롤러를 통해 연결해주면 기능 구현이 완료된다. Date 파라미터를 그냥 받으면 오류가 나는데 @DateTimeFormat 어노테이션을 통해 패턴을 미리 지정해두면 받은 값을 정상적으로 불러올 수 있다.

완료.

사실 로직보다는 의문의 오류로 인해 고통을 받았는데 post를 테스트 할 때 createdAt 칼럼이 null로 되어있는 값을 많이 넣어놔서 그 부분에서 오류가 난 것이었다. 개발 시 데이터베이스에 쓰레기 값이 있는지 잘 확인해봐야겠다.

profile
개발 블로그

0개의 댓글