프로젝트 주제 선정 과정
고객 친화적인 서비스(여행, 도서관 등)나 온오프라인 동시 서비스 등의 아이디어도 고려했지만, 조금 더 익숙하고 접근하기 쉬운 맛집을 주제로 선택
주제 선정 이유
- 많은 사람들이 "오늘 뭐 먹을까?"에 대한 고민을 자주 함
- 직장인을 포함한 다양한 사용자층을 확보 가능
- 메뉴 추천을 AI로 해결하면 데이터 입력의 한계를 극복할 수 있음
- 지도를 함께 제공하면 사용자 경험을 향상시킬 수 있음
- 오픈채팅 서비스를 통해 사용자 간 소통을 지원하고, 메뉴 추천과 맛집 경험을 공유할 수 있게 함
결론 : AI를 활용한 메뉴 추천 + 맛집 지도 연동 + 실시간 채팅 서비스를 주요 기능으로 설계하고 프로젝트를 진행하기로 결정
기술 스택 결정 과정
백엔드 트랙에서 배운 내용을 기반으로 선택하되, 프로젝트에 적합한 기술을 고민하면서 결정
주요 기술 스택 및 선택 이유
- Spring Boot : 백엔드 개발의 표준 기술로 활용
- MySQL : PostgreSQL과 고민했지만, 익숙한 MySQL을 선택해 쿼리 최적화에 집중하기로 결정
- WebSocket + STOMP + Redis Pub/Sub : 네이버 오픈톡 같은 실시간 채팅을 구현하기 위해 결정(실시간 채팅에 적합한 기술)
- Spring Security + JWT + Redis : 사용자 인증 및 세션 관리를 위해 선택
- AI 연동 (GPT-3.5) : 메뉴 추천 기능 구현을 구현하며, Spring AI를 활용해 OpenAI API와의 연동을 간소화 및 프롬프팅
- 카카오 지도 연동 : 메뉴 추천 이후 사용자들이 맛집 검색을 할 수 있도록 하기 위해 사용
PostgreSQL vs MySQL (가장 많은 고민을 한 기술 스택)
DB | 특징 | 선택하면 좋은 이유 |
PostgreSQL | - JSON 데이터를 효율적으로 저장 및 검색 가능 - MVCC를 통한 동시성 제어 - 복잡한 쿼리 최적화 가능 |
OpenAI API 응답 데이터 처리 및 실시간 채팅 성능 향상 |
MySQL | - 자료 및 커뮤니티가 풍부 - 간단한 관계형 데이터베이스로 사용 용이 |
익숙하지만 실시간 채팅과 JSON 처리에서 PostgreSQL 대비 불리 |
*MVCC(Multi Version Concurrency Control)
: 다중 버전 동시성 제어를 제공하여, 하나의 트랜잭션이 데이터를 수정하는 동안 다른 트랜잭션이 데이터를 읽을 수 있도록 함.
PostgreSQL은 데이터를 수정할 때 기존 데이터를 삭제하지 않고 새로운 버전으로 저장하므로, 동시 트랜잭션에서도 성능을 유지할 수 있음
결론 : 기술적 의사결정 과정에서 많은 의견충돌과 고민이 있었지만, 최종적으로 우리 팀이 효율적으로 개발할 수 있는 스택을 기준으로 결정
초기 설계
프로젝트 초기에는 맛집 추천을 AI 기반으로 구현하는 데 집중하여 Langchain, 프롬프팅, 자연어처리 등 AI 모델 개발에 초점을 맞춘 설계가 진행되었다. 특히, AI를 활용한 메뉴 추천 시스템을 중심으로 맛집 지도와 예약 기능까지 포함하려고 했다. 하지만 이 프로젝트의 주 목적은 백엔드 개발이었음에도 불구하고, AI 개발에 과도하게 집중하면서 핵심 기능의 우선순위가 흐려지고, 전반적인 설계가 복잡해지는 문제가 발생했다.
초기 설계 개요
- 사용자 기능: 회원가입, 로그인, 취향 설정 및 AI 메뉴 추천
- AI 연동: GPT-3.5를 활용한 메뉴 추천 -> Spring AI 사용은 나중에 도입
- 지도 API 연동: 메뉴 추천 후 근처 맛집 지도 제공 (카카오 지도 API 사용)
- 예약 기능: 맛집 예약 및 예약 상태 관리 (ENUM 활용)
- 실시간 채팅 기능: 사용자들이 추천 메뉴 및 맛집 경험을 공유할 수 있도록 지원
- 알림 기능: 예약 확정 및 30분 전 알림 (이메일 발송)
1. 와이어프레임
2. ERD
3. API 명세서
API 명세서 | Notion
Made with Notion, the all-in-one connected workspace with publishing capabilities.
clumsy-octave-632.notion.site
4. Cloud Architecture
5. 코드 컨벤션
*패키지 구조 및 도메인 분리
- 도메인별 패키지 분리 : 기능에 따라 Repository, Service, Dto, Controller를 구분
src
└── main
├── java
│ ├── com.project.tastefulai
│ │ ├── domain # (도메인별 패키지)
│ │ │ ├── domain1
│ │ │ │ ├── controller
│ │ │ │ ├── service
│ │ │ │ ├── repository
│ │ │ │ ├── dto
│ │ │ │ └── entity
│ │ │ ├── domain2
│ │ │ ├── domain3
│ │ │ └── domain4
│ │ ├── global # (공통 및 설정)
│ │ │ ├── common
│ │ │ ├── config
│ │ │ ├── constant
│ │ │ ├── error
│ │ │ └── util
*메서드 명명 규칙
HTTP 메서드 | 사용 규칙 | 메서드 예시 |
POST | 생성 관련 메서드, save 대신 create tkdyd | createMember() |
GET | 조회 관련 메서드, Service에서는 get, Repository에서는 find | getGenres(), findById() |
PUT/PATCH | 수정 관련 메서드, change, set 사용 금지 | updateImage() |
DELETE | 삭제 관련 메서드 | deleteProfiles() |
*코드 스타일 및 개발 구현 방식
- Setter/Getter 사용 제한
- Setter 사용 금지 : 데이터 무결성 보장을 위해 사용하지 않음
- Getter 사용 제한 : 양방향 매핑 시 N+1 문제를 방지하기 위해 사용 자제
- 대안 : 필요한 경우 QueryDSL을 활용해 필요한 데이터만 가져오기
- 주석 작성 기준
- 자율적으로 작성한 후 리팩토링 시 정리
- Service 로직 위주로 간결하게 작성
- JavaDoc 사용 /** */
- 새로운 스택 사용 시 주석 권장
- 클래스 및 메서드 네이밍
- 클래스명 : PascalCase 사용
- 메서드명 : camelCase 사용
- 패키지명 : 소문자 사용
- Entity, DTO 사용 원칙
- RequestDto -> Entity : Spread 방식으로 변환
- Entity -> ResponseDto : 생성자 활용(Entity를 매개변수로 받는 방식)
- Service -> Controller : ResponseDto 사용
- Controller -> Service : RequestDto를 풀어서 전달(reqeustDto.get() 형식 사용)
- CommonResponseDto 활용
- 응답 통일화 : CommonResponseDto<T> 사용
//응답 형식
public class CommonResponseDto<T> {
private String message;
private T data;
}
- 예외 처리 및 Enum 사용
- CustomExceptionHandler 활용
- Error 메시지 관리 : Enum을 통해 통일
- Enum 사용 규칙
- 대문자만 사용 : ADMIN, OWNER, USER
- Status 값은 모두 Enum으로 관리
- CustomExceptionHandler 활용
*기타 스타일 규칙
- 코드 줄 바꿈 규칙
- 어노테이션 있는 코드는 줄 바꿈
- 필드는 줄 바꿈 없이
- return문 전에 줄 바꿈
- 비슷한 로직은 묶어서 작성
- 코드가 옆으로 길어지면 적절히 줄 바꿈
- 금지
- @AllArgsConstructor 사용 금지:
- 대안: @RequiredConstructor, @NoArgsConstructor 사용
- Import 문에 와일드카드(*) 사용 금지:
- 설정: 9999999 이상으로 설정해 와일드카드가 사용되지 않도록 방지
- @AllArgsConstructor 사용 금지:
*초기 개발 방식
- Code With Me를 사용해 도메인별 기본 코드 다같이 작성(Controller, Service, DTO, Entity, Repository 생성 후 개발 진행)
- 컨벤션을 맞추기 위해 깃허브를 활용한 코드 리뷰 적극 진행
6. 프로젝트 구조 설계 및 Git Flow
- 아키텍쳐 : 클린 아키텍쳐 + 레이어드 아키텍쳐 -> 모듈화와 확장성 강화
- 도메인 중심의 설계를 유지하면서 Spring 기반의 계층 분리로 책임을 명확히하고, 유지보수성 확보
- Git Flow
- 프로젝트 개발 프로세스를 체계적으로 관리하기 위해 GitFlow 전략을 적용하여 여러 명이 동시에 개발을 진행하면서 코드 충돌을 최소화하고, 기능 개발과 배포를 원활하게 진행
- Git Branch 전략
브랜치 | 역할 | 설명 |
main | 배포용 | 최종 배포되는 코드 |
develop | 개발용 | 기능이 완성되기 전까지 통합 브랜치 |
feature/* | 기능 개발용 | 개별 기능을 개발하는 브랜치 |
hotfix | 긴급 수정 | 발생한 버그를 긴급 수정하는 브랜치 |
튜터링
& 1~2주차 동안 겪은 문제
& 해결 과정
프로젝트 초반, 튜터링이 AI 중심으로 진행되면서 Langchain, 프롬프팅, 자연어처리 등 AI 모델 활용이 주요 논의 대상이 되었다. 이 과정에서 백엔드 트랙임에도 불구하고 AI 개발에 초점이 맞춰지면서 프로젝트 방향이 흐려지는 문제가 발생하여 팀 내부에서 논의한 결과, "백엔드 개발 프로젝트를 진행 중"임을 명확히 하기로 했다.
따라서 기능의 우선순위를 조정하여 AI에 초점을 두기 보다는 기본적인 백엔드 기능(사용자 관리, 취향 관리, 채팅)을 먼저 구축하기로 했다.
1. AI 중심의 설계로 인해 프로젝트 방향 혼란
- 문제 상황
- 초기에는 AI모델(Langchain, 프롬프팅, 자연어처리)을 활용한 메뉴 추천을 중심으로 설계를 진행했지만, 핵심 기능의 우선순위가 흐려짐
- 맛집 지도, 예약 기능 등과 AI 추천을 연계하려다 보니 설계가 과도하게 복잡해짐
- 해결 방법
- 핵심 기능을 우선 개발하고 AI 연동을 점진적으로 추가하기로 결정
- MVP 목표를 명확하게 설정하여, AI 추천 -> 지도 연동 -> 예약 기능 순으로 개발 진행
- 튜터링
- 프롬프팅 & AI 히스토리
- AI 추천을 지속적으로 연결하려면 사용자의 취향 데이터와 히스토리를 유지하는 방식이 필요하다
- 단순한 OpenAI API 호출이 아니라 사용자 맞춤형 프롬프트 설계가 중요
- RDB 데이터 정형화 고려
- 추천 데이터를 어떻게 저장하고 활용할 것인지 고민해야 한다.
- PostgreSQL을 사용하여 AI 응답을 JSON 형식으로 저장하는 방식 논의
- 프롬프팅 & AI 히스토리
2. 기술 스택 결정 과정에서의 고민
- 문제 상황
- MySQL vs PostgreSQL 선택 과정에서 팀 내 논의가 많았음
- 실시간 채팅 기술을 결정할 때 Redis Pub/Sub이 적절한지 확신 부족
- 해결 방법
- DB 선택
- PostgreSQL은 JSON 저장, 복잡한 쿼리 지원, MVCC(다중 버전 동시성 제어) 등에서 강점이 있지만, 팀이 MySQL에 익숙하여 MySQL을 선택하고 쿼리 최적화에 집중하기로 결정
- Redis Pub/Sub
- Kafka, RabbitMQ는 대규모 메시지 처리에 적합하지만, 프로젝트에서 단일 채팅방을 운영하는 것이 목표였기 때문에 Redis Pub/Sub이 적절
- 튜터링
- MySQL과 PostgreSQL의 차이점 정리
- PostgreSQL은 JSON 데이터를 저장하고 분석하는데 강점이 있지만, 프로젝트 범위를 고려하면 MySQL이 더 적합할 수도 있다.
- Redis Pub/Sub 선택
- Kafka는 확장성이 크지만 운영 부담이 커서 실시간성이 중요하다면 Redis가 적합하다.
- MySQL과 PostgreSQL의 차이점 정리
- DB 선택
3. AI 프롬프팅 & 데이터 저장 방식 고민
- 문제 상황
- AI에게 최종적으로 보낼 질문(사용자 취향 + 채팅 질문)이 중복되는 경우, 불필요한 API 호출을 줄이는 방법이 필요함
- 같은 질문이라도 사용자의 말투에 따라 다르게 인식되는 문제 발생
- 해결 방법
- 프롬프팅 히스토리를 관리하여 AI 호출 최소화
- 유사도 검사 적용 가능성 검토
- 튜터링
- Stateful AI를 유지
- 이전 대화 히스토리를 포함해 프롬프트를 보낼 것
- AI가 문맥을 유지하도록 세션 조정할 것
- DB 캐싱과 검색 최적화
- 유사 질문을 버튼 클릭 방식으로 유도하면 NLP 처리를 줄일 수 있다.
- ElasticSearch 등을 활용하면 유사한 질문을 빠르게 검색할 수 있다.
- Stateful AI를 유지
4. 회원 관리 & 인증 관련 문제
- 문제 상황
- 회원 탈퇴 시 비밀번호 확인을 어떻게 구현할 지 고민
- 기본적인 회원 권한 외에 ADMIN 계정이 필요한지 논의
- 해결 방법
- 비밀번호 검증 후, 토큰을 새로 발급하여 탈퇴 요청을 보내는 방식으로 구현
- ADMIN 권한은 불필요하다고 판단하여 유지보수 단순화를 위해 USER만 운영
- 튜터링
- 회원 탈퇴 보안 강화
- DELETE 요청은 Body 값을 보내지 않는다. 세션이나 쿠키를 활용해서 검증할 것
- ADMIN 계정 필요 여부
- 불특정 다수를 대상으로 운영하는 서비스에서는 일반 USER만 관리하는 것이 효율적
- 회원 탈퇴 보안 강화
1~2주차 요약
- 기능의 우선순위를 정하고 MVP부터 구현하는 것이 중요하다.
- 기술 스택을 결정할 때, 팀이 다룰 수 있는 범위 내에서 정하고 최적화해야 한다.
- 주제를 명확하게 설정하는 것이 중요하다.
- 처음부터 너무 많은 기능을 넣지 말고 현실적으로 설정해야한다.
- 팀원 간의 의견을 조율하는 것이 가장 중요하다.
결론
1~2주차 설계 기간 동안 프로젝트의 핵심 기능을 명확히 정의하고, 현실적인 개발 방향을 설정하는 것의 중요성에 대해 알게 되었다. 초반에는 AI 중심의 설계로 인해 프로젝트가 복잡해졌고, 백엔드 개발이라는 본래의 목적이 흐려지는 문제가 발생했지만, 팀 회의를 통해 방향을 재조정하고, 핵심 기능을 먼저 개발하는 방식으로 수정하며 현실적인 설계란 무엇인지에 대해 배웠다.
기능의 우선순위를 정하고, 점진적으로 확장해나가야한다는 것이 중요하다는 것을 배우게 되었고, 무엇을 어떻게 먼저 만들것인가?를 신중하게 결정하는 것이 프로젝트의 올바른 방향과 일정 관리에 핵심이라는 것을 실감하게 되었다.
'TIL(Today I Learned) > 프로젝트' 카테고리의 다른 글
[TIL] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지? (4~5 주차. 중간발표 이후 리팩토링 및 추가 개발 + 프론트) (2) | 2025.04.18 |
---|---|
[TIL] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지? (2~3 주차. 구현 시작 및 중간 발표 준비) (0) | 2025.03.04 |
[TIL] Trello(칸반보드) 프로젝트 (0) | 2025.02.20 |
[TIL] 배달 앱 아웃소싱 프로젝트 (0) | 2024.12.19 |
[TIL] 고객과 통화 연관관계로 환전요청 만들기 (0) | 2024.12.02 |