Skip to content

Commit 07c3492

Browse files
committed
Merge branch 'develop' of https://github.com/kookmin-sw/capstone-2024-17 into #380-edit-design
2 parents f18903c + fafcdc0 commit 07c3492

34 files changed

+383
-95
lines changed

backend/src/main/java/com/coffee/backend/domain/auth/service/KakaoLoginService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public KakaoUserInfoDto getUserInfo(String accessToken) {
4141
userInfoURI, HttpMethod.GET, request, String.class);
4242

4343
if (response.getStatusCode() == HttpStatus.OK) {
44+
log.debug("kakaoResponse {}", response.getBody());
4445
return objectMapper.readValue(response.getBody(), KakaoUserInfoDto.class);
4546
} else {
4647
throw new RuntimeException("Failed to retrieve user info from Kakao API");

backend/src/main/java/com/coffee/backend/domain/cafe/service/CafeService.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import com.coffee.backend.domain.user.entity.User;
55
import com.coffee.backend.domain.user.repository.UserRepository;
66
import com.coffee.backend.domain.user.service.UserService;
7-
import com.coffee.backend.exception.CustomException;
8-
import com.coffee.backend.exception.ErrorCode;
97
import java.util.Collections;
108
import java.util.List;
119
import java.util.Objects;
@@ -101,11 +99,12 @@ public CafeUserDto getUserInfoFromDB(Long userId) {
10199

102100
public void clearSessionAndCafeIdBySessionId(String sessionId) {
103101
log.trace("clearSessionAndCafeIdBySessionId()");
104-
User user = userRepository.findBySessionId(sessionId).orElseThrow(() -> {
102+
Optional<User> user = userRepository.findBySessionId(sessionId);
103+
if (user.isEmpty()) {
105104
log.info("sessionId = {} 를 갖는 사용자가 존재하지 않습니다.", sessionId);
106-
return new CustomException(ErrorCode.USER_NOT_FOUND);
107-
});
108-
// redis 에서 cafeId 유저 삭제 및 cafeId, sessionId null 로 초기화
109-
deleteCafeChoice(user.getCafeId(), user.getUserId());
105+
} else {
106+
// redis 에서 cafeId 유저 삭제 및 cafeId, sessionId null 로 초기화
107+
deleteCafeChoice(user.get().getCafeId(), user.get().getUserId());
108+
}
110109
}
111110
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.coffee.backend.global;
2+
3+
import java.util.HashMap;
4+
import java.util.HashSet;
5+
import java.util.Map;
6+
import java.util.Set;
7+
import org.springframework.stereotype.Component;
8+
9+
@Component
10+
public class SubscriptionRegistry {
11+
private final Map<String, Set<String>> subscriptions = new HashMap<>();
12+
13+
// subscribe
14+
public synchronized void addSubscription(String sessionId, String destination) {
15+
subscriptions.computeIfAbsent(sessionId, k -> new HashSet<>()).add(destination);
16+
}
17+
18+
// 특정 세션이 특정 destination 을 구독 중인지 확인
19+
public synchronized boolean hasSubscription(String sessionId, String destination) {
20+
return subscriptions.containsKey(sessionId) && subscriptions.get(sessionId).contains(destination);
21+
}
22+
23+
// 구독 취소
24+
public synchronized void removeSubscription(String sessionId, String destination) {
25+
if (subscriptions.containsKey(sessionId)) {
26+
Set<String> destinations = subscriptions.get(sessionId);
27+
destinations.remove(destination);
28+
if (destinations.isEmpty()) {
29+
subscriptions.remove(sessionId);
30+
}
31+
}
32+
}
33+
34+
// 특정 세션의 모든 구독 취소
35+
public synchronized void removeSubscriptionsBySessionId(String sessionId) {
36+
subscriptions.remove(sessionId);
37+
}
38+
39+
// 전체 구독 정보를 출력
40+
public synchronized void printSubscriptions() {
41+
System.out.println("웹소켓 구독 정보: " + subscriptions);
42+
}
43+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.coffee.backend.global;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.context.event.EventListener;
5+
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
6+
import org.springframework.stereotype.Component;
7+
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
8+
import org.springframework.web.socket.messaging.SessionSubscribeEvent;
9+
import org.springframework.web.socket.messaging.SessionUnsubscribeEvent;
10+
11+
@Component
12+
public class WebSocketEventListener {
13+
private final SubscriptionRegistry subscriptionRegistry;
14+
15+
@Autowired
16+
public WebSocketEventListener(SubscriptionRegistry subscriptionRegistry) {
17+
this.subscriptionRegistry = subscriptionRegistry;
18+
}
19+
20+
// 구독 이벤트 발생 시, 구독 처리
21+
@EventListener
22+
public void handleSubscribeEvent(SessionSubscribeEvent event) {
23+
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
24+
String sessionId = headerAccessor.getSessionId();
25+
String destination = headerAccessor.getDestination();
26+
27+
// 이미 구독된 경우 pass
28+
if (destination != null && subscriptionRegistry.hasSubscription(sessionId, destination)) {
29+
return;
30+
}
31+
// 중복이 아닌 경우만 구독 추가
32+
subscriptionRegistry.addSubscription(sessionId, destination);
33+
subscriptionRegistry.printSubscriptions(); // 구독 정보 출력
34+
}
35+
36+
// 구독 취소 이벤트 발생 시, 구독 취소 처리
37+
@EventListener
38+
public void handleUnsubscribeEvent(SessionUnsubscribeEvent event) {
39+
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
40+
String sessionId = headerAccessor.getSessionId();
41+
String subscriptionId = headerAccessor.getSubscriptionId();
42+
43+
System.out.println(
44+
"구독 취소 이벤트 sessionId: " + sessionId + ", subscriptionId: " + subscriptionId);
45+
// 구독 취소 시 구독 정보 삭제
46+
subscriptionRegistry.removeSubscription(sessionId, subscriptionId);
47+
subscriptionRegistry.printSubscriptions(); // 구독 정보 출력
48+
}
49+
50+
// 웹소켓 disconnect 이벤트 발생 시, 해당 세션의 모든 구독 취소 처리
51+
@EventListener
52+
public void handleDisconnectEvent(SessionDisconnectEvent event) {
53+
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
54+
String sessionId = headerAccessor.getSessionId();
55+
56+
System.out.println("웹소켓 disconnect 이벤트 sessionId: " + sessionId);
57+
58+
// 연결 종료 시 모든 구독 정보 삭제
59+
subscriptionRegistry.removeSubscriptionsBySessionId(sessionId);
60+
subscriptionRegistry.printSubscriptions(); // 구독 정보 출력
61+
}
62+
}

frontend/android/app/build.gradle

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ if (flutterVersionName == null) {
3131
def googleMapApiKey = localProperties.getProperty('GOOGLE_MAP_KEY')
3232
def kakaoNativeAppKey = localProperties.getProperty('flutter.kakao.native.appKey')
3333

34+
// Gradle 서명 구성
35+
def keystoreProperties = new Properties()
36+
def keystorePropertiesFile = rootProject.file('app/key.properties')
37+
if (keystorePropertiesFile.exists()) {
38+
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
39+
}
40+
3441
android {
3542
namespace "com.example.frontend"
3643
compileSdkVersion 34
@@ -51,7 +58,7 @@ android {
5158

5259
defaultConfig {
5360
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
54-
applicationId "com.example.frontend"
61+
applicationId "com.example.careercup"
5562
// You can update the following values to match your application needs.
5663
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
5764
minSdkVersion 21
@@ -63,11 +70,28 @@ android {
6370

6471
}
6572

73+
signingConfigs {
74+
release {
75+
keyAlias keystoreProperties['keyAlias']
76+
keyPassword keystoreProperties['keyPassword']
77+
storeFile file(keystoreProperties['storeFile'])
78+
storePassword keystoreProperties['storePassword']
79+
}
80+
}
81+
6682
buildTypes {
83+
debug {
84+
signingConfig signingConfigs.debug
85+
}
6786
release {
6887
// TODO: Add your own signing config for the release build.
6988
// Signing with the debug keys for now, so `flutter run --release` works.
70-
signingConfig signingConfigs.debug
89+
90+
// 소스코드 암호화
91+
minifyEnabled true
92+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
93+
94+
signingConfig signingConfigs.release
7195
}
7296
}
7397
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## Flutter wrapper
2+
-keep class io.flutter.app.** { *; }
3+
-keep class io.flutter.plugin.** { *; }
4+
-keep class io.flutter.util.** { *; }
5+
-keep class io.flutter.view.** { *; }
6+
-keep class io.flutter.** { *; }
7+
-keep class io.flutter.plugins.** { *; }
8+
-dontwarn io.flutter.embedding.**

frontend/android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<application
99

10-
android:label="frontend"
10+
android:label="커리어 한잔"
1111
android:name="${applicationName}"
1212
android:icon="@mipmap/ic_launcher">
1313
<meta-data
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
3+
<background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
4+
<foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
5+
</adaptive-icon>
5.06 KB
Loading
852 Bytes
Loading

0 commit comments

Comments
 (0)