Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
8bf6c3f
chore: BaseEntity 생성
bebeis May 1, 2025
7718ece
feat(MemberPassword): 회원 비밀번호 관련 기능 구현
bebeis May 1, 2025
47b4b6d
feat(memberPassword): 회원 비밀번호 정책 추가
bebeis May 1, 2025
5281311
fix(memberPassword): 회원 비밀번호 검증 로직 추가
bebeis May 2, 2025
d9d9564
test(memberPassword): 비밀번호 관련 로직 테스트
bebeis May 2, 2025
5847518
docs(table): DB 스키마 추가
bebeis May 3, 2025
1eeb9ee
fix(MemeberAuth): 테이블명 매핑 수정 및 이메일 검증 메서드 추가
bebeis May 3, 2025
3ef64c2
feat(MemberProfile): 회원 프로필 엔티티 추가
bebeis May 3, 2025
13631a0
feat(socialAccount) 소셜 계정 엔티티 추가
bebeis May 3, 2025
3d8d90a
fix(-): BaseEntity 변수명 수정
bebeis May 3, 2025
07650b8
refactor: BaseEntity 클래스 상속 관계로 분리
bebeis May 10, 2025
e83267e
feat(Address): address 도메인 추가
bebeis May 10, 2025
25c8325
fix: 생성일/수정일 Auditing 애노테이션 추가
bebeis May 10, 2025
7f3c0a4
refactor(password): 빌더 패턴 제거
bebeis May 10, 2025
1c6f6fd
feat(SocialAccount): 도메인 기능 구현
bebeis May 10, 2025
2fa7fac
feat(MemberProfile): 도메인 기능 구현
bebeis May 10, 2025
54b2442
feat(MemberAuth): 도메인 기능 추가
bebeis May 10, 2025
b747ac6
feat(budget): 예산 도메인 추가
bebeis May 11, 2025
60d28c6
fix: PK 칼럼명 수정
bebeis May 11, 2025
e51a39d
feat: AddressType 종류 추가
bebeis May 11, 2025
80cf73b
refactor: password 테스트 코드 수정
bebeis May 11, 2025
cbb62d5
refactor(budget): budget 기능 리팩토링
bebeis May 11, 2025
21ee09d
test(budget): 예산 도메인 테스트 코드 작성
bebeis May 11, 2025
75fd664
refactor: 회원 클래스명 수정
bebeis May 11, 2025
e60e978
feat: OAuth 스펙 객체 구현
bebeis May 12, 2025
201cc95
refactor: provider 타입 변경
bebeis May 12, 2025
4c02e6d
feat: jwt 토큰 관련 기능 구현
bebeis May 12, 2025
b3055b4
chore: jwt 라이브러리 의존성 추가
bebeis May 13, 2025
28435d9
feat(food): food 엔티티 추가
bebeis May 13, 2025
31d2e4f
fix(member): 엔티티 필드 수정
bebeis May 13, 2025
b5f7cc5
fix(memberProfile): 그룹 추가 및 변수명 리팩토링
bebeis May 13, 2025
26534cc
refactor: 토큰 관련 클래스 역할 분리
bebeis May 13, 2025
108d3a2
feat: 이메일로 엔티티 조회하는 메서드 추가
bebeis May 13, 2025
1f31793
feat: 소셜 계정 필드 추가
bebeis May 13, 2025
bdab141
feat(socialAccount): 소셜 계정 비즈니스 로직 구현
bebeis May 13, 2025
d3de818
refactor: 클래스명 수정
bebeis May 13, 2025
46e4b2f
feat: jwt 헤더 argument resovler 구현
bebeis May 13, 2025
38d27c7
refactor: 공통 응답 객체 리팩토링
bebeis May 13, 2025
5fafcaf
fix: 토큰 응답 Dto 생성자 수정
bebeis May 13, 2025
1ac7e46
feat(Auth): 인증 api 엔드포인트 구현
bebeis May 13, 2025
fcc1b4c
feat: 이메일 중복, 회원 생성 api 구현
bebeis May 13, 2025
d1fdd02
fix: 테이블명 수정
bebeis May 13, 2025
3448531
fix: api uri 수정
bebeis May 13, 2025
e54b69d
refactor: 상수 클래스 리팩토링
bebeis May 13, 2025
4231d56
fix: 상태 체크 오류 수정
bebeis May 13, 2025
ed97fcd
fix: 오류 수정
bebeis May 13, 2025
478f2ea
chore: CORS 설정 등록
bebeis May 13, 2025
6196b61
test: 로깅 추가
bebeis May 13, 2025
ed5432f
fix: 스프링 빈을 다시 생성하는 오류 수정
bebeis May 13, 2025
6407e0f
chore: jwt json 직렬화 라이브러리 추가
bebeis May 13, 2025
d7e1b7a
feat: Google 로그인 커맨드 객체 구현
bebeis May 13, 2025
83734cf
fix: 엔티티 PK 생성 전략 수정
bebeis May 15, 2025
9ed41da
chore: docker 설정
bebeis May 15, 2025
63d13c3
chore: docker 설정
bebeis May 15, 2025
d70977d
Revert "chore: docker 설정"
bebeis May 15, 2025
bca63af
Merge remote-tracking branch 'origin/feat/kan-48-member' into feat/ka…
bebeis May 15, 2025
029e64b
chore: ci/cd 설정
bebeis May 15, 2025
5e8fdf3
fix: 필드명으로 인한 엔티티 임시 제거
bebeis May 15, 2025
f54ed2b
fix: gitignore 수정
bebeis May 15, 2025
bc45c9d
fix: gitignore 수정
bebeis May 15, 2025
63008d2
chore: ci/cd configuration 적용
bebeis May 15, 2025
83e746c
fix: ci/cd 브랜치 수정
bebeis May 15, 2025
9a929d1
fix: 환경변수 프로파일 수정
bebeis May 15, 2025
0f00b68
refactor: 디렉터리 수정
bebeis May 18, 2025
6ca4df7
refactor: 패키지 구조 개선
bebeis May 19, 2025
1c60575
refactor: 회원 엔티티 매핑 개선
bebeis May 19, 2025
4517d22
refactor: infra 계층 분리
bebeis May 19, 2025
b2f33d1
feat: 주소 좌표 변환 client 구현
bebeis May 19, 2025
5293e57
fix: 엔티티 칼럼명 수정
bebeis May 19, 2025
4855965
feat: 소셜 - 이메일 계정 연동 기능 구현
bebeis May 19, 2025
185eb19
feat: 회원 프로필 조회 API 구현
bebeis May 19, 2025
3515a5f
refactor: 일부 필드 및 클래스 명 수정
bebeis May 19, 2025
47c1aca
feat: 회원 로그인 기능 구현
bebeis May 19, 2025
05b531d
chore: data redis 의존성 추가
bebeis May 20, 2025
0a86520
feat: logout 기능 구현
bebeis May 20, 2025
eefc897
fix: Api 명세와 다른 엔드포인트 수정
bebeis May 20, 2025
48a89dc
fix: Api 명세와 다른 엔드포인트 수정 2
bebeis May 20, 2025
365f320
refactor: 주소 클래스 설계 변경
bebeis May 21, 2025
6caa0d1
refactor: Aggregate Root 분리
bebeis May 21, 2025
cb273dc
refactor: Jwt 인가 로직 개선
bebeis May 21, 2025
77e94ae
feat: Group 엔티티 설계
bebeis May 21, 2025
3d99620
feat: 프로필 조회/생성 기능 구현
bebeis May 21, 2025
472364b
refactor: Group과 Type 분리
bebeis May 21, 2025
0b3c9ff
feat: 회원 프로필 변경 구현
bebeis May 21, 2025
c92b227
feat: 대표 주소 변경 구현
bebeis May 21, 2025
c569f9f
refactor: 서비스 계층 트랜잭션 최적화
bebeis May 21, 2025
4cdf6aa
fix: 대표 주소 변경 응답 객체 누락 수정
bebeis May 21, 2025
b7720ed
refactor: 값 타입 필드 일부를 엔티티로 이전
bebeis May 21, 2025
f3be263
refactor: 필드 결합도 개선
bebeis May 21, 2025
eb25d09
feat: 회원 주소 추가 기능 구현
bebeis May 21, 2025
c5ddbdd
feat: 주소 수정 기능 구현
bebeis May 21, 2025
897e594
feat: 회원 주소 삭제 기능 구현
bebeis May 21, 2025
84a662f
fix: JPA 매핑 관련 오류 수정
bebeis May 21, 2025
e532369
feat: 그룹 조회 기능 구현
bebeis May 21, 2025
2ae47b9
fix: Api 명세와 다른 부분 수정
bebeis May 21, 2025
3cdafa9
feat: Term 도메인 개발
bebeis May 21, 2025
8bff8bb
feat: 회원 가입 최종 완료 기능 구현
bebeis May 21, 2025
32045a2
refactor: 음식 선호도 엔티티 구조 변경
bebeis May 22, 2025
d61b6c5
feat: Budget 등록 기능 구현
bebeis May 22, 2025
a3972c9
feat: budget 등록 api 구현
bebeis May 22, 2025
4205386
chore: swagger 의존성 추가
bebeis May 22, 2025
915b42c
fix: api URI 오타 수정
bebeis May 22, 2025
2153a14
fix: ArgumentResolver 대상 객체 Swagger Docs에서 제거
bebeis May 22, 2025
4fa2a1a
fix: swagger에서 응답 DTO가 보이지 않던 문제 수정
bebeis May 22, 2025
6bf81a5
test: Auth 도메인 테스트 코드 추가
bebeis May 22, 2025
a4f382c
chore: CORS Origins 추가
bebeis May 22, 2025
0c4d19e
refactor: 전역 ControllderAdvice로 예외처리
bebeis May 22, 2025
67c3c3b
feat: 예외 처리 추가
bebeis May 22, 2025
d612e7e
feat: HandlerMethodValidation 예외 검증 추가
bebeis May 22, 2025
749db89
chore: 테스트용 메모리 DB 추가
bebeis May 22, 2025
10d452a
fix: 회원 비밀번호 관련 로직 수정
bebeis May 22, 2025
1ee9df2
fix: 이메일 중복 검사 잘못된 로직 수정
bebeis May 22, 2025
1d4e0db
refactor: Group Service 인터페이스 분리
bebeis May 22, 2025
d83eed1
refactor: 공통 응답 객체 메서드 일부 수정
bebeis May 22, 2025
57a44fc
chore: 테스트 관련 Config 등록
bebeis May 22, 2025
5f78f94
test: 도메인 계층 테스트 구현
bebeis May 22, 2025
8826de6
test: 서비스 계층 테스트 작성
bebeis May 22, 2025
88eb7de
test: spring 커스텀 Argument Resolver 테스트
bebeis May 22, 2025
f88fd87
test: 회원 통합 테스트 작성
bebeis May 22, 2025
1806c66
test: 이용 약관 조회 API 테스트 작성
bebeis May 22, 2025
250d6f4
test: 그룹 정보 조회 API 테스트 작성
bebeis May 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Build & Deploy to EC2

on:
push:
branches: [ development ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Java 21
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 21

- name: Cache Gradle
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: ${{ runner.os }}-gradle-

- name: Build JAR with dev profile
run: ./gradlew bootJar --no-daemon -Dspring.profiles.active=dev

- name: Docker Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build & Push Docker Image
uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
push: true
tags: docker.io/${{ secrets.DOCKERHUB_USER }}/smart-meal-table:${{ github.sha }}

deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Install SSH
run: sudo apt-get update && sudo apt-get install -y openssh-client

- name: Setup SSH Key
env:
SSH_KEY: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
echo -e "Host *\n\tStrictHostKeyChecking no\n" > ~/.ssh/config

- name: Deploy to EC2
run: |
ssh ubuntu@${{ secrets.EC2_HOST }} << 'EOF'
# 1) 기존 컨테이너 제거
docker rm -f smart-meal-table || true
# 2) 최신 이미지 pull
docker pull docker.io/${{ secrets.DOCKERHUB_USER }}/smart-meal-table:${{ github.sha }}
# 3) 컨테이너 실행 (dev 프로파일)
docker run -d \
--name smart-meal-table \
-v /home/ubuntu/app:/config \
-e SPRING_PROFILES_ACTIVE=dev \
-p 8080:8080 \
docker.io/${{ secrets.DOCKERHUB_USER }}/smart-meal-table:${{ github.sha }}
EOF
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,12 @@ gradle-app.setting
# Java heap dump
*.hprof

# yml
# 모든 yml 파일 무시
*.yml

# → 하지만 GitHub Actions 워크플로우는 예외 처리
!/.github/
!/.github/workflows/
!/.github/workflows/ci-cd.yml

# End of https://www.toptal.com/developers/gitignore/api/java,intellij,macos,gradle,git,maven,visualstudiocode,windows
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM openjdk:21-jdk

LABEL authors="luna"

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} app.jar

ENV SPRING_PROFILES_ACTIVE=dev

ENTRYPOINT ["java","-jar", "/app.jar"]
58 changes: 34 additions & 24 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.4'
id 'io.spring.dependency-management' version '1.1.7'
id 'java'
id 'org.springframework.boot' version '3.4.4'
id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.stcom'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' // JSON 직렬화/역직렬화에 Jackson 사용
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testImplementation 'com.h2database:h2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}

jar {
enabled = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class SmartmealtableApplication {

public static void main(String[] args) {
SpringApplication.run(SmartmealtableApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(SmartmealtableApplication.class, args);
}

}
55 changes: 55 additions & 0 deletions src/main/java/com/stcom/smartmealtable/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.stcom.smartmealtable.config;

import com.stcom.smartmealtable.web.argumentresolver.UserContext;
import com.stcom.smartmealtable.web.dto.ApiResponse;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springdoc.core.utils.SpringDocUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.MethodParameter;

@Configuration
@Profile({"local", "dev"})
@SecurityScheme(
name = "bearerAuth",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT",
in = SecuritySchemeIn.HEADER
)
@OpenAPIDefinition(
security = @SecurityRequirement(name = "bearerAuth"),
info = @Info(
title = "SmartMealTable API 문서",
version = "v1",
description = "SmartMealTable API 명세서입니다."
)
)
public class SwaggerConfig {

static {
SpringDocUtils.getConfig().addAnnotationsToIgnore(UserContext.class)
.addResponseWrapperToIgnore(ApiResponse.class);
}

@Bean
public OperationCustomizer userContextSecurityCustomizer() {
return (operation, handlerMethod) -> {
for (MethodParameter param : handlerMethod.getMethodParameters()) {
if (param.hasParameterAnnotation(UserContext.class)) {
operation.addSecurityItem(
new io.swagger.v3.oas.models.security.SecurityRequirement().addList("bearerAuth"));
break;
}
}
return operation;
};
}
}
44 changes: 44 additions & 0 deletions src/main/java/com/stcom/smartmealtable/domain/Address/Address.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.stcom.smartmealtable.domain.Address;

import jakarta.persistence.Embeddable;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Embeddable
@NoArgsConstructor
public class Address {

private String lotNumberAddress;

private String roadAddress;

private String detailAddress;

private Double latitude;

private Double longitude;

@Builder
public Address(String lotNumberAddress, String roadAddress, String detailAddress, String alias, Double latitude,
Double longitude, AddressType type) {
this.lotNumberAddress = lotNumberAddress;
this.roadAddress = roadAddress;
this.detailAddress = detailAddress;
this.latitude = latitude;
this.longitude = longitude;
}


public void updateAddress(String lotNumberAddress, String roadAddress, String detailAddress,
Double latitude, Double longitude) {
this.lotNumberAddress = lotNumberAddress;
this.roadAddress = roadAddress;
this.detailAddress = detailAddress;
this.latitude = latitude;
this.longitude = longitude;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.stcom.smartmealtable.domain.Address;

import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor
@Getter
@Table(name = "address")
public class AddressEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "address_id")
private Long id;

@Embedded
private Address address;

@Column(name = "is_primary")
private boolean primary = false;

@Enumerated(EnumType.STRING)
private AddressType type;

private String alias;

@Builder
public AddressEntity(Address address, AddressType type, String alias) {
this.address = address;
this.type = type;
this.alias = alias;
}

public AddressEntity(Address address) {
this.address = address;
}

public void markPrimary() {
this.primary = true;
}

public void unmarkPrimary() {
this.primary = false;
}

public boolean isPrimaryAddress() {
return primary;
}

public void changeAddressType(AddressType newType) {
this.type = newType;
}

public void changeAlias(String newAlias) {
this.alias = newAlias;
}


public void changeAddress(Address newAddress) {
this.address = newAddress;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.stcom.smartmealtable.domain.Address;

public enum AddressType {
HOME, SCHOOL, OFFICE, ETC
}
Loading