Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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 31
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[WIL]20240804 멘토링CRUD에 아티클기능을 추가해주세요..? 본문

개발Article

[WIL]20240804 멘토링CRUD에 아티클기능을 추가해주세요..?

최밤빵 2024. 8. 4. 12:12

멘토링CRUD기능을 맡고 프론트헬퍼분이 요구하신사항이 "아티클" 기능을 넣고싶다는거였다. 당연히 못알아들어서 아티클이 뭔지 한참 여쭤보고, 참고하라고 주신 사진보고 해보겠다고 해맑게 말씀을 드렸는데...! 알아보니 웹소켓을 알아야 하는거 같다...! 엄청 어렵다고 듣기도 했고, 진짜 하나도 모르는 부분이라 일단은 GPT에게 부탁을 했다...! 

진환님의 요구사항에 따라 실시간 뉴스피드 같은 느낌의 아티클 (Article) 기능을 구현해보기 위해서 GPT에게 부탁한 코드예시에 대해 개발일지를 작성하려고 한다. 실시간 뉴스피드 기능은 사용자가 작성한 아티클을 다른 사용자에게 보여주고, 최신 업데이트가 즉시 반영될 수 있도록 하는 것을 목표로 하는데, 이러한 기능은 특히 사용자 간의 소셜 인터랙션을 강조하는 웹 애플리케이션에서 매우 중요한 역할을 하고, 사용자 경험을 크게 향상 시킬 수 있다. 실시간 뉴스피드를 구현하기 위해 필요한 핵심 기능과 기술, WebSocket, REST API, Spring Data JPA 등을 활용해야한다...😵‍💫

 

▶ 실시간 뉴스피드같은 아티클 기능 구현

실시간 뉴스피드(Real-Time News Feed) 기능은 사용자들이 작성한 아티클을 즉시 다른 사용자들에게 보여주기 위한 기능이다. 사용자는 글을 작성하고, 해당 글이 실시간으로 다른 사용자들에게 전파되어야 한다. 이를 위해 WebSocket을 이용한 실시간 통신과 REST API를 통한 기본 CRUD(Create, Read, Update, Delete) 작업이 모두 필요하다.

 

▷아티클 엔티티 정의

실시간 뉴스피드 기능의 기본이 되는 부분은 엔티티(Entity). 아티클 엔티티는 데이터베이스 테이블과 매핑되며, 사용자들이 작성한 글의 제목, 내용, 작성자 정보, 작성 시간 등을 포함한다.

package com.example.dischord.article;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.time.LocalDateTime;

@Entity
public class Article {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 생성되는 기본 키 설정
    private Long id;

    private String title; // 아티클의 제목
    private String content; // 아티클의 내용
    private String author; // 아티클 작성자

    private LocalDateTime createdAt; // 아티클 생성 시간
    private LocalDateTime updatedAt; // 아티클 수정 시간
    
}

→ @Entity 애너테이션은 이 클래스가 데이터베이스 테이블로 매핑되는 JPA 엔티티임을 나타낸다.

→ @GeneratedValue(strategy = GenerationType.IDENTITY)는 기본 키 값이 자동으로 생성됨을 의미한다.

→ LocalDateTime을 사용하여 아티클의 생성 및 수정 시간을 관리한다.

 

▷아티클 저장소(Repository) 인터페이스 구현

아티클 데이터를 데이터베이스에 저장하고 조회하기 위해 Spring Data JPA의 JpaRepository 인터페이스를 상속받는 아티클 저장소(Repository)를 구현한다.

package com.example.dischord.article;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {
    // 기본적인 CRUD 메서드가 자동으로 제공된다.
}

→  ArticleRepository는 JpaRepository를 상속받아, 기본적인 CRUD 작업을 수행할 수 있다.필요한 경우 커스텀 쿼리 메서드를 추가하여 다양한 데이터 조회를 지원할 수 있다.

 

▷ 아티클 서비스(Service) 클래스 구현

서비스 계층에서는 비즈니스 로직을 구현한다. 아티클 작성, 조회, 수정, 삭제와 같은 기능을 제공하며, WebSocket을 통해 실시간으로 다른 사용자들에게 변경 사항을 알릴 수 있다.

 
package com.example.dischord.article;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class ArticleService {

    private final ArticleRepository articleRepository;

    public ArticleService(ArticleRepository articleRepository) {
        this.articleRepository = articleRepository;
    }

    public List<Article> getAllArticles() {
        return articleRepository.findAll(); // 모든 아티클 조회
    }

    @Transactional
    public Article createArticle(Article article) {
        article.setCreatedAt(LocalDateTime.now());
        return articleRepository.save(article); // 아티클 생성
    }

    @Transactional
    public Article updateArticle(Long id, Article updatedArticle) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid article ID"));
        article.setTitle(updatedArticle.getTitle());
        article.setContent(updatedArticle.getContent());
        article.setUpdatedAt(LocalDateTime.now());
        return articleRepository.save(article); // 아티클 업데이트
    }

    @Transactional
    public void deleteArticle(Long id) {
        articleRepository.deleteById(id); // 아티클 삭제
    }
}

→ getAllArticles() 메서드는 모든 아티클을 조회한다.

→ createArticle() 메서드는 새로운 아티클을 생성하고 저장한다.

→ updateArticle() 메서드는 기존의 아티클을 수정한다.

→ deleteArticle() 메서드는 특정 아티클을 삭제한다.

 

▷실시간 업데이트를 위한 WebSocket 설정😱

실시간 뉴스피드를 구현하기 위해서는 WebSocket을 사용하여 클라이언트와 서버 간의 실시간 통신을 설정해야 한다.

 
package com.example.dischord.article;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic"); // 메시지 브로커 설정
        config.setApplicationDestinationPrefixes("/app"); // 앱 경로 설정
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS(); // WebSocket 엔드포인트 등록
    }
}

→ @EnableWebSocketMessageBroker는 WebSocket 메시지 브로커를 활성화한다.

→ configureMessageBroker() 메서드는 메시지 브로커를 설정하여, 클라이언트가 /topic으로 시작하는 목적지로 메시지를 구독할 수 있도록 한다.

→ registerStompEndpoints() 메서드는 클라이언트가 연결할 수 있는 WebSocket 엔드포인트를 등록하고, SockJS 폴백 옵션을 설정한다.

 

▷아티클 컨트롤러(Controller) 구현

컨트롤러는 HTTP 요청을 처리하고, REST API를 통해 CRUD 작업을 지원한다. 또한, 아티클이 작성되거나 수정될 때 WebSocket을 통해 실시간으로 다른 클라이언트에게 알릴 수 있다.

package com.example.dischord.article;

import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/articles")
public class ArticleController {

    private final ArticleService articleService;
    private final SimpMessagingTemplate messagingTemplate;

    public ArticleController(ArticleService articleService, SimpMessagingTemplate messagingTemplate) {
        this.articleService = articleService;
        this.messagingTemplate = messagingTemplate;
    }

    @GetMapping
    public List<Article> getAllArticles() {
        return articleService.getAllArticles(); // 모든 아티클 조회
    }

    @PostMapping
    public Article createArticle(@RequestBody Article article) {
        Article createdArticle = articleService.createArticle(article);
        messagingTemplate.convertAndSend("/topic/articles", createdArticle); // 실시간 전송
        return createdArticle;
    }

    @PutMapping("/{id}")
    public Article updateArticle(@PathVariable Long id, @RequestBody Article article) {
        Article updatedArticle = articleService.updateArticle(id, article);
        messagingTemplate.convertAndSend("/topic/articles", updatedArticle); // 실시간 전송
        return updatedArticle;
    }

    @DeleteMapping("/{id}")
    public void deleteArticle(@PathVariable Long id) {
        articleService.deleteArticle(id);
        messagingTemplate.convertAndSend("/topic/articles", "Article Deleted: " + id); // 실시간 삭제 알림
    }
}

→ SimpMessagingTemplate를 사용하여 아티클의 생성, 수정, 삭제 시 /topic/articles로 실시간 메시지를 전송한다.

→ @GetMapping, @PostMapping, @PutMapping, @DeleteMapping으로 CRUD 작업을 처리하는 REST API 엔드포인트를 제공한다.

 

▶정리...

정말 그냥 CRUD 겠거니 하고, 제가 뭐든 공부해서 꼭 요구사항 들어드릴게요😆!! 너무 해맑게 말해버렸는데 웹소켓같은 거대한 거였다니... 팀 프로젝트하면서 너무 공부를 안했다. 시간은 얼마나 걸리던지 상관없다고 하셨지만 작업시간이 느려터진 내가 이걸 해낼 수 있을까 걱정이 된다 ㅠㅠㅠㅠㅠ 하지만...!!! 한다고 했으니까 최대한 공부해서 최대한 구현해 볼 예정이다. 공부하러 가자ㅠ

 

추가 +) 예시로 주신건데.. 나는 정말 간단하게 구현되는 건 줄 알았다 ㅠㅠ 멍충이.. 실시간 뉴스 피드란 얘기듣자마자 솔직하게 모른다고 얘길 했어야했는데...!! 아직 구현하면 되는 단계니까 일단 웹소켓을 열심히 공부해보자...!! 

'개발Article' 카테고리의 다른 글

[TIL]20240806 RestTemplate  (0) 2024.08.06
[TIL]20240805 웹소켓(WebSocket)  (0) 2024.08.05
[TIL]20240803 스프링 시큐리티(Spring Security)  (0) 2024.08.03
[TIL]20240802 Filter  (0) 2024.08.02
[TIL]20240801 로드밸런서  (0) 2024.08.02