🖥️ 프로젝트 소개
유머와 편리함이 만나 10~30대의 SNS 사용자, 블로거 및 PPT 이용자를 대상으로 즐거운 경험을 선사하는 우리는 “짤뮤니티” 입니다.
유머, 편리함, 짤 추천, 짤 채팅, 커뮤니티, 10~30대, SNS 사용 유저, 블로거, 피피티 이용자
우리의 서비스를 통해 사용자들은 다양한 취향과 선호도에 따라 추천되는 흥미로운 짤 컬렉션에 쉽게 접근할 수 있습니다. 태그 기반 검색과 추천 서비스를 통해 사용자들은 원하는 짤 신속하게 찾을 수 있습니다.
사용자가 업로드가 가능해 보다 다양한 짤을 제공받을 수 있습니다.
짤을 활용한 채팅 서비스를 통해 사용자들은 다양한 사람들과 소통하며 짤을 통한 이야기를 나누고 즐길 수 있습니다.
기획 의도
단순히 짤을 찾는 것을 넘어, 사용자들이 짤로 소통하고 교류할 수 있는 활기찬 커뮤니티 플랫폼을 제공하는 것이 목적입니다.
- 태그 기반 검색과 개인 맞춤 추천을 통해 빠르고 정확한 짤을 제공
- 짤 채팅 서비스를 통한 특별하고 재밌는 경험 선사
서비스 필요성
- 다양한 짤을 활용한 채팅
- 서비스는 짤을 찾는 도구에 그치지 않고, 채팅방 서비스를 통해 사용자들이 짤을 활용해 자유롭게 소통하며 새로운 경험을 즐길 수 있는 공간을 제공합니다.
- 개인 맞춤형 추천
- 좋아요, 사용 기록 등을 기반으로 하는 개인화된 추천 서비스를 통해 사용자는 자신의 관심사와 취향에 맞는 다양한 짤을 발견할 수 있습니다.
- 태그 기반 검색
- 사용자는 태그 기반 검색을 통해 필요한 짤을 빠르게 찾을 수 있습니다. 불필요한 정보나 텍스트와 관련 없는 검색 결과를 최소화하여 정확하고 간편한 이용을 제공합니다.
- 공유를 통한 다양한 짤 경험
- 짤 업로드, 좋아요 등을 통해 사용자들은 서로의 창작물을 쉽게 공유하고 교류합니다. 이를 통해 다양한 스타일과 주제의 짤을 더욱 쉽게 접할 수 있습니다.
시장 조사
관련 웹/앱에 대한 조사
1) 오늘의짤방
키워드 기반으로 여러 상황에 어울리는 움짤을 정리해 놓은 사이트

특징
- 검색과 태그를 통해 관심 짤을 찾을 수 있다.
- 인기있는 짤을 추천 받을 수 있다.
- 짤을 다운로드, 좋아요, 공유할 수 있다.
- 짤을 편집하여 생성할 수 있다.
- 짤을 등록할 수 있다.
단점
- 상단에 광고가 있다.
- 실시간 이슈 짤을 상단에 보여줘, 관심 태그에 해당하는 짤을 스크롤을 내려야 확인할 수 있다.
- 짤과 관련 없는 기능을 제공한다. (짤뉴스, 게시판)
“짤뮤니티”의 차별점
- 채팅방을 통해, 짤로 소통할 수 있다.
- 광고가 없어, 사용자의 경험을 해치지 않는다.
- 원하는 정보를 다른 정보의 방해를 받지 않고 바로 볼 수 있다.
2) 2짤
다양한 움짤을 한눈에 볼 수 있고 검색할 수 있는 사이트

특징
- 검색을 통해 관심있는 짤을 찾을 수 있다.
- 짤을 복사, 다운로드, 좋아요를 할 수 있다.
- 짤을 편집하여 생성할 수 있다.
- 짤을 등록할 수 있다.
단점
- 페이지마다 광고가 있고, 팝업 광고도 뜬다.
- 짤을 눌렀을 때 상세를 볼 수 없다. (보기 이모지를 눌러야 상세로 이동)
“짤뮤니티”의 차별점
- 채팅방을 통해, 짤로 소통할 수 있다.
- 광고가 없어, 사용자의 경험을 해치지 않는다.
- 짤 상세로 쉽게 이동할 수 있다.
- 태그를 통해 관심있는 짤을 찾을 수 있다.
3) GIPHY
서양 쪽 움짤이 모여있는 외국 사이트

특징
- 검색과 태그 통해 관심있는 짤을 찾을 수 있다.
- 짤을 복사, 다운로드, 좋아요를 할 수 있다.
- 짤을 편집하여 생성할 수 있다.
- 짤을 등록할 수 있다.
- 앱 서비스가 있다.
단점
- 영어로 되어있다.
- 외국 관련 짤이 대부분이다.
“짤뮤니티”의 차별점
- 채팅방을 통해, 짤로 소통할 수 있다.
- 한글로 되어있다.
- 한국에 익숙한 짤을 사용할 수 있다.
기술 스택
BE
10FE
10FE 세팅
5Team
6기능 명세서
기능 명세서 (1)
와이어프레임
개발 문화 및 컨벤션
FE 컨벤션
개발 컨벤션
컴포넌트 작성 방식, 네이밍 규칙, 프로젝트 폴더와 파일 구조 등 필요한것들을 정하여 일관성 있게 개발합시다!
[중요] 줄임말은 쓰지 않는다. 줄임말은 어떠한 경우에도 사용하지 않습니다.
res
e(이벤트 객체)
i
등 과 같은 모든 줄임말은 금지합니다.1. 함수 export 방식 선언 후 export
👈VS 선언과 동시에 export
함수 선언 방식은
const
를 사용합니다.const Component = (props: Props) => {} export default Component;
- tsx를 반환한다면 확장자 이름을 .tsx를 사용합니다.
3. ASI를 이용하지 않고 세미콜론을 필수적으로 써줍니다. (prettier로 관리).
// Uncaught TypeError: 1 is not a function let a = 1 (function() { console.log("Hello!"); })();
4. 리터럴 값은 상수로 만들어서 사용합니다. 상수는 스네이크 케이스를 사용합니다.
const BASE_URL = 'http://localhost3000';
- 모든 함수는 화살표 함수로 작성합니다.
- var를 쓰지 않고, const와 let을 사용합니다.(단, const를 주로 쓰되 변수의 값 변경이 필요할 경우 let을 쓴다.)
- image, svg는 케밥 케이스 사용하여 네이밍합니다.(ex. erase-check.svg).
- 변수명은 camelCase로 작성합니다. (issueLabel).
- .tsx 파일의 파일(폴더)명은 PascalCase를 사용합니다. ex) LoginPage.tsx.
- 절대 경로로 import, export 사용합니다. src: @, test: #
- export할때 barrel export 방식을 사용하지 않습니다.
- 타입을 분리할 경우(여러 곳에서 타입이 생성될 경우(2군데 이상)) types 디렉토리에 관리한다.
- 최대한 코드에 대한 설명 주석은 적지 않습니다. 이름만 읽어도 무슨 일을 하는 함수인지 알 수 있어야합니다.
- 만약 주석이 필요한 경우
// TODO:
해야 할 일 혹은 한 일을 날짜와 함께 적어줍니다.(2022.09.01). 신경써서 사용하기
// TODO: [2024.02.01] 해야 할 일
- 변수명이나 함수명이 길어도 좋으니 한눈에 봐도 알아볼 수 있는 최대한 명시적인 변수명을 정해줍니다. 단, 의미없거나 불필요한 접두사나 접미사가 붙는 것은 지양합니다.(ex)
currentTodoListData
(X) ⇒todoList
(O))
변수명은 명사를 사용(단, 플래그들의 is, has는 예외) 함수명은 동사 + 명사
16. 이벤트 핸들러를 정의할때 handle + 메서드명로 정의합니다.
on
접두사는 하위 컴포넌트에 Props
로 전달할때 사용합니다.handle
접두사가 붙은 경우, 이벤트가 발생했을 때 호출되는 실제 Function을 의미합니다.(handle + 이벤트 + 버튼)function DateTypeToggleButton ({ onClick }) { return <button onClick={onClick} /> } function ModalButton ({ onClick }) { return <button onClick={onClick} /> } function Calendar () { const handleClickDateType = () => {} const handleModalOpen = () => {} /* 주의!! 컴포넌트의 props로 핸들러를 넘길때는 on 접두사를 사용해야 합니다. */ return ( <> <DateTypeToggleButton onClick={handleClickDateType} /> <ModalButton onClick={handleModalOpen} /> </> ) }
- 화살표 함수 작성시 한 개의 파라미터만 사용하더라도 중괄호 사용(prettier로 관리)
- 선언부, 구현부 사이에는 줄 간격 해줍니다. 이외에 의미가 서로 다른 부분이라면 줄 간격 필수.
18. 인라인 함수는 사용하지 않습니다. 함수를 생성하여 할당해주세요.
function MyComponent() { return ( // ❌ <button onClick={() => setClose(true)}>버튼</button> ); }
- 후위 연산자 사용하지 않습니다.
++
--
- import할때 형제 파일의 경우는 절대 경로 사용하지 않고, 상대 경로 사용합니다.
./component.tsx
- 컴포넌트의 Props type의 이름은 항상
Props
로 생성한다. tsx를 반환하지 않는 ts 파일의 경우에는Parameters
이름으로 생성한다.
- 컴포넌트와 커스텀 훅만
export default
- children 타입은
ReactNode
interface
를 주로 사용하고, interface를 사용할 수 없을때는type
사용
- h1, h2,…헤딩 태그들을 스타일용으로 사용하지말자. 접근성 위배
git 컨벤션
이슈 컨벤션
## 🔨 설명 작업할 내용에 대해 상세하게 설명해주세요. ## 📑 완료 조건 어디까지 개발할 것인지 목표에 대해 설명해주세요.
template에 맞게 issue를 작성해주세요. 기존에 만들어둔 template을 사용하면 됩니다.😀
(작업마다 이슈를 작성하는 방법에 한합니다. 구현할때마다 이슈를 생성하는 방법을 따르지 않는다면 위 방법은 사용하지 않습니다.)
이슈 단위 브랜치
이슈마다 브랜치가 1개 있는 셈입니다.
- branch
#이슈번호/feature/ #이슈번호fix/ #이슈번호/test/ #이슈번호/refactor/ ex. #11/feature/make-home-page(cabab-case)
issue 만들고, 그 issue에 맞는 번호를 확인한 뒤, 이 번호에 따라 branch 생성.
branch 이름은 다음과 같은 규칙으로 작성해주세요.
merge가 완료되어 작업이 끝났다면 반드시 branch를 삭제해주세요. 삭제하지 않는다면 추후에 같은 이름의 브랜치가 생성되었을 때 충돌이 발생할 수 있습니다. 충돌은 본인이 확인해서 해결 부탁드립니다.
fix, refactor 또한 issue 작성 후, issue 제목에 맞게 브랜치 생성해서 작업 부탁드립니다.
git commit message convention
- commit(유의미한 작업 별로 쪼개서 자주 커밋 부탁드립니다)
Feat: commit 내용 바디 (좀 더 상세한 커밋 내용) ex. Feat: make-home-page 컴포넌트 구현 - 컴포넌트 구현 완료
해당 이슈와 관련없는 커밋은 하지 않습니다. 관련없는 커밋이 필요하다면 새로운 이슈를 작성하고 브랜치를 변경해주세요. 첫 글자는 대문자로 적어주세요
- Feat : 새로운 기능 추가 - Fix: 버그 수정 - Docs: 문서의 수정 - Style: (코드의 수정 없이) 스타일(style)만 변경 - Refactor: 기존 기능과 동일하게 동작하지만 코드를 리팩토링. - Test: Test 관련한 코드의 추가, 수정 (Storybook 작업 포함) - Chore: (코드의 수정 없이) 설정을 변경 및 새로운 라이브러리 혹은 패키지 설치 - Modify: 기존 기능의 변경(코드 변경) - Rename: 디렉토리 구조 변경. 함수 이름 및 변수 이름 변경. - Cleanup: 콘솔 로그 및 주석 삭제, 파일 삭제, 불필요한 함수 삭제, 코드 위치 변경 - Merge: pull 과정 중 현재 commit과 자동병합이 일어날때 필수적으로 적어줘야하는 commit에 적어줌
PR convention
# pr 제목은 아래와 같이 작성해주세요. [#이슈 번호] Commit Type: pr 제목 ## 📝 작업 내용 > 이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능) ### 📷 스크린샷 (선택) ## 💬 리뷰 요구사항(선택) > 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요 > > ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요? # 📍 기타 (선택) > 다른 분들이 참고해야할 사항이 있다면 작성해주세요 close #이슈번호
PR title convention
다음과 같은 형식으로 pr 제목을 작성해주세요.
[#이슈번호] keyword: 구현 내용 간략히 ex) [#11] Feat: make-home-page 컴포넌트 구현
merge 전략
dev 브랜치 없이, squash merge 사용. 커밋을 너무 잘게 쪼갰을 경우, 같은 기능끼리 묶어서 rebase 해주시면 좋을 것 같습니다.
eslint
- eslint-recomment + import/order
- import 마다 개행 추가
- tailwind css lint
prettier
{ "printWidth": 100, "tabWidth": 2, "semi": true, "singleQuote": false, "trailingComma": "all", "arrowParens": "always", "bracketSameLine": false, "useTabs": false, "plugins": ["prettier-plugin-tailwindcss"] }
일정 관리
팀 구성, 역할
BE
- 팀장 : 김용상
- PL (CTO, 전반적인 BE 개발 프로세스 관리) : 소승수
FE
- 팀장 : 최익
- PL (CTO, 전반적인 FE 개발 프로세스 관리) : 김재민
피드백
2팀
- v1-1 이후 업무 분담이나 일정도 궁금해여
- 이미지 저작관 관련 이슈는 없었나요 ?
- 이미지 캐싱은 어떻게 처리하셨나요?
- A. react query의 캐싱 사용중입니다!
- 태그 검색은 어떤 방식으로 구현하셨나요 ?
- 엘라스틱 서치와 Sql 기반의 구현을 고민하다 , “태그” 하나로만 검색하면 되는 상황이라 sql 기반 검색을 이용했습니다
- 스켈레톤 UI 디자인이 핀터레스트가 떠오르는데 재밌어 보입니다!
- 이미지 압축도 혹시 하셨나요?!
- A. 이미지 압축은 하지 않았고, progressive jpeg를 사용하지 않을까 합니다.
9팀
- 저 진짜 짤 너무 잘쓰는 유머러스한 인간이 되고 싶었는데 저한테 딱 맞는 서비스겠네요.
- A.하하 열심히 잘 만들어서 질문 남겨주신 분도 유머러스한 인간이 될 수 있도록 기여하겠습니다..!
- 저는 이미 유머러스한 사람이에요.
- Good!
- 아이디어는 처음에 어떻게, 누가 내셨나요??
- A.처음에는 저희도 매칭 시스템 같이 사용자 범위를 좁히려 했었는데 계속 고민하며 의견을 나눈 결과 모든 팀원 분들이 사용자 범위를 조금 더 넓히면 좋을 것 같다고 이야기가 나와서 브레인 스토밍을 통해 짤방? 시스템을 구현하기로 했습니다 ㅎㅎ 제 기억에는 재민님이 최초 의견 내 주신걸로 기억해요 ㅎㅎ
- 역시 킹갓제네렐엠페럴 재민님. 그는 누구인가? 그는 빛인가? 맙소사 앞이 안보입니다.
- A. 그렇게 느끼시나요? 저희도 마찬가지입니다 ㅋㅋㅋㅋㅋ 우리 프론트팀 대장님~^&^
- 개인화된 추천 서비스는 어떤 방식으로 동작하는건가요? 어떻게 구현한지 궁금해요.
- A.좋아요와 태그 사용 횟수를 기반으로 알고리즘을 구현하기로 했는데 사실 이 부분은 백 분들이 오셔서 대답해주시는게.. 하하 → 좋아요랑 자주 조회,검색하는 이미지에 달린 태그 기반으로 추천해주고있습니다!
- Q. 혹시 적용된 알고리즘이 따로 있는건가요?
- A. 현재로서는 협업 필터링 이라는 알고리즘 이용해서 구현중입니다!
- 오오.. 멋있어요 한번 찾아보겠습니다 ㅎ
- 짤 데이터는 어떻게 수집하셨는지, 수집하고 계신지?? 아 짤을 직접 사용자가 넣는군요. 필터링이 중요하겠네요.
- 약 천 개의 총알 장전 했습니다.
- 무도 있나요? 이제는 더이상 물러날 곳이 없다~등등..
- FE에서 채팅은 StompJS + SockJS를 사용하고 계신것 같은데 어려움은 없으셨나요?
- TanStack Router의 사용 후기가 궁금해요. react-router과 어떤 차이가 있는지, 장/단점이 궁금합니다.
- next.js의 file 기반 라우팅 가치관을 많이 가져왔다고 생각합니다. 단점은 아직 v1밖에 없고, 레퍼런스도 적어서 공식문서에만 의존할 수 있는 점인 것 같습니다. 장점은 파일 기반 라우팅이라 디렉토리 구조만 설정해도 라우팅 설정이 자동으로 설정되는 것 같아요. 또 라이브러리 자체에서 loader, prefetching 등 기능을 주입할 수 있게 해주는 것 같습니다
- A. tanstack router 짱짱짱. suspense 붙일때 아주 편하고 직관적으로 사용할 수 있었습니다. react router로 못돌아갈 것 같아요. next 안써도 tanstack router가 맞다!
- Q. 파일 기반 라우팅이라고 하셨는데 react-router의 createHashBrowser, Router, Routes, 이런걸 사용하지 않아도 라우팅을 설정할 수 있는건가요?
- A. 넵 파일을 생성하면 자동 라우팅 설정이 됩니다
10팀
- Jotai를 선정하신 이유가 있을까요??😍
- 상태 관리 라이브러리중 가장 React 친화적이라고 느껴져서 선택하였습니다. react의 state와 비슷하여 러닝커브도 높지 않으며 빠르게 배우고 적용해 볼 수 있다는 점이 장점으로 느껴저서 사용하게 되었습니다.
- Tanstack Router를 선정하신 이유가 있으실까요?
- 질문 남겨주신분 바로 위에 같은 질문이 있어서 저희팀이 달아주고 계신데 확인해주시면 감사하겠습니다 ㅎㅎ
- A. react router에서 가장 아쉬운 점이 path type이잖아요. 근데 tanstack router는 타입을 더 확실히 잡아준다고 유명해서 사용해보고 싶었습니다. 최근에 아주 핫하기도 했고!! 근데 막상 사용해보니 그 tanstack query와 잘 사용할 수 있어 좋았습니다.