Skip to content

20250123-SSG/final-yesul

Repository files navigation

스크린샷

🍶 Yesul - 우리의 전통주를 소개하고 추천하는 플랫폼

AI 기반 맞춤형 추천을 통해 전통주를 접할 수 있는 플랫폼

📋 서비스 소개

Yesul은 전통주의 가치를 소개하고 소통할 수 있는 AI 기반 커뮤니티 플랫폼입니다. AI 기반 맞춤형 추천을 통해 전통주를 접하고, 사람들과 여러 정보를 공유하고 소통할 수 있는 공간을 만들어갑니다.

💡 핵심 가치

  • 🎯 개인화된 접근: AI가 사용자 취향을 반영해 전통주와의 첫 만남을 자연스럽게 연결
  • 🔒 안전한 환경: 2FA 기반 인증으로 보안성을 강화한 사용자 보호
  • 📱 간편한 사용: 직관적인 UI/UX로 모든 연령대가 쉽게 이용 가능
  • 🧩 다양한 기능 제공: 커뮤니티, 1:1 문의 등 소통 중심의 종합 서비스 제공

✨ 주요 기능

🤖 AI 기반 맞춤형 추천 시스템

  • Naver ClovaX: AI기반 개인 맞춤형 술 추천 제공
  • Role Prompting, CoT Prompting기법: Prompting 기법을 이용한 성능 향상
  • 여행지 추천: 술 추천과 질문을 기반으로 한 여행지 추천 기능까지 제공

💬 소통 중심의 종합 서비스

  • 3가지 종류의 커뮤니티: 레시피,정보,자유 게시판을 통한 다양한 술 정보 습득 및 소통 가능
  • 1:1 문의: 관리자와의 실시간 채팅을 통한 즉각적인 피드백 반영
  • 실시간 알림: 실시간 알림을 통한 사용자간 원활한 상호작용 가능

🛠️ 효율적인 운영을 위한 관리자 시스템

  • 실시간 방문자/접속자 통계: Redis를 활용한 실시간 사용자 트래픽 모니터링
  • 관리자 로그인 기록 관리: 관리자 활동 이력을 기록하여 보안성과 운영 투명성 강화
  • 서비스 운영 모니터링: 사용자 활동과 서비스 흐름을 실시간으로 확인할 수 있는 대시보드 제공
  • 1:1 문의 응대: 관리자 페이지 내 실시간 채팅 기능을 통해 빠르고 효율적인 사용자 대응 가능

🔐 간편한 인증

  • Kakao, Naver로그인: 복잡한 회원가입 없이 간편 시작
  • 2FA를 이용한 강력한 보안: Google T-OTP를 통한 2차 보안 기능 제공
  • 이메일: 실제 가입하려는 유저의 메일 소유여부 확인으로 보안강화

👥 팀원 소개

Team 🦕주락이들 - SSG I&C 자바 기반 개발자 양성과정

Image
이승주
Team Lead, Full Stack Developer
📧 GitHub
1:1 문의 채팅
알림 기능
프로젝트 세팅 및 설계
Image
대태호
Full Stack Developer
📧 GitHub
회원가입 및 로그인
소셜로그인 및 메일 발송
erd 설계
Image
이가영
Full Stack Developer
📧 GitHub
어드민 페이지 개발
실시간 모니터링 기능
OTP 보안 인증
Image
정인용
Full Stack Developer
📧 GitHub
AI기반 추천 시스템
메인 페이지 개발
인프라 구축
Image
황정연
Full Stack Developer
📧 GitHub
커뮤니티 기능
댓글 및 좋아요
포인트 기능

🛠️ 기술 스택

🖥️ Frontend

HTML5 CSS3 JavaScript Thymeleaf

⚙️ Backend

Java Spring Boot JPA QueryDSL MySQL Redis Swagger

☁️ Infra

Naver Cloud Docker Nginx GitHub Actions

🧠 AI API

Naver Clova

🧰 ETC

GitHub Notion 2FA Tool IntelliJ IDEA Slack ERDCloud

☁️ 서버 아키텍처

스크린샷

🤝 협업 방식

  • Agile development
    • 매일 Daily ScrumDaily Review를 통해 주기적으로 병합하고,
    • 진행상황과 에러를 빠르게 공유하고 인지함

🗓️ 오전 데일리 스크럼 및 오후 리뷰

💬 데일리 스크럼 예시

🔀 브랜치 전략 및 코드 컨벤션

📌 Branch & Issue 네이밍 규칙

타입 (Type) 설명 브랜치 예시
feat 새로운 기능 추가 feature/1-add-login-function
fix 버그 수정 fix/46-correct-typo
refactor 코드 리팩토링 refactor/789-update-naming-convention
docs 문서 수정 docs/125-update-readme
chore 기타 변경 사항 chore/345-cleanup-code

✅ 이슈 작성 기준

  • 하루 단위로 작업 가능한 수준으로 작성
    예: 로그인 UI 구현, 커뮤니티 작성 기능 추가, 오류 메시지 개선 등

✅ 이슈 상태에 따른 PR 전략

  • 세부내용이 정리된 이슈 → 브랜치 생성 후 PR
  • 미완성 이슈 → 브랜치에서 작업 후 후속 이슈/PR 처리

💬 커밋 메시지 컨벤션

타입 설명
feat 새로운 기능 추가
fix 버그 수정
refactor 코드 리팩토링 (기능 변화 없음)
docs 문서 수정 (README 등)
chore 빌드 업무, 패키지 매니저 설정 등 기타 수정
config 설정 파일 수정

🧑‍💻 코드 컨벤션

적절한 필드 네이밍messageContext, messageType  도메인 관점에서 직관적인 이름Builder 패턴 + protected 생성자불변성 유지  객체 생성 제어BaseTimeEntity 상속createdAt, updatedAt 공통 관리에 적절한 선택

@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Message extends BaseTimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    @Column(name = "sender_type", nullable = false)
    private Type senderType;

    @Column(name = "message_context",length = 5000, nullable = false)
    private String messageContext;

    @Enumerated(EnumType.STRING)
    @Column(name = "message_type", nullable = false, columnDefinition = "TEXT")
    private MessageType messageType;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "chatRoom_id", nullable = false)
    private ChatRoom chatRoom;

}
좋은 예시@Tag, @Operation으로 Swagger 문서화를 통한 API 명세 관리View 기반의 반환REST가 아닌 HTML 렌더링에 맞게 Model 사용명확한 역할 분리ChatRoomService는 채팅방 조회만 책임, View 로직과 분리됨
@Tag(name = "관리자 채팅방", description = "관리자 채팅방 관련 API")
@Controller
@RequestMapping("/admin/chatroom")
@RequiredArgsConstructor
public class AdminChatRoomController {

    private final ChatRoomService chatRoomService;
    private final MessageService messageService;

    @GetMapping
    @Operation(summary = "관리자 기준 채팅방 목록 조회", description = "관리자가 참여하고 있는 채팅방 목록을 조회합니다.")
    public String getAdminChatRooms(
            @RequestParam(required = false) Long cursor,
            @RequestParam(defaultValue = "8") int size,
            Model model
    ) {
        AdminChatRoomsResponse response = chatRoomService.getAdminChatRooms(cursor, size);

        model.addAttribute("chatRooms", response.getChatRooms());
        model.addAttribute("totalUnreadCount", response.getTotalUnreadCount());
        model.addAttribute("nextCursor", response.getNextCursor());

        return "admin/admin-chat";
    }
좋은 예시외부 서비스 연동을 전략화(uploadMode)하여 유연성 확보단일 책임 원칙 준수업로드 처리만 책임지고, 실제 구현은 ImageUpload에게 위임명확한 예외 처리UnsupportedOperationException으로 예외 상황 명시
@Service
@RequiredArgsConstructor
public class ChatImageServiceImpl implements ChatImageService {

    private final ImageUpload imageUpload;

    @Value("${app.image-upload.mode}")
    private String uploadMode;

    @Override
    public String uploadChatImage(MultipartFile image) {
        if ("ncp".equalsIgnoreCase(uploadMode)) {
            return imageUpload.uploadAndGetUrl("chat", image);
        } else {
            throw new UnsupportedOperationException("지원하지 않는 동작입니다.");
        }
    }
}

응답 및 요청 DTO 분리 – 계층 간 책임 분리의 기본

역할에 따른 명확한 클래스 분리 요청(Request DTO)과 응답(Response DTO)을 별도 클래스로 분리함으로써, 각각의 관심사를 분리

🖥️ 주요 기능 및 시연 영상

술 메인 화면: 다양한 주류의 술 정보 및 이미지 제공

AI 기반 술 추천 및 여행지 추천: 니즈에 맞는 술 추천 및 관련된 여행지 추천까지!

커뮤니티: 다양한 정보를 제공하고 소통할 수 있는 공간

1:1문의: 궁금한 점이나 문의 내용을 실시간으로 질문할 수 있는 공간

관리자 페이지: 실시간 모니터링 및 이벤트 관리 및 등록 관리까지!

🎥 시연 영상

시연 영상 바로가기

⚠️ 트러블슈팅 기록 (Troubleshooting)


1. 배포 실패 시에도 dev 브랜치에 병합되는 문제

🔍 문제 상황

  • CI 빌드는 성공했지만 배포 단계에서 오류가 발생했음에도 불구하고 dev 브랜치에 병합이 완료됨
  • 기존 구조는 dev 브랜치가 곧바로 배포 환경으로 연결되어 있어 사전 테스트가 어려운 구조

🛠️ 개선 방법

  • 개발 서버와 운영 서버를 분리
    • dev 브랜치 커밋은 개발 서버에서만 테스트
    • 배포 성공 시에만 운영 서버에 반영되도록 구성
    • 배포 실패 시 운영 서버에는 영향 없음

운영 서버의 안정성을 확보하고, CI/CD 파이프라인에서 병합과 배포를 분리하여 유연한 구조로 개선


2. 페이지 무한 로딩 현상

🔍 문제 상황

  • 페이지 로딩이 완료되었음에도 로딩 화면에서 멈춘 채 다음 페이지로 전환되지 않음
  • fragmenthtml에 동일한 코드가 중복 적용되면서 렌더링 완료 시점을 인식하지 못함

🛠️ 개선 방법

  • 모든 페이지에 공통 레이아웃(layout) 템플릿 적용
    • 중복된 코드 제거
    • 필요한 영역만 동적으로 렌더링되도록 수정
    • 전체 화면이 정확히 출력된 후 로딩 종료

사용자 경험을 저해했던 무한 로딩 문제 해결, 템플릿 구조를 유지보수하기 쉬운 방식으로 리팩토링


3. 게시글 조회 시 이미지 N+1 문제 발생

🔍 문제 상황

  • 게시글 조회 시 연관된 이미지들이 LAZY 로딩되어 post.getImages() 호출 시마다 쿼리가 반복 발생
  • 실제 운영 환경에서 쿼리 수가 급격히 증가, 성능 저하 유발

🛠️ 해결 방법

  • FETCH JOIN 적용
    • @Query에서 LEFT JOIN FETCH 사용
    • 게시글과 이미지 정보를 한 번의 쿼리로 조회
    • 성능 최적화 + Lazy 예외 방지 + 코드 안정성 확보

JPA의 지연 로딩 이슈에 대해 실제 운영 수준에서 문제를 인지하고 해결한 경험으로 이어짐


🔍 회고 및 배운 점

  • 사용자의 **니즈(추천 + 소통 + 알림)**를 반영한 종합 전통주 플랫폼 기획 및 구현
  • AI 추천, 채팅, 커뮤니티, 인증 등 다양한 기술 스택을 유기적으로 연결완성도 높은 기능을 제공
  • 일일 스크럼 및 회의를 통해 병합 이슈를 빠르게 해결하며 협업 능력과 소통 역량 강화

😓 아쉬운 점

  • 다양한 기술 습득과 구현을 병행하다 보니, 일부 기능의 완성도와 디테일이 부족
  • 기획 및 설계 단계에서의 우선순위 및 일정 조율이 미흡하여 구현 단계에서 반복적인 수정과 비효율적인 리팩토링 발생

📎 기타 자료

구분 설명 링크
🔗 Notion 프로젝트 정리 노션 페이지 바로가기
📋 Sprint Board 칸반 보드 (Sprint 관리) 바로가기
🧭 Milestone & Issue 마일스톤 및 이슈 관리 페이지 바로가기
🗂 WBS 문서 작업 분할 구조 (WBS) 바로가기
🗺 ERD 데이터베이스 설계 (ERDCloud) 바로가기

About

파이널 1팀 프로젝트 저장소

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors