Project Feed-a(피다)
발표자 최경진
Team 6pring(식스프링)
CONTENTS
팀 및 프로젝트 소개
주요 기능 및 API
프로젝트 진행 과정
팀원별 트러블슈팅
사용 기술 및 구조
팀원별 회고
01
04
02
05
03
06
팀 소개
최경진
김나경
안요한
이의현
팀장
팀원
팀원
팀원
프로필 기능 구현
게시글 댓글 API 구현
회원 관리 기능 구현
Entity, Repository 설계
게시글 댓글/좋아요 API 구현
전역 예외 처리
게시글 기능 구현
게시글 좋아요 API 구현
팔로우 기능 구현
페이징 처리
테스트 코드 작성 (일부분)
게시글 리팩토링
프로젝트 소개
개발자, 학생, 그리고 자기 계발에 관심 있는 모두가 모여
서로의 스터디 정보와 노하우를 나누는 커뮤니티 SNS입니다.
스터디 모집 및 경험 공유
질문과 답변을 통한 지식 나눔
성장과 동기부여를 위한 소통 공간
함께 배우고, 성장하는 즐거움을 경험 시켜 드릴수가 있을 것 같습니다.
피다(Feed-a)
프로젝트 진행 과정
역할 분담
와이어 프레임 작성
ERD, API 명세서 작성
Git 전략 수립
프로필 관리
뉴스피드 게시물 관리
사용자 인증 �친구 관리
검색 및 정렬 기능
댓글
좋아요
PPT 자료 준비
시연 영상 자료 준비
발표 준비
프로젝트 계획
필수 기능 구현
도전 기능구현
발표 준비
01
02
03
04
사용 기술 및 구조
핵심 기술 스택
ERD
와이어 프레임
구조
도메인 중심 패키징
구조
전역 예외 처리 + 커스텀 예외 응답
사용 기술
Spring Security + JWT Filter
사용 기술
Redis Cloud
Git (1)
- 동일 Organization을 통한 권한 및 Branch 관리
- issue 생성 => branch 자동 생성 github action 로직을 통해 명칭을 통일하고 개발 흐름을 효율적으로 확인
🛠 Github 전략 및 협업 방식 (1)
Git (2)
- Pull Request 개발 브랜치 develop 병합 리뷰어를 최소 2인으로 제한
- 팀원의 병합 승인 이후 병합 가능
=> 서로의 코드 이해 향상 및 병합 전 오류 최소화
🛠 Github 전략 및 협업 방식 (2)
게시글 기능
HTTP 메서드 | URL |
POST | /api/posts |
GET | /api/posts/{id} |
GET | /api/posts?page={page}&size={size}&keyword={keyword}&startUpdatedAt={startUpdatedAt}&endUpdatedAt={endUpdatedAt} |
GET | /api/posts/followings?page={page}&size={size} |
PUT | /api/posts/{id} |
DELETE | /api/posts/{id} |
주요 기능 및 API
주요 기능 및 API
사용자 인증 기능
HTTP 메서드 | URL |
POST | /api/accounts |
DELETE | /api/accounts/me |
PATCH | /api/accounts/password |
POST | /api/accounts/login |
POST | /api/accounts/logout |
프로필 기능
HTTP 메서드 | URL |
POST | 회원 가입시 자동 생성 |
GET | /api/profiles/{id} |
GET | /api/profiles?page={page}&size={size} |
PUT | /api/profiles/me |
주요 기능 및 API
팔로우 기능
HTTP 메서드 | URL |
POST | /api/follows/{profileId} |
DELETE | /api/follows/{followingId} |
GET | /api/follows/followings?page={page}&size={size} |
GET | /api/follows/followers?page={page}&size={size} |
GET | /api/follows/{profiileId}/followings?page={page}&size={size} |
GET | /api/follows/{profiileId}/followers?page={page}&size={size} |
주요 기능 및 API
게시글 댓글 기능
HTTP 메서드 | URL |
POST | 회원 가입시 자동 생성 |
GET / 단건 | /api/comments/{id} |
GET / 다건 | /api/comments/posts/{postId} |
PATCH | /api/comments/{id} |
DELETE | /api/comments/{id} |
주요 기능 및 API
영상 시연
팀원별 트러블슈팅
Spring Security + JWT 예외 처리 문제
상황
원인
Spring MVC 가 내부적으로 /error 경로로 foward 함
Security 인증 실패 메시지가 응답됨
해결 방법
팀원별 트러블슈팅
문제 요약
기존에는 단순히 profileId만 받아서 좋아요를 삭제했기 때문에,� 다른 사용자의 profileId를 알기만 하면 누구든 삭제 요청이 가능한 보안 취약점(IDOR: Insecure Direct Object Reference)이 발생함.
해결
JWT 인증 정보를 활용하여 현재 로그인한 사용자의 profileId를 서버에서 직접 추출하고, 해당 사용자만 자신의 좋아요를 삭제할 수 있도록 함.
@DeleteMapping("/{id}/likes")
public ResponseEntity<PostResponseDto> deleteLikes(
@PathVariable Long id,
@AuthenticationPrincipal JwtPayload jwtPayload) {
Long profileId = jwtPayload.getProfileId(); // 현재 로그인한 사용자 ID 추출
// 인증된 사용자만 자신의 좋아요 삭제 가능
return new ResponseEntity<>(postService.deleteLikes(id, profileId), HttpStatus.OK);}
흐름: 단순히 profileId를 받아서 삭제하기 때문에,
다른 사용자의 profileId를 알고 있으면
그 사람의 좋아요도 삭제할 수 있게 되어 보안상 문제 발생
수정자 권한 미검증으로 인한 수직적 접근 통제 실패
팀원별 트러블슈팅
원인
Java
// 문제된 코드
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDateTime startUpdatedAt
해결
Java
// 수정된 코드
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startUpdatedAt
문제
기간 조회 API 구현 중 String → LocalDateTime 변환 에러 발생
LocalDateTime -> LocalDate 변경
DB로직에서는 LocalDate -> LocalDateTime 타입변경하여 수행
LocalDateTime 형식 변환 문제
팀원별 트러블슈팅
// 문제 코드
GetProfileResponseDto dto = new GetProfileResponseDto();
dto.setAccountId(profile.getAccountId()); // setter 사용
해결: 생성자 기반 불변 객체로 통일
// 개선 코드
GetProfileResponseDto dto = new GetProfileResponseDto(
profile.getAccountId(),
profile.getNickname(),
profile.getBirth()
);
문제:
setter와 생성자 방식이 혼재되어 컴파일 에러 발생
DTO 필드 주입 방식 혼동
팀원별 회고
최경진:
김나경:
이의현:
안요한:
지금까지 개인 프로젝트만 진행했었기에 다른 팀원분들의 코드를 리뷰하며 몰랐던 부분을 확인하고, 비슷한 코드라도 더 좋은 방식이 있는 것을 알게 되어 유익한 시간이었습니다.
전체 프로젝트를 설계하고 구현하는 맥락을 처음부터 끝까지 차근차근 모두 배워나갈 수 있는 시간이었습니다.
서로의 코드를 직접 보며 의견을 나눈 과정이 큰 도움이 되었습니다. 각기 다른 접근 방식과 개선할 점을 발견하면서 부족한 부분도 깨닫게 되었고, 함께 성장할 수 있는 소중한 시간이었습니다.
팀 프로젝트를 통해 설계부터 구현까지의 전체 개발 과정을 체계적으로 학습하고, 다양한 접근 방식과 효율적인 코딩 기법을 익힐 수 있었습니다. 특히 스프링 학습 과정에서 팀원들과의 코드 리뷰와 협업을 통해 함께 성장하는 값진 경험을 얻었습니다.
감사합니다
발표자 최경진
Team 6pring(식스프링)