diff --git a/README.md b/README.md
index 660b835..923918a 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,29 @@
-# SobokSobok-Server
-SobokSobok server with Java, Spring
+
+## 프로젝트
+# 소복소복
+
+> 소중한 사람과 함께하는 복약 체크 서비스 💊
+
+
+
+## 💭 프로젝트 설명
+
+> 여러분은 소중한 사람의 건강을 지키기 위해 어떤 노력을 하고 계신가요?
+>
+> 걱정되는 마음은 있지만, 막상 내가 매일 무언가 행동하는 건 쉽지 않죠.
+> 일상이 바쁜 당신을 위해서 소복소복이 여러분의 일을 줄여드려요.
+> 소복소복에서는 소중한 사람이 약을 제 때 먹었는지 직접 물어보지 않고도 체크할 수 있거든요.
+>
+> **나의 복약 체크는 물론, 소중한 사람의 복약까지 확인할 수 있는 ‘소복소복’**
+> **우리의 건강을 챙기는 매일의 실천입니다** 🙂
+
+
+
+## 💭 프로젝트 핵심 기능
+
+- 메인 나의 복약을 체크하고, 상대방이 보내준 응원스티커를 확인할 수 있습니다.
+- 공유 소중한 사람의 복약 캘린더를 확인하고, 응원을 보낼 수 있습니다.
+- 알림 캘린더 공유 요청과 전송받은 복약 정보를 확인할 수 있습니다.
+- 약 추가 내 복약 정보를 추가하고, 소중한 사람에게 복약 일정을 전송할 수 있습니다.
+
+
diff --git a/build.gradle b/build.gradle
index e1a6dc3..f2f0577 100644
--- a/build.gradle
+++ b/build.gradle
@@ -57,6 +57,10 @@ dependencies {
// Health Check
implementation 'org.springframework.boot:spring-boot-starter-actuator'
+
+ // AWS
+ implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1")
+ implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs'
}
tasks.named('bootBuildImage') {
diff --git a/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java b/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java
index 318a810..be6c113 100644
--- a/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java
+++ b/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java
@@ -44,6 +44,7 @@ public SocialSignupResponse signup(SocialSignupRequest request) {
.build())
.deviceToken(request.deviceToken())
.roles(Role.USER.name())
+ .platform(request.platform())
.build());
Jwt jwt = jwtProvider.getUserJwt(signupUser.getSocialInfo().getSocialId());
@@ -69,6 +70,10 @@ public SocialLoginResponse login(SocialLoginRequest request) {
loginUser.updateDeviceToken(request.deviceToken());
}
+ if (!request.platform().equals(loginUser.getPlatform())) {
+ loginUser.updatePlatform(request.platform());
+ }
+
Jwt jwt = jwtProvider.getUserJwt(loginUser.getSocialInfo().getSocialId());
return SocialLoginResponse.builder()
diff --git a/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java b/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java
new file mode 100644
index 0000000..af26e23
--- /dev/null
+++ b/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java
@@ -0,0 +1,11 @@
+package io.sobok.SobokSobok.auth.domain;
+
+import lombok.Getter;
+
+@Getter
+public enum Platform {
+
+ iOS,
+ ANDROID,
+ ;
+}
diff --git a/src/main/java/io/sobok/SobokSobok/auth/domain/User.java b/src/main/java/io/sobok/SobokSobok/auth/domain/User.java
index d6d91b7..0f719a9 100644
--- a/src/main/java/io/sobok/SobokSobok/auth/domain/User.java
+++ b/src/main/java/io/sobok/SobokSobok/auth/domain/User.java
@@ -49,12 +49,17 @@ public class User extends BaseEntity implements UserDetails {
@Column
private String leaveReason;
+ @Column
+ @Enumerated(EnumType.STRING)
+ private Platform platform;
+
@Builder
- public User(String username, SocialInfo socialInfo, String deviceToken, String roles) {
+ public User(String username, SocialInfo socialInfo, String deviceToken, String roles, Platform platform) {
this.username = username;
this.socialInfo = socialInfo;
this.deviceToken = deviceToken;
this.roles = roles;
+ this.platform = platform;
}
public void updateDeviceToken(String newDeviceToken) {
@@ -65,6 +70,10 @@ public void changeUsername(String username) {
this.username = username;
}
+ public void updatePlatform(Platform platform) {
+ this.platform = platform;
+ }
+
public void deleteUser(String leaveReason) {
this.deviceToken = null;
this.username = null;
diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java b/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java
index 9219c88..d7c40ee 100644
--- a/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java
+++ b/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java
@@ -2,6 +2,7 @@
import io.sobok.SobokSobok.auth.application.AuthService;
import io.sobok.SobokSobok.auth.application.SocialService;
+import io.sobok.SobokSobok.auth.domain.Platform;
import io.sobok.SobokSobok.auth.domain.User;
import io.sobok.SobokSobok.auth.ui.dto.*;
import io.sobok.SobokSobok.common.dto.ApiResponse;
@@ -9,6 +10,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -48,8 +50,9 @@ public ResponseEntity> signup(
)
public ResponseEntity> login(
@RequestParam final String socialId,
- @RequestParam final String deviceToken
- ) {
+ @RequestParam final String deviceToken,
+ @RequestParam final Platform platform
+ ) {
return ResponseEntity
.status(HttpStatus.OK)
@@ -58,6 +61,7 @@ public ResponseEntity> login(
socialService.login(SocialLoginRequest.builder()
.socialId(socialId)
.deviceToken(deviceToken)
+ .platform(platform)
.build())
));
}
diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java
index ab6f111..c8640f7 100644
--- a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java
+++ b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java
@@ -1,6 +1,8 @@
package io.sobok.SobokSobok.auth.ui.dto;
+import io.sobok.SobokSobok.auth.domain.Platform;
import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
@Builder
@@ -10,6 +12,10 @@ public record SocialLoginRequest(
String socialId,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
- String deviceToken
+ String deviceToken,
+
+ @Schema(requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull
+ Platform platform
) {
}
diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java
index dce7b20..e8b391a 100644
--- a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java
+++ b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java
@@ -1,7 +1,9 @@
package io.sobok.SobokSobok.auth.ui.dto;
+import io.sobok.SobokSobok.auth.domain.Platform;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
public record SocialSignupRequest(
@@ -15,6 +17,10 @@ public record SocialSignupRequest(
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
- String deviceToken
+ String deviceToken,
+
+ @Schema(requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull
+ Platform platform
) {
}
diff --git a/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java b/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java
new file mode 100644
index 0000000..89599f1
--- /dev/null
+++ b/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java
@@ -0,0 +1,45 @@
+package io.sobok.SobokSobok.config;
+
+import io.awspring.cloud.sqs.operations.SqsTemplate;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsAsyncClient;
+
+@Configuration
+public class SQSConfig {
+
+ @Value("${spring.cloud.aws.credentials.access-key}")
+ private String AWS_ACCESS_KEY;
+
+ @Value("${spring.cloud.aws.credentials.secret-key}")
+ private String AWS_SECRET_KEY;
+
+ @Value("${spring.cloud.aws.region.static}")
+ private String AWS_REGION;
+
+ @Bean
+ public SqsAsyncClient sqsAsyncClient() {
+ return SqsAsyncClient.builder()
+ .credentialsProvider(() -> new AwsCredentials() {
+ @Override
+ public String accessKeyId() {
+ return AWS_ACCESS_KEY;
+ }
+
+ @Override
+ public String secretAccessKey() {
+ return AWS_SECRET_KEY;
+ }
+ })
+ .region(Region.of(AWS_REGION))
+ .build();
+ }
+
+ @Bean
+ public SqsTemplate sqsTemplate() {
+ return SqsTemplate.newTemplate(sqsAsyncClient());
+ }
+}
diff --git a/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java
new file mode 100644
index 0000000..82691b7
--- /dev/null
+++ b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java
@@ -0,0 +1,26 @@
+package io.sobok.SobokSobok.external.aws.sqs;
+
+import io.awspring.cloud.sqs.operations.SendResult;
+import io.awspring.cloud.sqs.operations.SqsTemplate;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import software.amazon.awssdk.services.sqs.SqsAsyncClient;
+
+@Component
+public class SQSMessageSender {
+
+ private final SqsTemplate queueMessagingTemplate;
+
+ @Value("${spring.cloud.aws.sqs.name}")
+ private String QUEUE_NAME;
+
+ public SQSMessageSender(SqsAsyncClient sqsAsyncClient) {
+ this.queueMessagingTemplate = SqsTemplate.newTemplate(sqsAsyncClient);
+ }
+
+ public SendResult sendMessage(SQSPushNotificationRequest request) {
+ return queueMessagingTemplate.send(to -> to
+ .queue(QUEUE_NAME)
+ .payload(request));
+ }
+}
diff --git a/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java
new file mode 100644
index 0000000..0e630e4
--- /dev/null
+++ b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java
@@ -0,0 +1,11 @@
+package io.sobok.SobokSobok.external.aws.sqs;
+
+public record SQSPushNotificationRequest(
+
+ String deviceToken,
+
+ String title,
+
+ String content
+) {
+}