Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

96 Commits
 
 
 
 
 
 

Repository files navigation

Dit

개발자 성향(DBTI) 기반 맞춤 프로젝트 추천 및 커뮤니티 서비스

Dit은 개발자가 포트폴리오 프로젝트를 준비할 때 겪는 "무엇을 만들지 모르겠다"는 문제에서 출발한 서비스입니다.
사용자는 DBTI 검사를 통해 자신의 개발 성향을 확인하고, AI 챗봇 Diti에게 DBTI 결과와 프로필 정보를 반영한 프로젝트를 추천받을 수 있습니다. 추천받은 프로젝트는 저장해 마이페이지에서 다시 확인할 수 있으며, 커뮤니티를 통해 개발 경험과 프로젝트 아이디어를 공유할 수 있습니다.


목차


👥 팀원 정보 및 업무 분담

이름 담당 영역 주요 구현 내용
정서영 회원 인증, 마이페이지, AI 프로젝트 추천, 저장 프로젝트, 커뮤니티 주요 기능 로그인/회원가입, 로그인 상태 유지, 마이페이지/계정 설정, 비밀번호 변경/계정 삭제, Diti AI 추천 챗봇, 추천 프로젝트 상세/찜하기, 저장 프로젝트 관리, 커뮤니티 게시글/댓글 CRUD
양혜림 프로젝트 초기 세팅, 홈, DBTI, 트렌드, 커뮤니티 검색, 공통 UI Vue/Django 초기 세팅, 홈 화면, DBTI 검사/결과, DBTI 질문/유형 데이터 구성, 기술 트렌드 시각화, 커뮤니티 검색, 라우터 접근 제어, Navbar/아이콘/반응형 UI 개선

정서영 담당 세부 구현

  • DRF Token 기반 로그인/회원가입 API 연동
  • 로그인 상태 유지 옵션에 따라 localStorage / sessionStorage 분리 저장
  • Pinia 기반 사용자 상태 관리 및 새로고침 시 사용자 정보 캐싱
  • 마이페이지 프로필 조회/수정, 검사 기록, 저장 프로젝트 연동
  • 계정 설정 페이지의 보안/상태 탭, 비밀번호 변경, 계정 삭제, 약관 모달 구현
  • AI 추천 요청 시 DBTI, 희망 직무, 전공, 보유 기술을 함께 전달하는 개인화 추천 흐름 구현
  • AI 응답을 JSON으로 받아 추천 카드, 상세 모달, 추천 이유 박스로 렌더링
  • 추천 프로젝트 찜하기/찜 취소 및 마이페이지 저장 프로젝트 관리
  • 커뮤니티 게시글/댓글 CRUD, 페이지네이션, 더보기 로직 구현

양혜림 담당 세부 구현

  • Vue 3 + Vite 프론트엔드 초기 구조 구성
  • Django REST Framework 백엔드 초기 구조 구성
  • 홈 화면 및 기술 트렌드 데이터 시각화 구현
  • DBTI 질문, 선택지, 유형, 궁합 데이터 구성
  • DBTI 검사 진행 및 결과 페이지 구현
  • 마이페이지 DBTI 검사 기록 API 연결
  • DBTI 결과 페이지 직접 URL 접근 제한
  • 커뮤니티 검색 기능 및 공통 UI 개선

🎯 목표 서비스 및 구현 정도

목표 기능 구현 정도 설명
회원가입/로그인 완료 이메일 기반 회원가입, 로그인, 로그아웃, 토큰 인증 구현
로그인 상태 유지 완료 체크 여부에 따라 localStorage 또는 sessionStorage 저장
DBTI 검사 완료 질문/선택지 기반 검사 진행 및 DBTI 결과 산출
DBTI 결과 조회 완료 유형 설명, 강점, 추천 키워드, 최신 결과 조회
AI 프로젝트 추천 완료 DBTI + 프로필 + 사용자 입력 기반 프로젝트 3개 추천
추천 상세 기획 완료 타깃 사용자, 문제, 핵심 기능, 사용자 흐름, 포트폴리오 포인트 제공
프로젝트 저장 완료 추천 프로젝트 찜하기/찜 취소, 마이페이지 저장 목록 조회
마이페이지 완료 프로필, 최신 DBTI, 검사 기록, 저장 프로젝트, 계정 설정 제공
계정 관리 완료 비밀번호 변경, 계정 삭제, 계정 상태 안내, 약관 모달
커뮤니티 완료 카테고리, 게시글 CRUD, 댓글 작성/삭제, 검색, 더보기
기술 트렌드 완료 홈 화면에서 기술 스택/AI 도구/프레임워크/DB 트렌드 표시
배포 미진행 로컬 개발 환경 기준으로 구현

🛠️ 기술 스택

Frontend

  • Vue 3
  • Vite
  • Vue Router
  • Pinia
  • Axios
  • Bootstrap 5
  • HTML2Canvas
  • HTML / CSS / JavaScript

Backend

  • Python
  • Django 5.2.4
  • Django REST Framework
  • DRF Token Authentication
  • django-allauth
  • dj-rest-auth
  • django-cors-headers
  • requests

Database

  • SQLite
  • Django ORM

AI

  • OpenAI Chat Completions 호환 API
  • gpt-5-nano
  • Django 백엔드에서 requests로 직접 호출
  • .env 기반 API Key, API URL, Model 관리

Tools

  • Git / GitLab
  • Visual Studio Code
  • Figma
  • Notion
  • Chrome DevTools

✨ 핵심 기능

1. DBTI 검사

  • 개발자의 협업 방식, 문제 해결 방식, 구현 성향을 진단합니다.
  • 질문별 선택지의 score 값을 기반으로 DBTI 유형을 산출합니다.
  • 결과 페이지에서 유형명, 설명, 강점, 추천 키워드를 제공합니다.
  • 최신 DBTI 결과는 마이페이지와 프로젝트 추천에 활용됩니다.

2. AI 프로젝트 추천 챗봇 Diti

  • 사용자의 최신 DBTI, 희망 직무, 전공, 보유 기술을 추천 요청에 포함합니다.
  • 사용자가 자유롭게 입력한 도메인/주제/조건을 함께 반영합니다.
  • AI는 프로젝트 3개를 추천하고, 각 프로젝트에 다음 정보를 포함합니다.
    • 제목
    • 카테고리
    • 요약
    • 난이도
    • 예상 기간
    • 추천 기술 스택
    • 추천 이유
    • 상세 기획 정보

3. 추천 프로젝트 상세 보기

추천 프로젝트는 단순 제목 추천에서 끝나지 않고, 기획서 형태의 상세 정보를 제공합니다.

  • 타깃 사용자
  • 해결하려는 문제
  • 핵심 기능
  • 사용자 흐름
  • 데이터 흐름
  • 확장 아이디어
  • 포트폴리오에서 강조할 수 있는 역량

4. 프로젝트 저장

  • 추천받은 프로젝트를 찜할 수 있습니다.
  • 이미 저장한 프로젝트를 다시 누르면 찜이 취소됩니다.
  • 저장한 프로젝트는 마이페이지에서 다시 확인할 수 있습니다.
  • 저장 프로젝트에서도 상세 보기와 찜 취소가 가능합니다.

5. 마이페이지

  • 사용자 프로필 조회/수정
  • 최신 DBTI 결과 요약
  • DBTI 검사 기록 조회
  • 저장한 프로젝트 조회
  • 계정 설정
    • 계정 정보 확인
    • 비밀번호 변경
    • 계정 삭제
    • 계정 상태 확인
    • Dit 이용 약관/커뮤니티 지침 모달

6. 커뮤니티

  • 자유게시판, 질문답변, 프로젝트 홍보, 정보공유 카테고리 제공
  • 게시글 작성/조회/수정/삭제
  • 댓글 작성/삭제
  • 카테고리별 필터링
  • 제목/내용/작성자 기반 검색
  • 더보기 기반 페이지네이션

🤖 추천 알고리즘 및 AI 추천 구조

Dit의 추천은 규칙 기반 DBTI 결과와 생성형 AI 추천을 함께 사용합니다.

1. DBTI 기반 성향 분석

DBTI 검사는 질문별 선택지에 부여된 score 값을 기반으로 사용자의 개발 성향을 산출합니다.

사용자 응답
→ 선택지별 score 집계
→ DBTI 유형 결정
→ DbtiTestResult 저장
→ 최신 DBTI 결과를 추천/마이페이지에서 활용

DBTI 유형 데이터는 dbti_types.json에 정의되어 있으며, 각 유형은 다음 정보를 포함합니다.

  • type_code
  • type_name
  • short_description
  • description
  • strengths
  • recommended_keywords
  • character_image

2. AI 추천 요청 구성

프로젝트 추천 페이지에서 사용자가 메시지를 입력하면 프론트엔드는 사용자 입력에 프로필 정보를 함께 붙여 백엔드로 전달합니다.

[사용자 프로필]
DBTI: TDL
희망 직무: 프론트엔드
전공: 경영학과
보유 기술: Java, JavaScript, Vue, Python, React

[사용자 메시지]
금융 쪽 프로젝트 추천해줘

이 구조를 선택한 이유는 AI가 마지막 사용자 입력만 보고 추천하지 않고, 사용자의 성향과 현재 역량을 함께 고려하도록 하기 위해서입니다.

3. 추천 세션 및 대화 히스토리

추천 요청은 ProjectRecommendationSession 단위로 관리됩니다.

추천 세션 생성
→ 사용자 메시지 저장
→ 같은 세션의 대화 히스토리 조회
→ developer 프롬프트 + 대화 히스토리로 AI API 호출
→ AI 응답 저장
→ 추천 프로젝트 DB 저장

대화 히스토리를 함께 전달하기 때문에 사용자가 조건을 나눠 말하거나, "다른 프로젝트 추천해줘"처럼 이어지는 요청을 해도 이전 맥락을 반영할 수 있습니다.

4. AI 응답 JSON 구조화

AI 응답은 프론트 UI에서 바로 사용할 수 있도록 JSON 형식으로 강제했습니다.

{
  "message": "채팅창에 보여줄 짧은 답변",
  "recommendation_reason": "추천 이유 박스에 보여줄 자연스러운 설명",
  "quick_options": [],
  "projects": [
    {
      "title": "개인 소비 패턴 분석 대시보드",
      "category": "금융 웹앱",
      "summary": "소비 내역을 시각화하고 월별 지출 패턴을 분석하는 서비스",
      "difficulty": "보통",
      "expected_period": "2주",
      "skills": ["Vue", "JavaScript", "Chart.js"],
      "reason": "프론트엔드 구현력과 데이터 시각화 역량을 보여주기 좋습니다.",
      "rank": 1,
      "detail": {
        "target_users": "소비 습관을 관리하고 싶은 개인 사용자",
        "problem": "지출 흐름을 한눈에 파악하기 어렵다",
        "core_features": ["소비 입력", "카테고리별 시각화", "월별 리포트"],
        "user_flow": ["소비 내역 입력", "대시보드 확인", "월간 리포트 조회"],
        "data_flow": "사용자 입력 데이터를 카테고리별로 집계하고 차트로 표시",
        "extension_ideas": ["예산 초과 알림", "CSV 내보내기"],
        "portfolio_points": ["데이터 시각화", "상태 관리", "사용자 경험 설계"]
      }
    }
  ]
}

JSON을 강제한 이유는 AI 응답을 단순 텍스트가 아니라 서비스 데이터처럼 사용하기 위해서입니다. 추천 결과는 카드, 상세 모달, 추천 이유 박스에 각각 연결됩니다.

5. 추천 프로젝트 저장 구조

AI가 생성한 추천 결과와 사용자가 저장한 프로젝트는 분리해서 관리합니다.

RecommendedProject
AI 추천 세션에 속한 추천 결과

Project
사용자가 저장할 수 있는 프로젝트 데이터

SavedProject
사용자와 Project를 연결하는 찜/저장 테이블

사용자가 찜하기를 누르면 RecommendedProject를 기반으로 Project를 생성하거나 조회하고, SavedProject로 사용자와 연결합니다. 이미 저장되어 있으면 삭제하여 찜 취소로 동작합니다.


🧠 생성형 AI 활용

활용 위치

  • 프로젝트 추천 챗봇 Diti
  • 추천 이유 생성
  • 프로젝트 상세 기획 정보 생성

사용 방식

  • 프론트엔드에서 직접 AI API를 호출하지 않습니다.
  • Django 백엔드에서 .env에 저장된 API Key를 사용해 외부 LLM API를 호출합니다.
  • API Key 노출을 방지하고, 응답 파싱 및 예외 처리를 서버에서 관리하기 위한 구조입니다.

프롬프트 설계 핵심

  • Diti의 역할과 말투 정의
  • 항상 한국어 존댓말 사용
  • JSON 외의 텍스트 반환 금지
  • 사용자 프로필 태그 적극 반영
  • 사용자가 주제/도메인을 입력하면 추가 질문 없이 바로 추천
  • 모호한 경우에만 quick options 제공
  • 추천 시 프로젝트는 반드시 3개
  • 각 프로젝트에 상세 기획 정보 포함

예외 처리

  • AI API timeout 발생 시 504 응답 반환
  • AI 응답 JSON 파싱 실패 시 기본 메시지 형태로 fallback
  • 프론트에서는 실패 시 사용자에게 재시도 메시지 표시

📡 API 명세서

계정 (/api/v1/accounts/)

Method Endpoint 인증 설명
POST /signup/ - 회원가입
GET /check-email/ - 이메일 중복 확인
GET /check-nickname/ - 닉네임 중복 확인
POST /login/ - 로그인 (토큰 발급)
POST /logout/ 필요 로그아웃
GET /me/ 필요 내 정보 조회
POST /password/ 필요 비밀번호 변경
DELETE /account/ 필요 계정 삭제

마이페이지 (/api/v1/mypage/)

Method Endpoint 인증 설명
GET / PATCH /profile/ 필요 마이페이지 프로필 조회/수정
GET /dbti-results/ 필요 DBTI 검사 기록 목록 조회

DBTI (/api/v1/dbti/)

Method Endpoint 인증 설명
GET /types/ - DBTI 유형 전체 목록
GET /types/<code>/ - DBTI 유형 상세
GET /questions/ - DBTI 검사 질문 목록
POST /results/ 필요 DBTI 검사 결과 생성
GET /results/latest/ 필요 최신 DBTI 결과 조회
GET /results/<id>/ 필요 DBTI 결과 상세 조회

AI 프로젝트 추천 (/api/v1/recommendations/)

Method Endpoint 인증 설명
GET / POST /sessions/ 필요 추천 세션 목록 조회 / 생성
GET /sessions/<id>/ 필요 추천 세션 상세(대화 히스토리) 조회
POST /sessions/<id>/messages/ 필요 메시지 전송 및 AI 추천 응답 생성

저장 프로젝트 (/api/v1/projects/)

Method Endpoint 인증 설명
GET / POST /saved/ 필요 저장 프로젝트 목록 조회 / 찜하기
DELETE /saved/<id>/ 필요 저장 프로젝트 삭제(찜 취소)

커뮤니티 (/api/v1/community/)

Method Endpoint 인증 설명
GET /categories/ - 카테고리 목록
GET / POST /posts/ GET: - / POST: 필요 게시글 목록 조회 / 작성
GET / PATCH / DELETE /posts/<id>/ GET: - / PATCH·DELETE: 필요(작성자) 게시글 상세 조회 / 수정 / 삭제
POST /posts/<id>/comments/ 필요 댓글 작성
DELETE /comments/<id>/ 필요 댓글 삭제(작성자)

트렌드 / 홈 (/api/v1/)

Method Endpoint 인증 설명
GET /trends/tech-stacks/ - 기술 스택 트렌드
GET /trends/ai-tools/ - AI 도구 트렌드
GET /trends/frameworks/ - 프레임워크 트렌드
GET /trends/databases/ - DB 트렌드
GET /home/stats/ - 홈 통계 (DBTI 검사 수, 추천 프로젝트 수)

인증이 필요한 요청은 Authorization: Token <token> 헤더로 DRF Token을 전달합니다.


🖼️ 와이어프레임

Figma 와이어프레임 보러가기


🗄️ 데이터베이스 모델링 ERD

erDiagram
    User ||--|| UserProfile : has
    User ||--o{ DbtiTestResult : takes
    DbtiType ||--o{ DbtiTestResult : result_type
    DbtiType ||--o{ DbtiCompatibility : base_type
    DbtiType ||--o{ DbtiCompatibility : target_type
    DbtiQuestion ||--o{ DbtiOption : has

    User ||--o{ ProjectRecommendationSession : owns
    DbtiTestResult ||--o{ ProjectRecommendationSession : based_on
    ProjectRecommendationSession ||--o{ RecommendationMessage : has
    ProjectRecommendationSession ||--o{ RecommendedProject : recommends

    User ||--o{ SavedProject : saves
    Project ||--o{ SavedProject : saved_as

    User ||--o{ Post : writes
    CommunityCategory ||--o{ Post : contains
    Post ||--o{ Comment : has
    User ||--o{ Comment : writes

    User {
        int id PK
        string email
        string nickname
        datetime created_at
        datetime updated_at
    }

    UserProfile {
        int id PK
        int user_id FK
        string profile_image
        string major
        string desired_job
        string skills
        string bio
    }

    DbtiType {
        string type_code PK
        string type_name
        string short_description
        text description
        json strengths
        json recommended_keywords
        string character_image
    }

    DbtiQuestion {
        int id PK
        int question_order
        string question_text
    }

    DbtiOption {
        int id PK
        int question_id FK
        string option_text
        string description
        string score_value
    }

    DbtiTestResult {
        int id PK
        int user_id FK
        string dbti_type_id FK
        datetime created_at
    }

    ProjectRecommendationSession {
        int id PK
        int user_id FK
        int dbti_result_id FK
        text desired_idea
        string expected_period
        string service_purpose
        string preferred_difficulty
        string status
    }

    RecommendationMessage {
        int id PK
        int session_id FK
        string sender
        text message
        datetime created_at
    }

    RecommendedProject {
        int id PK
        int session_id FK
        string title
        string category
        string summary
        string difficulty
        string expected_period
        json skills
        text reason
        json detail
        int rank
    }

    Project {
        int id PK
        string title
        string category
        string summary
        text description
        string difficulty
        string expected_period
        text portfolio_point
        json skills
        json detail
    }

    SavedProject {
        int id PK
        int user_id FK
        int project_id FK
        datetime created_at
    }

    CommunityCategory {
        int id PK
        string name
        string slug
        int order
    }

    Post {
        int id PK
        int user_id FK
        int category_id FK
        string title
        text content
        datetime created_at
        datetime updated_at
    }

    Comment {
        int id PK
        int post_id FK
        int user_id FK
        text content
        datetime created_at
        datetime updated_at
    }
Loading

사용자 플로우 및 권한 정책

사용자 플로우

회원가입/로그인
→ DBTI 검사
→ DBTI 결과 확인
→ 프로젝트 추천 페이지 이동
→ Diti와 대화 또는 조건 선택
→ AI 추천 프로젝트 확인
→ 상세 보기
→ 프로젝트 저장
→ 마이페이지에서 저장 프로젝트 관리
→ 커뮤니티에서 아이디어 공유

권한 정책

기능 비회원 로그인 사용자 작성자/소유자
홈 조회 가능 가능 가능
회원가입/로그인 가능 불필요 불필요
DBTI 메인 조회 가능 가능 가능
DBTI 검사 불가 가능 가능
DBTI 결과 상세 제한 본인 결과 중심 접근 본인 결과 접근
프로젝트 추천 불가 가능 가능
추천 프로젝트 저장 불가 가능 본인 추천 결과만 가능
저장 프로젝트 조회/삭제 불가 가능 본인 저장 프로젝트만 가능
마이페이지 조회/수정 불가 가능 본인 정보만 가능
비밀번호 변경/계정 삭제 불가 가능 본인 계정만 가능
커뮤니티 목록/상세 조회 가능 가능 가능
커뮤니티 글 작성 불가 가능 가능
커뮤니티 글 수정/삭제 불가 불가 작성자만 가능
댓글 작성 불가 가능 가능
댓글 삭제 불가 불가 작성자만 가능

접근 제어 방식

  • 프론트엔드
    • Vue Router beforeEach로 로그인 필요 페이지 접근 제한
    • 로그인하지 않은 사용자가 프로젝트 추천, DBTI 검사/결과 등에 접근하면 로그인 페이지로 이동
  • 백엔드
    • DRF IsAuthenticated, IsAuthenticatedOrReadOnly 사용
    • 게시글/댓글 수정 삭제 시 작성자 검증
    • 추천 프로젝트 저장 시 session__user=request.user 조건으로 본인 추천 결과만 저장 가능
    • 저장 프로젝트 조회/삭제 시 user=request.user 조건으로 본인 데이터만 접근 가능

프로젝트 구조

Dit
├── README.md
├── backend
│   ├── .gitignore
│   ├── manage.py
│   ├── requirements.txt
│   ├── accounts
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── mypage_urls.py
│   │   ├── serializers.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       └── __init__.py
│   ├── community
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── serializers.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   ├── fixtures
│   │   │   └── community_categories.json
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       └── __init__.py
│   ├── config
│   │   ├── __init__.py
│   │   ├── asgi.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── dbti
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   ├── fixtures
│   │   │   ├── dbti_compatibilities.json
│   │   │   ├── dbti_options.json
│   │   │   ├── dbti_questions.json
│   │   │   └── dbti_types.json
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       └── __init__.py
│   ├── home
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── tests.py
│   │   ├── views.py
│   │   ├── fixtures
│   │   │   ├── 2024_2025_trend_data.json
│   │   │   ├── 2025_ai_tool_trend_data.json
│   │   │   ├── 2025_database_trend_data.json
│   │   │   └── 2025_framework_trend_data.json
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       ├── 0002_aitooltrend.py
│   │       ├── 0003_databasetrend_frameworktrend.py
│   │       └── __init__.py
│   ├── projects
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── serializers.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       ├── 0002_project_skills.py
│   │       ├── 0003_project_detail.py
│   │       └── __init__.py
│   ├── recommendations
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── serializers.py
│   │   ├── services.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   └── migrations
│   │       ├── 0001_initial.py
│   │       ├── 0002_alter_recommendedproject_options_and_more.py
│   │       ├── 0003_recommendedproject_detail.py
│   │       └── __init__.py
│
├── frontend
│   ├── .gitignore
│   ├── index.html
│   ├── jsconfig.json
│   ├── package-lock.json
│   ├── package.json
│   ├── vite.config.js
│   ├── public
│   │   ├── favicon.ico
│   │   └── favicon.png
│   ├── src
│   │   ├── App.vue
│   │   ├── main.js
│   │   ├── api
│   │   │   ├── projects.js
│   │   │   └── recommendations.js
│   │   ├── assets
│   │   │   ├── base.css
│   │   │   ├── main.css
│   │   │   ├── images
│   │   │   │   ├── common
│   │   │   │   │   ├── Logo.png
│   │   │   │   │   └── diti_icon.png
│   │   │   │   ├── community
│   │   │   │   │   ├── community1.png
│   │   │   │   │   ├── noSearch.png
│   │   │   │   │   └── search.png
│   │   │   │   ├── dbti
│   │   │   │   │   ├── BadIcon.png
│   │   │   │   │   ├── DbtiCharacter.png
│   │   │   │   │   ├── DbtiTypeCharacter.png
│   │   │   │   │   ├── FeatureIcon1.png
│   │   │   │   │   ├── FeatureIcon2.png
│   │   │   │   │   ├── FeatureIcon3.png
│   │   │   │   │   ├── GoodIcon.png
│   │   │   │   │   ├── dbti1.png
│   │   │   │   │   └── dbti2.png
│   │   │   │   ├── home
│   │   │   │   │   ├── BannerBg.png
│   │   │   │   │   ├── HomeCharacter.png
│   │   │   │   │   ├── home1.png
│   │   │   │   │   ├── home2.png
│   │   │   │   │   ├── home3.png
│   │   │   │   │   ├── home4.png
│   │   │   │   │   ├── home5.png
│   │   │   │   │   ├── home6.png
│   │   │   │   │   ├── home7.png
│   │   │   │   │   ├── wave-bottom.svg
│   │   │   │   │   └── wave-top.svg
│   │   │   │   └── profile
│   │   │   │       ├── MyProfileEdit.png
│   │   │   │       ├── profile1.png
│   │   │   │       ├── profile2.png
│   │   │   │       ├── profile3.png
│   │   │   │       └── profile4.png
│   │   │   └── styles
│   │   │       ├── auth.css
│   │   │       ├── community.css
│   │   │       ├── dbti.css
│   │   │       ├── home.css
│   │   │       ├── mypage.css
│   │   │       ├── project.css
│   │   │       └── variables.css
│   │   ├── components
│   │   │   ├── auth
│   │   │   │   ├── AuthIntroCarousel.vue
│   │   │   │   ├── LoginForm.vue
│   │   │   │   └── SignupForm.vue
│   │   │   ├── common
│   │   │   │   ├── Footer.vue
│   │   │   │   ├── Navbar.vue
│   │   │   │   └── PolicyModal.vue
│   │   │   ├── community
│   │   │   │   ├── CommunityCategoryTabs.vue
│   │   │   │   ├── CommunityCommentItem.vue
│   │   │   │   ├── CommunityCommentList.vue
│   │   │   │   ├── CommunityHero.vue
│   │   │   │   ├── CommunityPostDetail.vue
│   │   │   │   ├── CommunityPostForm.vue
│   │   │   │   ├── CommunityPostItem.vue
│   │   │   │   └── CommunityPostList.vue
│   │   │   ├── dbti
│   │   │   │   ├── DbtiBanner.vue
│   │   │   │   ├── DbtiChemistry.vue
│   │   │   │   ├── DbtiExamCard.vue
│   │   │   │   ├── DbtiFeatures.vue
│   │   │   │   ├── DbtiProgressBar.vue
│   │   │   │   ├── DbtiRecommendLink.vue
│   │   │   │   ├── DbtiReportCard.vue
│   │   │   │   └── DbtiTypePreview.vue
│   │   │   ├── home
│   │   │   │   ├── HomeBanner.vue
│   │   │   │   ├── HomeFeatures.vue
│   │   │   │   ├── HomeStats.vue
│   │   │   │   └── HomeTrends.vue
│   │   │   ├── mypage
│   │   │   │   ├── MyDbtiBanner.vue
│   │   │   │   ├── MyInfoSummary.vue
│   │   │   │   ├── MyPageSidebar.vue
│   │   │   │   ├── MyProfileEditModal.vue
│   │   │   │   ├── MyProfileSummary.vue
│   │   │   │   ├── MyTestHistoryList.vue
│   │   │   │   └── MyTestHistorySummary.vue
│   │   │   ├── project
│   │   │   │   ├── ProjectCard.vue
│   │   │   │   ├── ProjectDetailModal.vue
│   │   │   │   ├── ProjectReasonBox.vue
│   │   │   │   ├── ProjectSideCard.vue
│   │   │   │   └── ProjectSummaryBar.vue
│   │   │   └── recommendations
│   │   │       ├── RecommendationChatBox.vue
│   │   │       └── RecommendationMessageItem.vue
│   │   ├── router
│   │   │   └── index.js
│   │   ├── stores
│   │   │   ├── auth.js
│   │   │   ├── community.js
│   │   │   └── counter.js
│   │   ├── utils
│   │   │   └── skillColors.js
│   │   ├── views
│   │   │   ├── community
│   │   │   │   ├── CommunityCreateView.vue
│   │   │   │   ├── CommunityDetailView.vue
│   │   │   │   ├── CommunityEditView.vue
│   │   │   │   └── CommunityListView.vue
│   │   │   ├── dbti
│   │   │   │   ├── DbtiExamView.vue
│   │   │   │   ├── DbtiMainView.vue
│   │   │   │   └── DbtiResultView.vue
│   │   │   ├── HomeView.vue
│   │   │   ├── LoginView.vue
│   │   │   ├── MyPageAccountSettingsView.vue
│   │   │   ├── MyPageSavedProjectsView.vue
│   │   │   ├── MyPageTestsView.vue
│   │   │   ├── MyPageView.vue
│   │   │   ├── ProjectRecommendView.vue
│   │   │   └── SignupView.vue
│   │   └── README.md
│   └── README.md

실행 방법

1. Backend

cd backend
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt

.env 파일을 backend/.env 경로에 생성합니다.

GMS_KEY=your_api_key
GMS_API_URL=your_chat_completions_api_url
GMS_MODEL=gpt-5-nano

DB 마이그레이션 및 fixture 로드:

python manage.py migrate
python manage.py loaddata dbti/fixtures/dbti_types.json
python manage.py loaddata dbti/fixtures/dbti_questions.json
python manage.py loaddata dbti/fixtures/dbti_options.json
python manage.py loaddata dbti/fixtures/dbti_compatibilities.json
python manage.py loaddata community/fixtures/community_categories.json

개발 서버 실행:

python manage.py runserver

2. Frontend

cd frontend
npm install
npm run dev

기본 접속 주소:

Frontend: http://localhost:5173
Backend:  http://127.0.0.1:8000

서비스 URL

현재 배포는 진행하지 않았으며, 로컬 개발 환경 기준으로 실행합니다.

http://localhost:5173

협업 규칙

Branch 전략

  • dit: 최종 통합 브랜치
  • 기능 단위 브랜치: home, dbti, community, project, chatbot, fix
  • 기능 구현 후 merge request를 통해 통합

Commit 규칙

태그 설명
setting 프로젝트 초기 세팅
feat 기능 구현 및 추가
fix 버그 수정
refactor 기능 변경 없는 구조 개선
chore 설정, 이미지, 기타 작업
docs 문서 수정

구현 과정 회고

양혜림

1. 구현 과정 중 학습한 내용

  • Django와 Vue 3 프로젝트 초기 세팅을 직접 구성하면서, 두 서버가 분리된 구조에서 CORS와 API 베이스 URL을 어떻게 맞춰야 하는지 학습했습니다.
  • DBTI 검사를 문항, 선택지, 유형, 유형 간 호환성으로 모델을 나누어 설계하면서, 진단 로직을 프론트가 아니라 데이터 구조로 표현하는 방법을 익혔습니다.
  • Vue Router의 beforeEach 가드와 START_LOCATION을 활용해, 새로고침이나 URL 직접 입력처럼 "앱 내부 이동이 아닌 진입"을 구분하는 방법을 학습했습니다.
  • 홈 화면 트렌드 위젯을 만들면서 Stack Overflow Developer Survey 같은 외부 공개 데이터를 fixture로 가공해 보여주는 흐름을 익혔습니다.

2. 어려웠던 부분

  • 프로필 드롭다운 메뉴가 바깥을 클릭해도 닫히지 않는 문제를 고치면서, Vue 컴포넌트 안에서 document에 직접 이벤트 리스너를 등록·해제하는 타이밍을 맞추는 게 생각보다 까다로웠습니다.
  • DBTI 결과 페이지를 주소창 직접 입력이나 새로고침으로 들어오지 못하게 막아야 했는데, "정상적인 이동"과 "직접 진입"을 라우터 단에서 구분하는 기준을 잡는 데 시간이 걸렸습니다.
  • 커뮤니티 검색을 "전체 탭에서는 모든 게시글, 특정 탭에서는 그 카테고리만" 검색되도록 범위를 나누는 과정에서, 프론트만으로는 한계가 있어 백엔드 쿼리 파라미터까지 같이 손봐야 했습니다.
  • 커뮤니티 페이지를 사이드바 레이아웃으로 리뉴얼하는 과정에서 CSS Grid의 align-items: stretch와 디바이더 위치 같은 디테일을 맞추느라 같은 부분을 여러 번 수정했습니다.

3. 새로 배운 것들

  • Bootstrap 유틸리티 클래스(.mb-3 등)는 !important로 정의되어 있어서, 같은 요소에 인라인 스타일을 줘도 조용히 무시될 수 있다는 점을 직접 겪고 배웠습니다.
  • 구분선을 "카드 끝까지 가득 차게" 할지 "위아래 여백을 두고" 할지에 따라, 패딩을 부모(카드)에 줄지 자식(아이템)에 줄지가 달라진다는 CSS 박스 모델의 디테일을 배웠습니다.
  • 프론트엔드 라우터 가드만으로는 막을 수 없는 부분(새로고침, 직접 진입)도 있고, 이런 흐름 제어는 화면 전환 방식 자체를 이해해야 다룰 수 있다는 점을 배웠습니다.
  • 외부 설문 데이터를 그대로 보여주는 것보다, TOP10처럼 일정한 기준으로 가공하고 출처를 명시해야 신뢰할 수 있는 콘텐츠가 된다는 점을 배웠습니다.
  • 반복되는 모달(이용약관, 커뮤니티 지침 등)은 타입을 prop으로 받는 공용 컴포넌트로 분리하면, 페이지마다 같은 마크업을 복사하지 않아도 된다는 걸 배웠습니다.

4. 느낀 점

  • 초기 세팅부터 화면 디테일을 다듬는 작업까지 직접 해보면서, 기능이 동작하는 것과 "사용자가 어색함을 못 느끼게" 만드는 것 사이에 꽤 큰 차이가 있다는 걸 느꼈습니다.
  • 같은 레이아웃이라도 화면 크기가 줄어들면 의도와 다르게 깨지는 경우가 많아서, 반응형까지 고려해야 진짜 끝난 작업이라는 걸 체감했습니다.
  • 디자인을 여러 번 엎고 다시 만드는 과정이 많았는데, 그만큼 작은 디테일(정렬, 간격, 폰트 크기)이 전체 인상에 미치는 영향이 크다는 걸 느꼈습니다.
  • 트렌드처럼 외부 데이터를 다루는 기능은 "어떤 데이터를 보여줄지" 기획하는 단계가 구현보다 더 오래 걸릴 수 있다는 걸 알게 됐습니다.
  • 혼자 작업한 기능이라도 결국 다른 페이지(마이페이지, 프로젝트 추천)와 자연스럽게 이어져야 한다는 걸 느꼈고, 그래서 작은 버그 하나도 전체 흐름을 다시 점검하게 되는 경우가 많았습니다.

정서영

1. 구현 과정 중 학습한 내용

  • Django REST Framework의 Token Authentication을 사용해 로그인/회원가입 이후 인증이 필요한 API를 호출하는 흐름을 학습했습니다.
  • Pinia store를 활용해 로그인 상태, 사용자 정보, 마이페이지 정보를 전역 상태로 관리하는 방식을 익혔습니다.
  • localStoragesessionStorage의 차이를 활용해 로그인 상태 유지 여부에 따라 저장 방식을 분리했습니다.
  • AI 추천 결과를 단순 텍스트가 아니라 프론트 UI에서 바로 사용할 수 있는 JSON 데이터로 다루는 방식을 학습했습니다.
  • 추천 프로젝트와 저장 프로젝트를 분리해 RecommendedProject, Project, SavedProject로 관리하는 데이터 흐름을 설계했습니다.
  • 비밀번호 변경, 계정 삭제처럼 민감한 기능은 프론트 검증과 백엔드 검증을 함께 적용해야 한다는 점을 학습했습니다.

2. 어려웠던 부분

  • AI가 사용자의 의도를 충분히 이해하면서도 항상 일정한 JSON 형식으로 응답하게 만드는 프롬프트 설계가 어려웠습니다.
  • 사용자가 조건을 모두 선택하지 않고 자유롭게 입력했을 때, 추가 질문 없이 바로 추천되도록 AI 규칙을 조정하는 과정이 까다로웠습니다.
  • 프로젝트 추천 페이지에서 다른 페이지로 이동했다가 돌아와도 채팅과 추천 결과가 유지되도록 상태를 관리하는 부분이 어려웠습니다.
  • 새로고침 시 Navbar나 마이페이지에서 사용자 정보가 잠깐 기본값으로 보이는 문제를 해결하기 위해 Pinia와 storage 캐싱 흐름을 맞추는 데 시간이 걸렸습니다.
  • 추천 프로젝트를 찜했을 때 마이페이지 저장 프로젝트와 자연스럽게 연결되도록 프론트 상태와 백엔드 저장 로직을 맞추는 과정이 복잡했습니다.

3. 새로 배운 것들

  • 프론트엔드 라우터 가드는 사용자 경험을 위한 1차 접근 제어이고, 실제 권한 검증은 백엔드에서 반드시 다시 처리해야 한다는 점을 배웠습니다.
  • AI API Key는 프론트에 두지 않고 백엔드 .env에서 관리해야 하며, 외부 API 호출과 응답 파싱도 서버에서 처리하는 것이 안전하다는 점을 배웠습니다.
  • AI 응답을 서비스 화면에 연결하려면 프롬프트에서 응답 구조, 필수 필드, 예외 상황을 구체적으로 정의해야 한다는 점을 배웠습니다.
  • 사용자 프로필이나 DBTI 결과가 바뀌면 기존 추천 결과가 더 이상 적절하지 않을 수 있으므로, 추천 당시의 프로필 snapshot을 저장해 비교하는 방식이 필요하다는 점을 배웠습니다.
  • 저장/찜하기 기능은 별도 저장 API와 삭제 API로 나눌 수도 있지만, toggle 방식으로 구현하면 프론트의 버튼 상태 관리가 단순해질 수 있다는 점을 배웠습니다.

4. 느낀 점

  • 단순히 기능을 구현하는 것보다 사용자의 흐름이 끊기지 않도록 데이터를 어떻게 이어줄지 고민하는 과정이 중요하다고 느꼈습니다.
  • AI를 활용할 때는 API를 호출하는 것 자체보다, AI가 반환한 결과를 실제 서비스 데이터처럼 안정적으로 사용할 수 있도록 구조를 설계하는 것이 더 중요하다고 느꼈습니다.
  • 로그인, 마이페이지, AI 추천, 저장 프로젝트가 각각 따로 있는 기능처럼 보이지만, 실제 서비스에서는 하나의 사용자 경험으로 이어져야 한다는 점을 많이 배웠습니다.
  • 구현 중간에 UI 문구나 추천 이유가 어색하게 느껴지는 부분이 많았고, 기능뿐 아니라 사용자가 읽고 납득할 수 있는 흐름을 만드는 것도 중요하다고 느꼈습니다.
  • 짧은 기간 안에 여러 기능을 연결하면서 버그도 많았지만, 문제를 하나씩 추적하고 상태 흐름을 정리하면서 전체 서비스 구조를 더 잘 이해할 수 있었습니다.

향후 개선 방향

  • 추천 결과에 대한 사용자 피드백 수집
  • 저장/취소 데이터를 기반으로 한 추천 품질 개선
  • 저장 프로젝트 진행률 및 체크리스트 기능 추가
  • 추천 프로젝트 커뮤니티 공유 기능
  • DBTI 기반 팀원 매칭 기능
  • AI 응답 JSON schema 검증 및 재요청 로직 강화
  • 실제 배포 환경 기준의 인증 보안 강화

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages