인스타그램을 모티브로 하여 만든 Rest API 서버입니다.
- 목적 : 지인, 가족, 친구들간에 사진과 글을 공유하는 서비스 개발
- 기간 : 2022년 7월 25일 ~ 2023년 4월 3일
- 팀 구성 : 백엔드 1명
- ✍ 프로젝트 전체 업무 관리
- 📰 API 명세서
ERD는 다음과 같은 기준으로 설계하였습니다.
- 공통 설계 기준
- 소문자 사용
- 단어 축약 X : password (O), pwd (X)
- 동사는 능동태 사용 : create_at(O), created_at(X)
- 테이블 설계 기준
- 단수형 사용
- 테이블 명에 snake case(_) 사용
- 칼럼 설계 기준
- 칼럼 명에 snake case(_) 사용
- password 칼럼 : 암호화된 패스워드 문자열을 저장하므로 VARCHAR(200)으로 지정
- image 칼럼 : 게시글 이미지에 대한 URL을 TEXT 타입으로 저장
- status 칼럼 : JPA Entity 클래스의 Enem 타입 status 상수와 매핑하기 위해 VARCHAR 타입 사용
- MySQL 데이터 타입 지정 기준
- BIGINT 타입 : 많은 사용자를 감당하기 위해 idx 칼럼에 지정
- VARCHAR 타입 : 영문 1바이트, 한글 3바이트임을 고려하여 각 칼럼에 바이트 할당
- TIMSTAMP 타입 : 테이블에서 하나의 row의 값들이 생성(created_at)되고 변경(updated_at)될때마다 시각을 기록하기 위해 사용하며, JPA Entity 클래스의 LocalDateTime 타입 필드와 매핑
게시글(Post) 엔티티 설계
@Entity
@Table(name = "post")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idx;
@Column (nullable=false, columnDefinition="varchar(3002)")
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_idx")
private User user;
@Column (nullable=true, columnDefinition ="varchar(10) default 'VISIBLE'")
@Enumerated(EnumType.STRING)
private PostStatus postStatus;
@Column (columnDefinition = "varchar(10) default 'ACTIVE'")
@Enumerated(EnumType.STRING)
private DataStatus status;
@Column (columnDefinition = "timestamp default CURRENT_TIMESTAMP")
private LocalDateTime createdAt;
@Column (columnDefinition = "timestamp default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
private LocalDateTime updatedAt;
@OneToMany(mappedBy = "post")
private List<PostImage> postImages = new ArrayList<>();
}
- 회원가입과 게시글 조회 API 호출시의 서버 동작 흐름입니다.
- 회원가입 API 동작 흐름
- Client <-> UserController <-> UserService <-> UserRepository <-> MySQL DB
- 게시글 조회 API 동작 흐름
- Client <-> Interceptor <-> Local Cache <-> PostController <-> PostService <-> PostRepository <-> MySQL DB
- 기타 API의 백엔드 로직 흐름은 시퀀스 다이어그램을 참고해 주시면 감사합니다.
📂 src
└── 📂 main
├── 📂 java.com.instagram
| ├── 📂 domain #도메인 관리
| | ├── 📂 comment
| | ├── 📂 commentLike
| | ├── 📂 follow
| | ├── 📂 followReq
| | ├── 📂 user
| | ├── 📂 postLike
| | ├── 📂 post #게시글 도메인
| | | ├── 📂 controller #컨트롤러 계층
| | | ├── 📂 service #서비스 계층
| | | ├── 📂 dao #레포지토리 계층
| | | ├── 📂 dto #데이터 전송
| | | └── 📂 domain #엔티티 관리
| | └── 📂 model #공통으로 사용되는 ENUM 클래스 정의
| ├── 📂 global #전체적인 설정 관리
| | ├── 📂 config #환경설정 관리 (인터셉터, 시큐리티, 스웨거)
| | ├── 📂 error #예외 처리 클래스 관리
| | ├── 📂 interceptor #인터셉터 관리
| | ├── 📂 util #유틸 클래스 관리
| | ├── 📂 Scheduler #스케줄러 관련
| | └── 📂 Security #보안 관련
| ├── 📂 infra #외부 인프라스트럭처 관리
| | └── 📂 aws #AWS 서비스 관리
| └── 📄 InstagramApplication.java #애플리케이션 실행 클래스
└── 📂 resources
└── 📄 applicaiton.yml #DB, 외부서비스, 로그 등의 연결 설정
📄 .gitignore #깃허브 업로드시 제외 파일 관리
📄 build.gradle
📄 README.md
- 도메인형으로 패키지 구조를 설계했습니다.
- 디렉터리별 세부 파일 구조는 Wiki를 참고해 주시면 감사합니다.
- ERD와 JPA 엔티티 설계
- Rest API 설계
- 도메인형으로 패키지 구조 설계
- 단방향 암호화로 패스워드 외부 노출 방지
- 룰 기반 파일 업로드 실행
- 페이징을 통해 API의 응답시간 개선
- 캐시 도입으로 응답시간 개선
- 슬로우 쿼리를 JPA 메서드로 리팩토링하여 쿼리 실행 시간 99.73% 개선
applicaiton.yml 파일에 애플리케이션 정보, DB 정보, AWS S3 정보를 기입해 주시면 됩니다.
# Application
server:
port: 10000
# MYSQL DB
spring:
datasource:
url:
username:
password:
# AWS S3
cloud:
aws:
credentials:
access-key:
secret-key:
region:
static:
s3:
bucket:
stack:
auto:
# 프로젝트 빌드
$ ./gradlew clean build
# Jar 파일 실행
$ java -jar build/libs/Instagram_Clone_Server-0.0.1-SNAPSHOT.jar
http://localhost:10000/swagger-ui/