Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

NeedsLap/MOMOO-Nextjs

Repository files navigation

MOMOO | λͺ¨λ¬΄

KakaoTalk_Photo_2024εΉ΄05月29ζ—₯-18-03-19 μ›Ήμ‚¬μ΄νŠΈ ν”Œλ ˆμ΄μŠ€ν† μ–΄ React Native GitHub React GitHub (Migration μ „)

ν”„λ‘œμ νŠΈ κΈ°κ°„: 2023εΉ΄09月29ζ—₯ ~ 2023εΉ΄11月16ζ—₯ | λ¦¬νŒ©ν† λ§ κΈ°κ°„: 2023εΉ΄11月20ζ—₯ ~ μ§„ν–‰ 쀑
μ²΄ν—˜κ³„μ • ID: momoo@gmail.com | PW: 123qwe



λͺ©μ°¨

  1. πŸ‘¨β€πŸ’»πŸ‘©β€πŸ’» νŒ€ μ†Œκ°œ
  2. πŸ› οΈ 기술 및 개발 ν™˜κ²½
  3. πŸ’‘ μ£Όμš” κΈ°λŠ₯
  4. πŸ“ ν•΅μ‹¬κΈ°μˆ 
  5. πŸ› νŠΈλŸ¬λΈ” μŠˆνŒ…
  6. πŸ™‹β€β™‚οΈ μœ μ € ν”Όλ“œλ°±
  7. πŸš€ 버전 2(λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, κΈ°λŠ₯μΆ”κ°€)
  8. πŸ”₯ Firebase ꡬ쑰
  9. βœ”οΈ Best Practices
  10. πŸ“š ν”„λ‘œμ νŠΈ κ΄€λ ¨ λ¬Έμ„œ



1. πŸ‘¨β€πŸ’»πŸ‘©β€πŸ’» νŒ€ μ†Œκ°œ

λͺ©μ°¨λ‘œ ▲さんかく


2. πŸ› οΈ 기술 및 개발 ν™˜κ²½


FrontEnd BackEnd Design ν˜‘μ—…λ°©μ‹ μ»¨λ²€μ…˜

λͺ©μ°¨λ‘œ ▲さんかく


3. πŸ’‘ μ£Όμš” κΈ°λŠ₯

1) 인트둜

  • μŠ€ν”Œλž˜μ‹œ
  • 둜그인 및 νšŒμ›κ°€μž…

2) ν™ˆ

  • λ‚˜μ˜ 앨범/곡유 앨범 리슀트
  • 앨범 μ •λ ¬(μ΅œμ‹ μˆœ/였래된순)
  • 앨범 μΆ”κ°€/μˆ˜μ •/μ‚­μ œ
  • 앨범 곡유

3) 앨범 μƒμ„ΈνŽ˜μ΄μ§€

  • μ•¨λ²”μ˜ ν”Όλ“œ μ•¨λ²”ν˜•
  • 앨범에 사진 μΆ”κ°€
  • ν”Όλ“œ μˆ˜μ •

4) ν”Όλ“œ μƒμ„ΈνŽ˜μ΄μ§€

  • μ•¨λ²”μ˜ ν”Όλ“œ λ¦¬μŠ€νŠΈν˜•
  • ν”Όλ“œ μˆ˜μ •/μ‚­μ œ/앨범 λ³€κ²½

5) ν”Όλ“œ μ—…λ‘œλ“œ

  • 사진 및 제λͺ© (ν•„μˆ˜)
  • λ³Έλ¬Έ, 날씨/κΈ°λΆ„ 이λͺ¨ν‹°μ½˜, μœ„μΉ˜ (선택)

6) λ§ˆμ΄νŽ˜μ΄μ§€

  • ν”„λ‘œν•„ μˆ˜μ •
  • νšŒμ›νƒˆν‡΄ 및 λ‘œκ·Έμ•„μ›ƒ
  • μ΄μš©μ•½κ΄€ 및 κ°œμΈμ •λ³΄μ²˜λ¦¬λ°©μΉ¨

λͺ©μ°¨λ‘œ ▲さんかく


4. πŸ“ 핡심 기술

앨범 곡유

κΈ°λŠ₯ μ†Œκ°œ

  1. κ³΅μœ ν•  μ‚¬μš©μžλ₯Ό 검색할 수 μžˆλ‹€.
  2. 앨범을 κ³΅μœ ν•˜κ±°λ‚˜, κ³΅μœ ν•œ λŒ€μƒμ„ μ‚­μ œν•  수 μžˆλ‹€.
  3. ν™ˆμ—μ„œ κ³΅μœ ν•˜κ±°λ‚˜ 곡유 받은 앨범을 λ³Ό 수 μžˆλ‹€.
  4. 앨범을 곡유 λ°›μœΌλ©΄, ν•΄λ‹Ή 앨범에 μ €μž₯된 사진을 λ³Ό 수 μžˆλ‹€.

μ½”λ“œ

  • μ‚¬μš©μž 검색

    Firebase Admin SDKλ₯Ό μ‚¬μš©ν•˜μ—¬, μ‚¬μš©μžλ₯Ό λΆˆλŸ¬μ˜¨λ‹€.

    // src/app/api/user/route.ts
    adminApp.auth().getUserByEmail(email);

  • 곡유/곡유 μ·¨μ†Œ

    Firestore Database에 곡유 정보 μ €μž₯ & μ‚­μ œ

    // [uid]/[uid]
    sharedAlbums: Reference(albumDoc)[] 
    // [uid]/[uid]/album/[albumId]
    sharedUsers: {uid, permission}[]

  • ν™ˆ - 곡유 앨범

    • Firestoreμ—μ„œ λ‘œκ·ΈμΈν•œ μ‚¬μš©μžμ˜ 곡유 앨범 리슀트λ₯Ό κ°€μ Έμ˜¨λ‹€.

      // src/utils/SDKUtils.ts
      const getSharedAlbums = async (
       uid: string,
      ): Promise<DocumentReference[]> => {
       const userDocRef = doc(appFireStore, uid, uid);
       const userDoc = (await getDoc(userDocRef)).data();
       return userDoc.sharedAlbums;
      };

    • 곡유 앨범 데이터λ₯Ό λΆˆλŸ¬μ˜¨λ‹€.

      // src/app/api/album/sharing
      sharedAlbums.map(async (ref: DocumentReference) => {
       const albumData = await getDoc(ref).data();
       // (μ€‘λž΅)
      });

    • κ³΅μœ ν•œ μ‚¬μš©μž 데이터λ₯Ό λΆˆλŸ¬μ˜¨λ‹€.

      // src/app/api/album/sharing
       
      const { displayName, email } = await adminAppAuth.getUser(sharedAlbumUserUid);

  • 곡유 앨범 상세
    • ν”Όλ“œ 리슀트λ₯Ό μ–»κΈ° μœ„ν•΄ 곡유 앨범/λ‚˜μ˜ 앨범 ꡬ뢄없이 μš”μ²­μ„ 보낸닀.

      // src/services/feed.ts
      // Path Parameter(uid, albumName)λ₯Ό 쿼리 λ§€κ°œλ³€μˆ˜λ‘œ μš”μ²­μ— μΆ”κ°€ν•˜μ—¬ 전솑
      // 앨범 μƒμ„ΈνŽ˜μ΄μ§€ 경둜: {uid}/album/{albumName}
      // ν”Όλ“œ μƒμ„ΈνŽ˜μ΄μ§€ 경둜: {uid}/album/{albumName}/feed
      await fetch(
       `${API_URL}/feed?limit=${limit}&skip=${skip}&album=${albumName}&uid=${uid}`,
      );

    • μΏ ν‚€μ˜ uid(λ‘œκ·ΈμΈν•œ μ‚¬μš©μž)와 쿼리 λ§€κ°œλ³€μˆ˜λ‘œ 받은 uid(앨범 μƒμ„±μž)κ°€ λ‹€λ₯Ό 경우 κΆŒν•œμ„ κ²€μ‚¬ν•œλ‹€.

      // src/app/api/route.ts
      export async function GET(req: NextRequest) {
       // μ€‘λž΅
       let hasPermission = true;
       if (userUid !== uid) {
       const sharedAlbums = await getSharedAlbums(userUid);
       hasPermission = await checkAlbumPermission(albumDoc, sharedAlbums);
       }
       if (!hasPermission) {
       return new Response('μ ‘κ·Ό κΆŒν•œμ΄ μ—†λŠ” μ•¨λ²”μž…λ‹ˆλ‹€.', {
       status: 403,
       });
       }
       // μ€‘λž΅
      }
Masonry Layout
  • CSS

    • λΆ€λͺ¨ μš”μ†Œ CSS

      // src/containers/albumDetail/StyledFeed.ts
      const StyledFeedList = styled.ul`
       display: grid;
       grid-template-columns: repeat(3, minmax(0, 1fr));
       margin: -8px -8px;
       grid-auto-rows: 1px;
      `;
    • μ•„μ΄ν…œ CSS

      // src/components/AlbumItem/StyledAlbumItem.ts
      const StyledAlbumItem = styled.li`
       margin: 8px;
      `;
  • JS

    • gridRowEnd 값을 κ³„μ‚°ν•˜λŠ” μ»€μŠ€ν…€ν›…

      // src/hooks/useAlbumItemLayout.ts
      interface ImgSize {
       width: number;
       height: number;
      }
      function useAlbumItemLayout(node: HTMLLIElement) {
       const [imgSize, setImgSize] = useState<ImgSize | null>(null);
       const [gridRowEnd, setGridRowEnd] = useState('');
       useEffect(() => {
       const setLayout = async () => {
       if (!imgSize || !node) {
       return;
       }
       const height = node.clientWidth * (imgSize.height / imgSize.width);
       setGridRowEnd(`span ${Math.round(height + 16)}`);
       };
       setLayout();
       }, [imgSize]);
       return { setImgSize, gridRowEnd };
      }
    • gridRowEnd 값을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ μ•„μ΄ν…œ 이미지 μ‚¬μ΄μ¦ˆ κ΅¬ν•˜κΈ°

      // src/components/AlbumItem/AlbumItem.tsx
      <img
       onLoad={(e) =>
       setImgSize({
       width: e.currentTarget.naturalWidth,
       height: e.currentTarget.naturalHeight,
       })
       }
      />
λ¬΄ν•œ 슀크둀
앨범 μƒμ„ΈνŽ˜μ΄μ§€μ™€ κ²Œμ‹œλ¬Ό μƒμ„ΈνŽ˜μ΄μ§€ μ μš©ν•œ κΈ°μˆ μž…λ‹ˆλ‹€.
두 νŽ˜μ΄μ§€μ— μ μš©λ˜λŠ” 기술둜, μ½”λ“œ 쀑볡을 μ΅œμ†Œν™”ν•˜κΈ° μœ„ν•΄ Custom Hook을 톡해 핡심 λ‘œμ§μ„ λΆ„λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.
  • Custom Hook

    • Intersection Observer APIλ₯Ό ν™œμš©ν–ˆμŠ΅λ‹ˆλ‹€.
    • νŠΉμ • μ•„μ΄ν…œμ΄ λ·°ν¬νŠΈμ— λ‚˜νƒ€λ‚˜λ©΄ νŽ˜μ΄μ§€λ₯Ό μ—…λ°μ΄νŠΈν–ˆμŠ΅λ‹ˆλ‹€.

    // src/hooks/useInfiniteScroll.ts
    import { useRef, useState } from 'react';
    export default function useInfiniteScroll() {
     const itemRef = useRef<HTMLLIElement | null>();
     const observer = useRef<IntersectionObserver | null>(null);
     const [page, setPage] = useState(1);
     const observe = (node: HTMLLIElement) => {
     observer.current = new IntersectionObserver(entries => {
     if (entries[0].isIntersecting) {
     setPage(prev => prev + 1);
     if (observer.current) {
     observer.current.disconnect();
     }
     }
     });
     observer.current.observe(node);
     };
     const setItemToObserveRef = (node: HTMLLIElement) => {
     if (node && node !== itemRef.current) {
     itemRef.current = node;
     observe(node);
     }
     };
     return { page, setItemToObserveRef };
    }
  • Custom Hook μ‚¬μš©

    // src/containers/albumDetail/albumDetail.tsx
    const { page, setItemToObserveRef } = useInfiniteScroll();
    // page μ—…λ°μ΄νŠΈ μ‹œ, μΆ”κ°€ 데이터 페칭
    useEffect(() => {
     if (page === 1) {
     return;
     }
     (async () => {
     const feedsToAdd = await getFeeds({
     limit: pageSize * page,
     skip: pageSize * page - pageSize,
     uid,
     albumName
     });
     if (feedsToAdd) {
     setFeedsData(prev => [...prev, ...feedsToAdd]);
     }
     })();
    }, [page]);
    // observe item
    {feedsData.map((v, i) => {
     return (
     <AlbumItem
     key={v.id}
     ref={i === feedsData.length - 1 ? setItemToObserveRef : null}
     />
     );
    })}

    μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œ refλ₯Ό 전달받기 μœ„ν•΄ forwardRef μ‚¬μš©

    // src/components/AlbumItem/AlbumItem.tsx

function AlbumItem(ref: ForwardedRef) { return ( ); }

export default forwardRef(AlbumItem);
```

λͺ©μ°¨λ‘œ ▲さんかく


5. πŸ› νŠΈλŸ¬λΈ” μŠˆνŒ…

1) μ•ˆλ“œλ‘œμ΄λ“œ 기기의 λ’€λ‘œκ°€κΈ°
  1. λ’€λ‘œκ°€κΈ° 클릭 μ‹œ, 앱이 λ‹«νžˆλŠ” 이슈
    - ν•΄κ²°: 이전 νŽ˜μ΄μ§€κ°€ μ‘΄μž¬ν•  경우, 이전 νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•˜λ„λ‘ μˆ˜μ •

  2. λ’€λ‘œκ°€κΈ° 클릭 μ‹œ, κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • λͺ¨λ‹¬μ΄ 계속 μ—΄λ €μžˆλŠ” 이슈
    - 원인: κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • λͺ¨λ‹¬μ΄ νŽ˜μ΄μ§€ μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ Œλ”λ§λ˜κΈ° λ•Œλ¬Έμ—, 이전 νŽ˜μ΄μ§€λ‘œ 이동해도 λͺ¨λ‹¬μ€ λ‹«νžˆμ§€ μ•ŠμŒ
    - ν•΄κ²°: λͺ¨λ°”일에선 κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • λͺ¨λ‹¬μ„ νŽ˜μ΄μ§€λ‘œ λ³€κ²½

  3. κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • ν›„ κ²Œμ‹œλ¬Ό μƒμ„ΈνŽ˜μ΄μ§€μ—μ„œ λ’€λ‘œκ°€κΈ° 클릭 μ‹œ, κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • νŽ˜μ΄μ§€λ‘œ λŒμ•„κ°€λŠ” 이슈
    - 상황: κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • ν™”λ©΄μœΌλ‘œ λŒμ•„κ°€λŠ” 흐름이 λΆˆνŽΈν•˜λ‹€λŠ” ν”Όλ“œλ°±μ„ λ°›μŒ
    - ν•΄κ²°: λͺ¨λ°”μΌμ—μ„œλ„ κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ •μ„ λͺ¨λ‹¬λ‘œ 되돌리고, λ’€λ‘œκ°€κΈ° 클릭 μ‹œ λͺ¨λ‹¬μ΄ λ‹«νžˆλ„λ‘ λ³€κ²½

μžμ„Έν•œ λ‚΄μš© | MOMOO-RN

2) 이미지 ν™•μž₯자 μœ νš¨μ„± 검사 - SVG
  • 문제: 이미지 선택 ν›„ μœ νš¨μ„± 검사 μ‹œ, svg 파일이 ν†΅κ³Όν•˜μ§€ λͺ»ν•˜λŠ” 버그

  • 원인: 기쑴에 svg νŒŒμΌμ„ image/svg둜 κ²€μ‚¬ν•˜κ³  μžˆμ—ˆμœΌλ‚˜, ν‘œμ€€ MIME νƒ€μž…μ€ image/svg+xml이기 λ•Œλ¬Έ

  • ν•΄κ²°: image/svg+xml을 ν†΅κ³Όμ‹œν‚€λ„λ‘ μ •κ·œ ν‘œν˜„μ‹ μˆ˜μ •

    /^image\/(jpg|svg|png|jpeg|gif|bmp|tif|heic)$/ // κΈ°μ‘΄
    /^image\/(jpg|svg(\+xml)?|png|jpeg|gif|bmp|tif|heic)$/ // λ³€κ²½
3) λͺ¨λ‹¬ λ°°κ²½ μ½˜ν…μΈ  슀크둀
  • 문제: λͺ¨λ°”μΌμ—μ„œ κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • λͺ¨λ‹¬ λ‚΄ 슀크둀 μ‹œλ„ μ‹œ, λ°°κ²½ μ½˜ν…μΈ κ°€ μŠ€ν¬λ‘€λ˜λŠ” κ²½μš°κ°€ 있음

  • 원인: ν•΄λ‹Ή μš”μ†Œμ˜ μŠ€ν¬λ‘€μ„ (더) 내릴/올릴 수 μ—†λŠ” 경우, window에 슀크둀 이벀트 λ°œμƒ (chrome λ™μž‘ 방식)

  • ν•΄κ²°: λͺ¨λ°”μΌμ—μ„œ ν•΄λ‹Ή λͺ¨λ‹¬ open μ‹œ, body에 scroll-rock 클래슀 μΆ”κ°€ (close μ‹œ, scroll-rock 클래슀 μ‚­μ œ)

    .scroll-lock {
     position: fixed;
     height: 100vh;
     overflow: hidden;
    }
4) 데이터 μ—…λ°μ΄νŠΈμ™€ UI
  • 문제: 데이터 μ—…λ°μ΄νŠΈ μ‹œ, λ‹€λ₯Έ 경둜둜 μ΄λ™ν•œ ν›„ λŒμ•„μ˜€λ©΄ 이전 데이터가 λ Œλ”λ§λ¨
  • ν•΄κ²°: 데이터 μ—…λ°μ΄νŠΈ μ‹œ 라우트 μƒˆλ‘œκ³ μΉ¨
import { useRouter } from 'next/navigation';
router.refresh();

λͺ©μ°¨λ‘œ ▲さんかく


6. πŸ™‹β€β™‚οΈ μœ μ € ν”Όλ“œλ°±

1) 1μ°¨ μœ μ € ν…ŒμŠ€νŠΈ

ν”Όλ“œλ°± λͺ©λ‘


νšŒμ›κ°€μž…

  1. (ε‰Šι™€) μ΄μš©μ•½κ΄€ 읽고 λ’€λ‘œ 였면 μž…λ ₯ν•΄ λ†“μ•˜λ˜ λ‚΄μš©μ΄ 사라지고, λͺ¨λ“  체크 λ°•μŠ€κ°€ ν•΄μ œλ¨ (ε‰Šι™€γ“γ“γΎγ§)5a0b0d0
  2. (ε‰Šι™€) ν”„λ‘œν•„ 사진 λ³€κ²½ λ²„νŠΌμ— 마우슀 μ»€μ„œλ₯Ό κ°€μ Έλ‹€ λ†“μ•˜μ„ λ•Œ, 손가락 λͺ¨μ–‘μœΌλ‘œ λ°”λ€Œλ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)bdfc9ea
  3. λ²„νŠΌ ν•˜λ‹¨λΆ€κ°€ 잘림. 앱이 μ „μ²΄μ μœΌλ‘œ ν•˜λ‹¨λΆ€ UIκ°€ 잘림
  4. (ε‰Šι™€) 'μ•ˆλ…•ν•˜μ„Έμš” λͺ¨λ¬΄μž…λ‹ˆλ‹€'λΌλŠ” ν…μŠ€νŠΈκ°€ μ—†μœΌλ©΄ 쒋을 것 κ°™μŒ. 이미 μŠ€ν”Œλž˜μ‹œμ—μ„œ μ†Œκ°œν–ˆκΈ° λ•Œλ¬Έ (ε‰Šι™€γ“γ“γΎγ§)4f05ab6
  5. (ε‰Šι™€) 아이디가 λ‘œκ·ΈμΈμš©μΈμ§€ μ‚¬λžŒλ“€μ—κ²Œ λ³΄μ΄λŠ” μš©μΈμ§€ λͺ¨λ₯΄κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)(username -> nickname)


ν”„λ‘œν•„ μˆ˜μ •

  1. (ε‰Šι™€) ν”„λ‘œν•„ μˆ˜μ • κΈ°λŠ₯μ—μ„œ 사진 크기 2MB μ΄λ‚΄λΌμ„œ ν•Έλ“œν°μœΌλ‘œ 찍은 사진은 등둝이 μ•ˆ 됨 (ε‰Šι™€γ“γ“γΎγ§)(src/hooks/useProfileImg.ts)
  2. (ε‰Šι™€) 계정 재인증 λͺ¨λ‹¬ - λΉ„λ°€λ²ˆν˜Έκ°€ λ§ˆμŠ€ν‚Ή 처리되면 μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)7e75388
  3. (ε‰Šι™€) ν”„λ‘œν•„ 섀정이 μˆ˜μ •μΈ 건지 ν—·κ°ˆλ¦Ό (ε‰Šι™€γ“γ“γΎγ§)6167780
  4. (ε‰Šι™€) νƒˆν‡΄ λͺ¨λ‹¬ ν•˜λ‹¨λΆ€κ°€ 잘림 (ε‰Šι™€γ“γ“γΎγ§)#227


ν™ˆ

  1. ν”ŒλŸ¬μŠ€ μ•„μ΄μ½˜μ΄ 앨범 μΆ”κ°€ λ²„νŠΌμΈμ§€ ν—·κ°ˆλ¦Ό
  2. (ε‰Šι™€) 앨범 이름을 μž…λ ₯ν•˜μ§€ μ•Šμ•„λ„ 앨범 μΆ”κ°€ κ°€λŠ₯ (ε‰Šι™€γ“γ“γΎγ§)#236
  3. (ε‰Šι™€) 앨범 μˆ˜μ •/μ‚­μ œ λͺ¨λ‹¬μ— μžˆλŠ” 체크 ν‘œμ‹œμ˜ κΈ°λŠ₯을 λͺ¨λ₯΄κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)(μ €μž₯ λ²„νŠΌ: 체크 μ•„μ΄μ½˜ -> 'μ €μž₯' ν…μŠ€νŠΈ)
  4. (ε‰Šι™€) 앨범 생성 μ‹œ, μ—”ν„°λ₯Ό λˆŒλŸ¬μ„œ μ €μž₯ κ°€λŠ₯ν•˜λ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)91d0fe3
  5. (ε‰Šι™€) 같은 μ΄λ¦„μœΌλ‘œ 앨범을 μ—¬λŸ¬ 개 λ§Œλ“€ 수 있음 (ε‰Šι™€γ“γ“γΎγ§)#236
  6. (ε‰Šι™€) ν˜„μž¬ 앨범 ... λ²„νŠΌ(더보기) 클릭 μ‹œ, 앨범 μˆ˜μ •/μ‚­μ œ λͺ¨λ‹¬μ΄ μ—΄λ¦¬λŠ”λ° κΈ°λŠ₯을 λͺ…λ£Œν™”ν•˜λ©΄ 더 쒋을 것 κ°™μŒ (ε‰Šι™€γ“γ“γΎγ§)(더보기 클릭 μ‹œ, 선택 λͺ¨λ‹¬μ΄ λœ¨λ„λ‘ λ³€κ²½)01e4d5f b825983
  7. (ε‰Šι™€) 앨범 ν•˜λ‹¨λΆ€κ°€ 잘림 (ε‰Šι™€γ“γ“γΎγ§)571a714
  8. (ε‰Šι™€) 앨범λͺ…을 μž…λ ₯ν•˜κ³  μ €μž₯ λ²„νŠΌμ„ μ—¬λŸ¬ 번 λˆ„λ₯΄λ©΄ 앨범이 μ—¬λŸ¬κ°œ 생성됨 (ε‰Šι™€γ“γ“γΎγ§)692c719
  9. (ε‰Šι™€) 앨범 μˆ˜μ •/μ‚­μ œ λͺ¨λ‹¬μ˜ λ²„νŠΌμ„ μ—¬λŸ¬ 번 λˆ„λ₯΄λ©΄ μ—λŸ¬ νŽ˜μ΄μ§€("μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” νŽ˜μ΄μ§€μž…λ‹ˆλ‹€")둜 이동됨
    상황 μž¬ν˜„: λ²„νŠΌμ΄ μœ„μΉ˜ν•œ 곳을 κ³„μ†ν•΄μ„œ ν΄λ¦­ν•˜λ©΄, 생성이 μ™„λ£Œλ  λ•Œ λͺ¨λ‹¬μ΄ λ‹«νžˆλŠ” λ™μ‹œμ— 앨범이 클릭 됨 -> 클릭 된 μ•¨λ²”μ˜ 제λͺ©μ΄ 없을 μ‹œ, μœ νš¨ν•˜μ§€ μ•Šμ€ μ£Όμ†Œλ‘œ 이동됨 (ε‰Šι™€γ“γ“γΎγ§)
    #236
  10. (ε‰Šι™€) λͺ¨λ‹¬μ°½μ΄ λ„μ›Œμ‘Œμ„ λ•Œ λ²„νŠΌμ€ λˆŒλŸ¬μ§€μ§€ μ•Šμ§€λ§Œ 슀크둀이 κ°€λŠ₯ -> 일반적인 μ‚¬μš©μ„±μ΄λ‚˜, κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ • λͺ¨λ‹¬μ˜ 경우 λͺ¨λ°”μΌμ—μ„œ ν™”λ©΄ 전체λ₯Ό μ°¨μ§€ν•˜κΈ° λ•Œλ¬Έμ— μ‚¬μš©μ— λΆˆνŽΈν•¨μ΄ 있음 (ε‰Šι™€γ“γ“γΎγ§) #143
  11. (ε‰Šι™€) 앨범 ν•„ν„° λ²„νŠΌμ΄ λ„ˆλ¬΄ μž‘μŒ (ε‰Šι™€γ“γ“γΎγ§)036022a
  12. (ε‰Šι™€) 앨범 제λͺ© κΈ€μž 수의 μ œν•œμ΄ μ—†μŒ (ε‰Šι™€γ“γ“γΎγ§)536bae6
  13. (ε‰Šι™€) μ •λ ¬ κΈ°μ€€ λˆ„λ₯΄κ³  λ‚˜μ„œ λ‹€λ₯Έ λΆ€λΆ„ ν„°μΉ˜ν–ˆμ„ λ•Œ 정렬창이 꺼쑌으면 함 (ε‰Šι™€γ“γ“γΎγ§)9b16fbf


앨범 상세 νŽ˜μ΄μ§€

  1. (ε‰Šι™€) κ²Œμ‹œκΈ€μ΄ λ§Žμ•„μ§ˆμˆ˜λ‘ '앨범에 κ²Œμ‹œκΈ€ μΆ”κ°€ λ²„νŠΌ'도 λ’€λ‘œ λ°€λ €μ„œ λˆ„λ₯΄λŸ¬ κ°€κΈ° νž˜λ“€μ–΄μ§ (ε‰Šι™€γ“γ“γΎγ§)5bbe7dd 63fa419
  2. (ε‰Šι™€) λͺ©λ‘ν˜•, μ•¨λ²”ν˜• 선택 κ°€λŠ₯ν•˜λ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)fe9614f
  3. λ‚ μ§œ, 제λͺ©μ΄ λ³΄μ˜€μœΌλ©΄ μ’‹κ² μŒ


κ²Œμ‹œλ¬Ό 상세 νŽ˜μ΄μ§€

  1. (ε‰Šι™€) 제λͺ©κ³Ό 본문이 κΈ€μž 크기 차이가 크게 μ•ˆ λ‚˜μ„œ μƒ‰μƒμ΄λ‚˜ 폰트 μ‚¬μ΄μ¦ˆλ₯Ό μ’€ 더 μ‘°μ ˆν•˜λ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)17cc95d


κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ

  1. (ε‰Šι™€) ν•œ λ²ˆμ— μ—¬λŸ¬ μž₯의 사진을 등둝할 수 있으면 μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§) => λΈŒλΌμš°μ € 파일 선택 κΈ°λŠ₯ μ΅μˆ™μ§€ μ•Šμ€ μ‚¬μš©μž
  2. μ²˜μŒμ— λͺ¨λ“  selectboxκ°€ λ‹«ν˜€μžˆμ–΄μ„œ ν•œ 번 더 λˆŒλŸ¬μ•Ό ν•˜λŠ” 게 μ‚¬μš©μ„±μ΄ μ•ˆ 쒋은 것 κ°™μŒ
  3. λ­”κ°€ μ§€λ„μ˜ 핀을 μ›€μ§μ—¬μ„œ μœ„μΉ˜λ₯Ό 선택할 수 μžˆλŠ” κΈ°λŠ₯이 있으면 μ’‹κ² μŒ
  4. (ε‰Šι™€) 체크 ν‘œμ‹œκ°€ μœ„μΉ˜ μΆ”κ°€ λ²„νŠΌμ΄λΌλŠ” 것을 μ•ŒκΈ° μ–΄λ €μ› μŒ (ε‰Šι™€γ“γ“γΎγ§)#52
  5. (ε‰Šι™€) μ—…λ‘œλ“œ λ²„νŠΌμ€ ν¬μ»€μŠ€κ°€ λ§ˆμ§€λ§‰μ— 되면 μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)#74
  6. (ε‰Šι™€) 였늘의 λ‚ μ”¨μ—μ„œ 비와 눈의 ꡬ뢄이 λͺ¨ν˜Έν•¨ (ε‰Šι™€γ“γ“γΎγ§)89f4104
  7. μ§€λ„μ—μ„œ λ‚΄κ°€ μ›ν•˜λŠ” 뢀뢄을 ν„°μΉ˜ν•˜μ—¬ μ§€μ •ν•  수 있으면 μ’‹κ² μŒ
  8. μœ„μΉ˜ μΆ”κ°€λž€μ„ μ—΄μ—ˆμ„ λ•Œ, μ•„λž˜λ‘œ λ“œλž˜κ·Έν•˜μ—¬ 였늘의 날씨도 λ³Ό 수 있으면 μ’‹κ² μŒ
  9. (ε‰Šι™€) 앨범이 볡수 선택 κ°€λŠ₯ν•΄μ„œ μ’‹μŒ (ε‰Šι™€γ“γ“γΎγ§)
  10. (ε‰Šι™€) ESCλ₯Ό λˆ„λ₯΄λ©΄ λͺ¨λ‹¬μ΄ λ‹«νžˆλ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)61d1e8a
  11. (ε‰Šι™€) κΈ°μ‘΄ 사진에 μΆ”κ°€ν•  μ‚¬μ§„λ§Œ μ„ νƒν–ˆλŠ”λ°, κΈ°μ‘΄ 사진은 없어짐 (ε‰Šι™€γ“γ“γΎγ§)#269
  12. (ε‰Šι™€) 사진이 μ΅œλŒ€ 3μž₯이 μ˜¬λΌκ°€λŠ”λ° λ”°λ‘œ μ•ˆλ‚΄ 사항이 μ—†λŠ” 점이 아쉬움 (ε‰Šι™€γ“γ“γΎγ§)#269
  13. μœ„μΉ˜ μΆ”κ°€μ˜ 경우 지도에 ν‘œμ‹œλ˜λŠ” μž₯μ†Œλ₯Ό ν™•λŒ€ν•˜κ³  μΆ•μ†Œν•˜λŠ” κΈ°λŠ₯을 μ‚¬μš©ν•  λ•Œ λ§Œμ•½ input에 μ»€μ„œκ°€ λ“€μ–΄κ°€ μžˆλŠ” 경우 (검색어λ₯Ό μž…λ ₯ν•˜κ³  λ°”λ‘œ 지도λ₯Ό ν™•λŒ€ν•˜λŠ” 경우) ν™•λŒ€ μΆ•μ†Œν•  λ•Œλ§ˆλ‹€ input에 자꾸 ν¬μ»€μŠ€κ°€ 듀어감. inputμ—μ„œ 포컀슀λ₯Ό λΉΌμ•Ό(λ’€λ‘œκ°€κΈ° λ²„νŠΌ λˆŒλŸ¬μ•Ό) κΉ”λ”ν•˜κ²Œ ν™•λŒ€μΆ•μ†Œκ°€ κ°€λŠ₯함
  14. 검색어λ₯Ό λͺ¨ν˜Έν•˜κ²Œ μž…λ ₯ν–ˆμ„ λ•Œ 선택지가 μ—†λŠ”κ²Œ 아쉬움(μ„œμšΈλ‘œ μž…λ ₯ν•˜λ©΄ 경볡ꢁ이 선택됨)
  15. (ε‰Šι™€) ν•„μˆ˜ ν•­λͺ©μ„ μ•Œ 수 μ—†μ–΄μ„œ λΆˆνŽΈν•¨ (ε‰Šι™€γ“γ“γΎγ§)#269
  16. 앨범 선택 μ‹œ, μƒˆλ‘œμš΄ 앨범을 λ§Œλ“€μ–΄μ„œ κ·Έ 앨범에 λ°”λ‘œ μΆ”κ°€ν•  수 있으면 μ’‹κ² μŒ
  17. (ε‰Šι™€) 사진 μ—…λ‘œλ“œ λ²„νŠΌμ— ν¬μ»€μŠ€κ°€ 되면 μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)#74
  18. μ‚¬μ§„λΏλ§Œ μ•„λ‹ˆλΌ λ™μ˜μƒλ„ μ €μž₯ν•  수 있으면 μ’‹κ² μŒ
  19. νƒ­λ°”κ°€ μžˆμ–΄λ„ 쒋을 듯함
  20. (ε‰Šι™€) μ—…λ‘œλ“œλ˜λŠ” μ‚¬μ§„μ˜ ν™•μž₯λͺ…을 μΆ”κ°€ν•˜λ©΄ μ’‹κ² μŒ(gif λ“±) (ε‰Šι™€γ“γ“γΎγ§)#53
  21. (ε‰Šι™€) κ²Œμ‹œλ¬Ό 제λͺ©κ³Ό κ²Œμ‹œλ¬Ό 본문은 곡백 포함 500μžκΉŒμ§€ μ œν•œ 있음(μ•ˆλ‚΄ ν•„μš”) (ε‰Šι™€γ“γ“γΎγ§)#269
  22. (ε‰Šι™€) μœ„μΉ˜ 선택 μ‹œ, 지도가 λœ¨μ§€ μ•ŠλŠ” 버그 (ε‰Šι™€γ“γ“γΎγ§)(Kakao Developers에 μ£Όμ†Œ μΆ”κ°€)
  23. (ε‰Šι™€) 날씨와 κΈ°λΆ„ μ…€λ ‰νŠΈ λ°•μŠ€κ°€ μ„ νƒλ˜μ§€ μ•ŠλŠ” 버그(κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ 22 λ²„κ·Έλ‘œ μΈν•œ 버그) (ε‰Šι™€γ“γ“γΎγ§)
  24. (ε‰Šι™€) μ—…λ‘œλ“œ λ²„νŠΌμ΄ λˆŒλŸ¬μ§€μ§€ μ•ŠμŒ -> UI ν”Όλ“œλ°±μ΄ μ—†μ–΄μ„œ μ—…λ‘œλ“œμ€‘μž„μ„ μ•Œ 수 μ—†μŒ -> λ‘œλ”©μ€‘ UI μΆ”κ°€ (ε‰Šι™€γ“γ“γΎγ§)


μ•±

  1. (ε‰Šι™€) μ•ˆλ“œλ‘œμ΄λ“œ 기기의 λ’€λ‘œκ°€κΈ° λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ 앱이 μ’…λ£Œλ¨ (ε‰Šι™€γ“γ“γΎγ§)dc43540


기타

  1. (ε‰Šι™€) μŠ€ν¬λ‘€μ„ ν•˜λ©° κ³„μ†ν•΄μ„œ κ²Œμ‹œκΈ€μ„ 보고 μ‹ΆμŒ (ε‰Šι™€γ“γ“γΎγ§)fe9614f
  2. (ε‰Šι™€) 앨범을 ν•„μˆ˜λ‘œ 생성해야 사진이 μ—…λ‘œλ“œν•  수 μžˆκ±°λ‚˜, 앨범 생성 μ „ 사진을 μ—…λ‘œλ“œν•΄λ„ κΈ°λ³Έ 앨범에 사진이 μ—…λ‘œλ“œλ˜λ©΄ μ’‹κ² μŒ
    상황: νšŒμ›κ°€μž… μ‹œ, '전체 보기' 앨범이 μžλ™ μƒμ„±λ˜λ‚˜ μ‚¬μš©μžλŠ” μΈμ§€ν•˜μ§€ λͺ»ν•¨
    ν•΄κ²°1: κΈ°μ‘΄μ—” μ—…λ‘œλ“œ ν›„ μ΄λ™ν•œ ν”Όλ“œ 상세 νŽ˜μ΄μ§€μ—μ„œ ν•΄λ‹Ή ν”Όλ“œμ— λŒ€ν•œ μ •λ³΄λ§Œ λ³Ό 수 있음. '전체 보기'의 ν”Όλ“œ 상세 νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•˜λ„λ‘ λ³€κ²½ν•˜μ—¬, '전체 보기' 앨범이 μžλ™ μƒμ„±λ˜κ³  ν•΄λ‹Ή 앨범에 μ €μž₯λ˜μ—ˆμŒμ„ 인지할 수 μžˆλ„λ‘ 함 (ε‰Šι™€γ“γ“γΎγ§)
    (${userUid}/전체 보기/feed)
    ν•΄κ²°2: νšŒμ›κ°€μž… μ‹œ, νŠœν† λ¦¬μ–Ό
  3. (ε‰Šι™€) 사진 μŠ¬λΌμ΄λ“œκ°€ λ™μž‘ν•˜μ§€ μ•ŠμŒ
    3-1. μ—…λ‘œλ“œ (ε‰Šι™€γ“γ“γΎγ§)
    3aabb70
    (ε‰Šι™€) 3-2. κ²Œμ‹œλ¬Ό 상세 νŽ˜μ΄μ§€ (ε‰Šι™€γ“γ“γΎγ§)#35
  4. (ε‰Šι™€) κ²Œμ‹œκΈ€ μˆ˜μ • ν›„ κ²Œμ‹œκΈ€μ—μ„œ < λ’€λ‘œκ°€κΈ° μ•„μ΄μ½˜μ„ λˆ„λ₯΄λ©΄ λ‹€μ‹œ κ²Œμ‹œκΈ€ μˆ˜μ • νŽ˜μ΄μ§€κ°€ λ‚˜μ™€μ„œ λΆˆνŽΈν•¨
    - κ°œμ„ : κ²Œμ‹œλ¬Ό μˆ˜μ • νŽ˜μ΄μ§€ -> λͺ¨λ‹¬λ‘œ 톡일 (ε‰Šι™€γ“γ“γΎγ§)
    #32
  5. (ε‰Šι™€) κ²Œμ‹œκΈ€ μ‚­μ œλ₯Ό ν•˜λ©΄ 기쑴에 있던 νŽ˜μ΄μ§€κ°€ μ•„λ‹ˆλΌ μƒˆ κ²Œμ‹œκΈ€ μž‘μ„±ν•˜λŠ” νŽ˜μ΄μ§€κ°€ λ‚˜μ™€μ„œ λΆˆνŽΈν•¨ - 상황: κ²Œμ‹œλ¬Ό 생성 ν›„ μ‚­μ œ μ‹œ 이전 νŽ˜μ΄μ§€μΈ μƒˆ κ²Œμ‹œκΈ€ νŽ˜μ΄μ§€λ‘œ 이동됨 - κ°œμ„ : μƒˆ κ²Œμ‹œκΈ€ νŽ˜μ΄μ§€(κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ νŽ˜μ΄μ§€) -> λͺ¨λ‹¬λ‘œ 톡일 (ε‰Šι™€γ“γ“γΎγ§)#39
  6. (ε‰Šι™€) confirm μ°½μ΄λ‚˜ alert창을 직접 λ§Œλ“€μ§€ μ•Šμ•„μ„œ UIκ°€ μ˜ˆμ˜μ§€ μ•ŠμŒ (ε‰Šι™€γ“γ“γΎγ§)#191
  7. μΊ˜λ¦°λ” ν˜•μ‹μœΌλ‘œ μ—…λ‘œλ“œν•œ λ‚ μ§œλ₯Ό μ§€μ •ν•΄ 확인할 수 μžˆλŠ” κΈ°λŠ₯이 있으면 μ’‹κ² μŒ
  8. μ•± 잠금 κΈ°λŠ₯이 있으면 μ’‹κ² μŒ
  9. (ε‰Šι™€) 곡유 κΈ°λŠ₯ μΆ”κ°€ 희망 (ε‰Šι™€γ“γ“γΎγ§)#253
  10. 예쁜 이미지 μ‚¬μ§„μœΌλ‘œ λ§Œλ“€μ–΄μ Έ μ‚¬μ§„μœΌλ‘œ κ³΅μœ ν•  수 있으면 μ’‹κ² μŒ
  11. (ε‰Šι™€) λ‚΄λΉ„κ²Œμ΄μ…˜ 바에 ν™ˆ λ²„νŠΌμ΄ a νƒœκ·Έμ™€ button νƒœκ·Έλ‘œ μ΄λ£¨μ–΄μ Έμ„œ ν¬μ»€μŠ€κ°€ 두 번 됨 (ε‰Šι™€γ“γ“γΎγ§)(#241)https://github.com/yonainthefish/MoMoo/issues/241[https://github.com/yonainthefish/MoMoo/commit/270938caf1635d0ee1eb806c8d0c7cd91535da98]
  12. (ε‰Šι™€) λͺ¨λ‹¬μ΄ λ‚˜μ™”μ„ 땐, λͺ¨λ‹¬ λ‚΄μ—μ„œλ§Œ ν¬μ»€μŠ€κ°€ μ΄λ™ν•˜λ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)(#245)[https://github.com/yonainthefish/MoMoo/issues/245]
  13. (ε‰Šι™€) μœ νš¨ν•˜μ§€ μ•Šμ€ URL 접속 μ‹œ, λ‚΄λΉ„κ²Œμ΄μ…˜λ°”λŠ” λ‚˜μ˜€λ©΄ 쒋을 것 κ°™μŒ (ε‰Šι™€γ“γ“γΎγ§)(#231)[https://github.com/yonainthefish/MoMoo/issues/231]
  14. (ε‰Šι™€) μ•„μ΄μ½˜μ˜ 퀄리티가 더 λ°œμ „ν•˜λ©΄ μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§)
  15. μ•±μ˜ 컨셉이 더 λΆ„λͺ…ν•˜λ©΄ 쒋을 것 κ°™μŒ
    15-1. 사진 μ—…λ‘œλ“œ 메인일 경우, 앨범 상세 νŽ˜μ΄μ§€μ—μ„œ μ‚¬μš©μžκ°€ μ—…λ‘œλ“œν•œ 사진듀이 λͺ¨μ˜€μ„ λ•Œ λΏŒλ“―ν•¨μ„ λŠλ‚„ λ§Œν•œ λ””μžμΈ μš”μ†Œ μΆ”κ°€ν•˜λ©΄ μ’‹κ² μŒ
    15-2. 일기 κΈ°λŠ₯이 메인일 경우,
    • 폰트 속성 λ³€ν™” κΈ°λŠ₯을 μΆ”κ°€ν•˜λ©΄ μ’‹κ² μŒ
    • λ‚˜μ˜ ν•˜λ£¨ 기뢄을 μ£Όκ°„/μ›”κ°„ κ·Έλž˜ν”„λ‘œ 확인할 수 μžˆλŠ” κΈ°λŠ₯ μΆ”κ°€ν•˜λ©΄ μ’‹κ² μŒ
  16. (ε‰Šι™€) νŠœν† λ¦¬μ–Όμ΄λ‚˜ μ‚¬μš©λ²•μ„ μ•Œλ €μ£ΌλŠ” κΈ°λŠ₯이 있으면 μ’‹κ² μŒ (ε‰Šι™€γ“γ“γΎγ§) μ΄μš©κ°€μ΄λ“œ
  17. (ε‰Šι™€) 앨범이 μ—¬λŸ¬ κ°œκ°€ λ˜λŠ” 경우 슀크둀이 λ„ˆλ¬΄ κΈΈμ–΄μ Έμ„œ ν•Έλ“œν°μ˜ 가러리처럼 μž‘μ•„λ„ 쒋을 λ“― 함 (ε‰Šι™€γ“γ“γΎγ§)
  18. 전체보기가 μ‹œμ„ μ„ κ°•νƒˆν•¨
  19. (ε‰Šι™€) λ§ˆμ΄νŽ˜μ΄μ§€ μ°½μ—μ„œ μœ μ € ν”„λ‘œν•„ κΈ°λŠ₯을 λ”°λ‘œ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ λΉΌλ©΄ μ’‹κ² μŒ(λ˜λŠ” 쀄 μ•Œκ³  λͺ‡ 번 클릭함) (ε‰Šι™€γ“γ“γΎγ§)#91
  20. λ‹€λ₯Έ μ‚¬λžŒκ³Όμ˜ μ±„νŒ… κΈ°λŠ₯이 μžˆμ—ˆμœΌλ©΄ μ‹ μ„ ν•  것 κ°™μŒ
  21. (ε‰Šι™€) 앨범 생성, νšŒμ›νƒˆν‡΄ λͺ¨λ‹¬ - λ²„νŠΌμ΄ 보이지 μ•ŠμŒ (ε‰Šι™€γ“γ“γΎγ§)
  22. (ε‰Šι™€) 404 νŽ˜μ΄μ§€μ— navκ°€ 있으면 μ’‹κ² μŒ(λ‹€λ₯Έ νŽ˜μ΄μ§€λ‘œ 이동할 수 μžˆλ„λ‘) (ε‰Šι™€γ“γ“γΎγ§)

*총 73개의 ν”Όλ“œλ°±μ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€. ν˜„μž¬ 56개λ₯Ό 반영 μ™„λ£Œν–ˆμŠ΅λ‹ˆλ‹€.


2) 2μ°¨ μœ μ € ν…ŒμŠ€νŠΈ

μ‚¬μš© λ§Œμ‘±λ„ κ°œμ„ 
  • 1μ°¨ λ§Œμ‘±λ„ 쑰사 λŒ€λΉ„ 평균 μ•½ 29% ν–₯상됨 (4번 μ œμ™Έ)
  • ⭐ 10점 만점

  1. νšŒμ›κ°€μž…/둜그인/ν”„λ‘œν•„ μˆ˜μ •: ⭐ 7.3 -> ⭐ 10
  2. 앨범 생성/μˆ˜μ •/μ‚­μ œ: ⭐ 7.7 -> ⭐ 9.5
  3. κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ •/μ‚­μ œ: ⭐ 6.7 -> ⭐ 10
  4. 앨범 곡유: 10
ν”Όλ“œλ°± λͺ©λ‘


ν™ˆ

  1. '더보기'λ₯Ό λˆ„λ₯΄λ©΄ (μˆ˜μ •ν•˜κΈ°, 곡유 λŒ€μƒ) 이외에 μ‚­μ œν•˜κΈ°λ„ μžˆμ—ˆμœΌλ©΄ 함
  2. μ•¨λ²”μ—μ„œ 사진을 λˆ„λ₯΄κ±°λ‚˜ ν™•λŒ€λ₯Ό 톡해 사진을 μ’€ 더 μžμ„Ένžˆ λ³Ό 수 있으면 쒋을 것 κ°™μŒ
  3. (ε‰Šι™€) 앨범 클릭 μ‹œ, 404 화면이 λœ¨λŠ” κ²½μš°κ°€ 있음 -> 앨범 이름이 '.'인 경우 (ε‰Šι™€γ“γ“γΎγ§)#145


κ²Œμ‹œλ¬Ό 상세

  1. (ε‰Šι™€) μ‹€μ œ μ—…λ‘œλ“œν•œ λ‚ μ§œμ˜ λ‹€μŒλ‚ λ‘œ λ‚˜μ˜΄ (ε‰Šι™€γ“γ“γΎγ§)412e163


κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ/μˆ˜μ •/μ‚­μ œ

  1. κΈ°μ‘΄μ—” 앨범에 λ“€μ–΄κ°€ μžˆλŠ” μƒνƒœμ—μ„œ μ—…λ‘œλ“œλ₯Ό λˆŒλŸ¬λ„ 앨범 선택을 λ”°λ‘œ λˆŒλŸ¬μ•Ό ν•˜λŠ”λ°, λ§Œμ•½ 앨범에 λ“€μ–΄κ°„ μƒνƒœμ—μ„œ μ—…λ‘œλ“œν•˜κ³ μž ν•˜λ©΄ μ €μ ˆλ‘œ μ–΄λ–€ 앨범인지 μ„ νƒλ˜λ©΄ μ’‹κ² μŒ
  2. μ‹œκ°„μ΄ 였래 κ±Έλ¦¬λŠ” 경우 있음
  3. 사진을 μ—¬λŸ¬μž₯ 올릴 λ•Œ 닀쀑 선택이 κ°€λŠ₯ν•˜λ©΄ μ’‹κ² μŒ


곡유 앨범

  1. 곡유 앨범을 λ§Œλ“€κ³  μ‚¬μš©μžλ₯Ό μ΄ˆλŒ€ν•˜λ©΄ 사진을 같이 λ³Ό 수 μžˆλ‹€λŠ” 게 μž¬λ°ŒλŠ” 뢀뢄인 κ±° κ°™μŒ
  2. 곡유 앨범을 λ§Œλ“€ λ•Œ, μ‚¬μš©μžλ₯Ό μ΄ˆλŒ€ν•΄μ•Όλ§Œ 곡유 앨범(ν™ˆ)에 앨범이 μƒκΈ°λŠ” 것을 λͺ°λžμŒ. μ„€λͺ…이 ν•„μš”ν•  것 κ°™μŒ


기타

  1. (ε‰Šι™€) μ—…λ‘œλ“œ λͺ¨λ‹¬μ—μ„œ 기기의 λ’€λ‘œκ°€κΈ°λ₯Ό λˆ„λ₯΄λ©΄ μ–΄ν”Œμ΄ μ’…λ£Œλ˜λŠ” ν˜„μƒμ΄ λ‚˜νƒ€λ‚¨ -> AndroidManifest.xmlμ—μ„œ λ”λŠ” μ§€μ›ν•˜μ§€ μ•ŠλŠ” 속성을 μ œκ±°ν•œ ν›„ 해결됨 (ε‰Šι™€γ“γ“γΎγ§)832a5ab
  2. μ•±μŠ€ν† μ–΄λ‘œλ„ μ„€μΉ˜ν•˜κ³  μ‹ΆμŒ
  3. 곡유 앨범에 λ°˜μ‘μ„ 남길 수 있으면 μ’‹κ² μŒ. μ’‹μ•„μš” ν˜Ήμ€ μŠ€ν‹°μ»€. λ‹€μ–‘ν•œ μŠ€ν‹°μ»€λ₯Ό νŒλ§€ν–ˆμœΌλ©΄ μ’‹κ² μŒ
  4. κ³΅μœ λ°›μ€ 앨범에 사진을 올리고 μ‹ΆμŒ
  5. 사진 보정도 ν•  수 있으면 μ’‹κ² μŒ. 밝기 μ‘°μ •, 채도 μ‘°μ • λ“±
  6. μ—…λ‘œλ“œ λ‚ μ§œλŠ” ν˜„μž¬ μžλ™μœΌλ‘œ μ €μž₯λ˜λŠ”λ°, 직접 μˆ˜μ • κ°€λŠ₯ν•˜λ©΄ μ’‹κ² μŒ

λͺ©μ°¨λ‘œ ▲さんかく


7. πŸš€ 버전 2(λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, κΈ°λŠ₯μΆ”κ°€)

1) React -> Next.js Migration 이유

  • Admin SDK μ‚¬μš©: v2의 앨범 곡유 κΈ°λŠ₯ μΆ”κ°€λ₯Ό μœ„ν•΄ Admin SDKλ₯Ό μ‚¬μš©ν•΄μ•Ό ν–ˆκ³ , 이λ₯Ό μœ„ν•΄ μ„œλ²„ ν™˜κ²½μ„ ꡬ좕해야 ν–ˆμŠ΅λ‹ˆλ‹€.

  • μ„œλ²„ μ‚¬μ΄λ“œ λ Œλ”λ§ (SSR) 지원: SSR을 톡해 SEOλ₯Ό ν–₯μƒμ‹œν‚€κ³  초기 νŽ˜μ΄μ§€ λ‘œλ”© 속도λ₯Ό κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    초기 λ Œλ”λ§ 속도 μ•½ 78% κ°œμ„  (FCP, LCO, Speed Index)


2) 달라진 κΈ°λŠ₯

앨범 곡유 (μ‹ κΈ°λŠ₯)
  • 앨범 곡유 λͺ¨λ‹¬μ„ 톡해, 곡유 λŒ€μƒμ„ 검색/μΆ”κ°€/μ‚­μ œν•  수 μžˆλ‹€

  • ν™ˆμ—μ„œ 곡유 앨범을 확인할 수 μžˆλ‹€

    πŸ‘‰
    v1 v2

  • 곡유 받은 μ‚¬μš©μžλŠ” ν•΄λ‹Ή μ•¨λ²”μ˜ λͺ¨λ“  사진을 λ³Ό 수 μžˆλ‹€

  • ν˜„μž¬ read κΆŒν•œκΉŒμ§€ 개발 μ™„λ£Œ. write, admin κΆŒν•œ μΆ”κ°€ μ˜ˆμ •

κ²Œμ‹œλ¬Ό μ—…λ‘œλ“œ λͺ¨λ‹¬
  • κΈ°μ‘΄: 사진 선택 및 전체 μž¬μ„ νƒ κ°€λŠ₯
  • κ°œμ„ : 사진 선택 ν›„, 일뢀 μ‚­μ œ 및 μΆ”κ°€ 선택 κ°€λŠ₯
πŸ‘‰
v1 v2

3) λ¦¬νŒ©ν† λ§

API μ—”λ“œν¬μΈνŠΈ
  • κΈ°μ‘΄: νŒŒμ΄μ–΄λ² μ΄μŠ€μ™€μ˜ λͺ¨λ“  톡신을 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ²˜λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

  • κ°œμ„ : νŒŒμ΄μ–΄λ² μ΄μŠ€μ™€μ˜ 톡신 λ‘œμ§μ„ λ°±μ—”λ“œλ‘œ λΆ„λ¦¬ν•œ μ΄μœ λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

    • μœ μ§€λ³΄μˆ˜μ„± ν–₯상을 μœ„ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 뢄리
    • μš”μ²­ μ€‘λ‹¨μœΌλ‘œ μΈν•œ 데이터 손싀 λ°©μ§€
    • λ³΄μ•ˆ κ°•ν™”

    // src/app/api/user/route/ts
    export async function DELETE() {
     const uid = cookies().get('uid')?.value;
     if (!uid) {
     return NextResponse.json(
     {
     error: 'μΈμ¦λ˜μ§€ μ•Šμ€ μ‚¬μš©μžμž…λ‹ˆλ‹€.'
     },
     {
     status: 401
     }
     );
     }
     try {
     const { photoURL } = await getUserByUid(uid);
     await Promise.all([
     deletePhothURL(photoURL),
     deleteFeedsImg(uid),
     deleteUserDoc(uid),
     deleteAlbumDocs(uid),
     deleteFeedDocs(uid)
     ]);
     await adminAppAuth.deleteUser(uid);
     } catch (error) {
     console.error(error);
     return NextResponse.json(
     {
     error: '계정 μ‚­μ œ 쀑 예기치 λͺ»ν•œ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.'
     },
     {
     status: 500
     }
     );
     }
     return NextResponse.json({
     status: 204
     });
    }

4) μ‚¬μš©μ„± κ°œμ„  및 버그 μˆ˜μ •

6. μœ μ € ν”Όλ“œλ°±μ„ μ°Έκ³ ν•΄μ£Όμ„Έμš” :)

λͺ©μ°¨λ‘œ ▲さんかく


8. πŸ”₯ Firebase ꡬ쑰

Firestore Database
// {uid}/{uid}
{
 sharedAlbums: Reference(albumDoc){}
}
// {uid}/{uid}/album/{albumId}
{
 createdTime: Timestamp;
 feedList: String(feedId)[];
 name: String;
 sharedUsers: {uid:String; permission: "read"}[];
}
// {uid}/{uid}/feed/{feedId}
{
 id: String;
 title: String;
 text: String;
 seletedAddress: String;
 emotionImage: String;
 weatherImage: String;
 timestamp: Timestamp;
}
Storage
feed/{feedId + imageIndex}.{ν™•μž₯자}
profile/{uid}.{ν™•μž₯자}

λͺ©μ°¨λ‘œ ▲さんかく


9. βœ”οΈ Best Practices

μ ‘κ·Όμ„±

μ»¨λ²€μ…˜

λͺ©μ°¨λ‘œ ▲さんかく


10. πŸ“š ν”„λ‘œμ νŠΈ κ΄€λ ¨ λ¬Έμ„œ

λͺ©μ°¨λ‘œ ▲さんかく

About

πŸ“·λͺ¨λ¬΄λŠ” 넀컷사진을 κΈ°λ‘ν•˜λŠ” μ›Ή/μ•± μ„œλΉ„μŠ€μž…λ‹ˆλ‹€.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

Languages

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /