Skip to content

[Chore/#112] kakao key 추가#115

Open
taegeon2 wants to merge 3 commits into
developfrom
chore/#112-kakao-key
Open

[Chore/#112] kakao key 추가#115
taegeon2 wants to merge 3 commits into
developfrom
chore/#112-kakao-key

Conversation

@taegeon2
Copy link
Copy Markdown
Contributor

📝 요약

  • .env.example에 카카오 JS 키 항목을 추가했습니다.

⚙️ 작업 내용

  • .env.example에 EXPO_PUBLIC_KAKAO_JS_KEY 항목 추가

🔗 관련 이슈

✅ 체크리스트

  • 코딩 컨벤션(Biome/Lint)을 준수하였습니다.
  • 모든 타입 에러를 해결하였습니다. (Typecheck)
  • 변경 사항에 대한 테스트를 마쳤습니다.
  • 불필요한 로그(console.log)를 제거하였습니다.

💬 리뷰어에게

@taegeon2 taegeon2 self-assigned this May 25, 2026
@github-actions github-actions Bot added the chore 버전 코드 수정, 패키지 구조 변경 등 작은 작업 label May 25, 2026
@github-actions
Copy link
Copy Markdown

Thanks for the contribution!
I have applied any labels matching special text in your title and description.

Please review the labels and make any necessary changes.

@taegeon2 taegeon2 changed the title Chore/#112 kakao key [Chore/#112] kakao key May 25, 2026
@taegeon2 taegeon2 changed the title [Chore/#112] kakao key [Chore/#112] kakao key 추가 May 25, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements Kakao Maps integration using react-native-webview and expo-location, featuring a custom map component and a location-tracking hook. The reviewer identified a race condition in the location hook's cleanup and recommended moving business logic from the widget layer to higher-level layers to improve architectural separation. Other feedback includes optimizing performance by preventing unnecessary WebView reloads when coordinates change, adding defensive checks for environment variables, and improving error logging for communication between the WebView and the native application.

Comment on lines +17 to +59
useCallback(() => {
let positionSub: Location.LocationSubscription | undefined;
let headingSub: Location.LocationSubscription | undefined;

(async () => {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
setCenter(SOONGSIL);
return;
}

const loc = await Location.getCurrentPositionAsync({});
const userLoc = { lat: loc.coords.latitude, lng: loc.coords.longitude };
setCenter(userLoc);
setMyLocation(userLoc);

positionSub = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.High,
timeInterval: 2000,
distanceInterval: 3,
},
(l) =>
setMyLocation({ lat: l.coords.latitude, lng: l.coords.longitude }),
);

headingSub = await Location.watchHeadingAsync((hdg) => {
const rounded = Math.round(hdg.magHeading);
if (
lastHeadingRef.current === null ||
Math.abs(rounded - lastHeadingRef.current) >= HEADING_THRESHOLD_DEG
) {
lastHeadingRef.current = rounded;
setHeading(rounded);
}
});
})();

return () => {
positionSub?.remove();
headingSub?.remove();
};
}, []),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

useFocusEffect 내의 비동기 로직에서 positionSub와 headingSub가 할당되기 전에 cleanup 함수가 실행될 수 있는 레이스 컨디션이 존재합니다. isActive 플래그를 도입하여 비동기 작업 완료 시점에 컴포넌트가 여전히 활성 상태인지 확인하고, 이미 cleanup이 호출되었다면 즉시 구독을 해제하도록 로직을 보완해야 합니다. 또한, Rule 7에 따라 widget은 presentational component로 설계되어야 하므로, 해당 비즈니스 로직(hook)의 위치를 features나 pages 레이어로 이동하는 것을 검토해 주세요.

References
  1. When creating reusable UI blocks (widgets), design them as presentational components that receive data via props. This separates UI from business logic, which should be handled in higher-level layers like features or pages.

<WebView
ref={webViewRef}
source={{
html: buildMapHtml(appKey, initialCenter),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

initialCenter가 buildMapHtml에 전달되어 WebView의 source.html을 생성하고 있습니다. 이로 인해 initialCenter 객체의 참조가 변경될 때마다 WebView 전체가 다시 로드되는 문제가 발생할 수 있습니다. HTML 소스는 정적으로 유지하고, 초기 위치 설정은 지도가 준비된 시점(isMapReady)에 injectJavaScript를 통해 수행하는 것이 성능과 사용자 경험 측면에서 더 유리합니다.


export const KakaoMap = forwardRef<KakaoMapHandle, KakaoMapProps>(
function KakaoMap({ initialCenter = SOONGSIL, myLocation, heading }, ref) {
const appKey = process.env.EXPO_PUBLIC_KAKAO_JS_KEY ?? "";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

EXPO_PUBLIC_KAKAO_JS_KEY 환경 변수가 설정되지 않은 경우 appKey가 빈 문자열이 되어 지도가 정상적으로 동작하지 않습니다. Rule 13에 따라 mock data 단계에서는 TODO 주석으로 대체를 고려할 수 있으나, 핵심 설정값인 만큼 명시적인 처리가 권장됩니다.

References
  1. Defensive logic for handling missing data (e.g., undefined results from .find()) may be deferred during the mock data phase of development, provided a TODO comment is added to ensure it is implemented during the actual API integration.

try {
const data = JSON.parse(event.nativeEvent.data) as { type: string };
if (data.type === "MAP_READY") setIsMapReady(true);
} catch {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

handleMessage 함수에서 JSON.parse 실패 시 에러를 단순히 무시하고 있습니다. WebView로부터 전달되는 메시지 형식이 변경되거나 잘못된 데이터가 올 경우 원인을 파악하기 어려울 수 있으므로, 최소한 개발 환경(DEV)에서는 에러를 로깅하는 것을 권장합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore 버전 코드 수정, 패키지 구조 변경 등 작은 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant