# 기능 B 구현
## 참가자 - 3주차
| **김세영** | **신우진** | **신효근** | **이용광** | **이재영** | **이태욱** | **박태현** | **정지승** |
| :-------: | :-------: | :-------: | :-------: | :-------: | :-------: | :-------: | :-------: |
| <img src="https://avatars.githubusercontent.com/u/63814960?v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/76616101?v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/52554235?v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/48857296?s=400&v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/42104898?s=400&v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/72855455?v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/37128456?v=4" width="80"> | <img src="https://avatars.githubusercontent.com/u/49086747?v=4" width="80">
| [J034 김세영](https://github.com/se030) | [J113 신우진](https://github.com/gintooooonic) | [J116 신효근](https://github.com/dldydrhkd) | [J147 이용광](https://github.com/yjooooo) | [J157 이재영](https://github.com/lee-3-8) | [J167 이태욱](https://github.com/Najeong-Kim) | [K025 박태현](https://github.com/CrewDaniel) | [S053 정지승](https://github.com/JungJiSeung)
## 프론트엔드 구현사항
기능 | 상태 | 관련 파일
--- | --- | ---
이미지 표시 | 완료 | ```stargram/main```
이미지 링크 복사 | 완료 | ```stargram/main```
페이지 이동 | 완료 | ```stargram/main``` ```stargram/upload_image```
### 메인페이지에서 랜덤으로 이미지 전시
[`flutter_staggered_grid_view`](https://pub.dev/packages/flutter_staggered_grid_view) 패키지를 활용하여 메인 페이지 UI를 구성하였습니다.
#### Retrofit으로 서버에서 이미지 url 다운로드
```.dart
loadImage() {
// 전체 이미지 다운로드
var imageData = server.getImages('');
imageData.then((imageList) {
this.imageList = imageList;
setState(() {
isLoaded = true;
});
});
}
```
#### `flutter_staggered_grid_view`로 UI 구성, 이미지 표시
```.dart
body: isLoaded
? StaggeredGridView.countBuilder(
primary: false,
itemCount: imageList.length,
crossAxisCount: 4,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
itemBuilder: (context, index) =>
_Tile(index, imageList[index].image),
staggeredTileBuilder: (index) => const StaggeredTile.fit(2),
)
```
itemCount로 아이템의 수와, itemBuilder로 내부 컴포넌트를 참조합니다.
```.dart
Center(
child: InkWell(
child: Image.network(
url,
),
onLongPress: () {
FlutterClipboard.copy(url).then((value) => {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('이미지 주소가 복사 되었습니다.'),
duration: Duration(milliseconds: 5000),
),
)
});
},
)),
```
서버에서 받아온 URL을 ```Image.network(url)``` 으로 불러와 표시합니다.
이미지를 길게 누르게 되면 이미지 주소(url)를 복사하고 Snackbar로 표시합니다.
### 이미지 다운로드
[`clipboard`](https://pub.dev/packages/clipboard) 패키지를 활용하여 메인페이지에서 이미지를 길게 누르면(long press) '이미지가 주소가 복사 되었습니다'라는 Snackbar와 함께 해당 이미지의 주소가 복사됩니다.
### 메인페이지 - 업로드 페이지 연결
메인 페이지 상단 우측에서 업로드 버튼을 통해 업로드 페이지로 이동합니다. (Navigator 활용)
```.dart
Widget build(BuildContext context) {
loadImage();
return Scaffold(
appBar: AppBar(),
body: isLoaded ? StaggeredGridView.countBuilder() : Text(''),
);}
```
### C 기능 작업시 변경해야할 사항
1. 서버 연동 IP 변경
* lib/retrofit/DiService.dart - BASE_URL 변경
* lib/retrofit/RetrofitService.dart - @RestApi 파라미터
* lib/retrofit/RetrofitService.g.dart - _RetrofitService 생성자 내부
* lib/upload_image.dart - uploadImageData() 함수 내부
</br>
## 백엔드 구현사항
기능 | 상태 | 관련 파일
--- | --- | ---
API를 위한 Express 서버 | 완료 | ```backend/```
데이터베이스 연동 | 완료 | ```backend/modules/db```
엘라스틱 서치를 사용한 동의어 검색 | 완료 | ```backend/modules/search```
이미지 업로드 | 완료 | ```backend/middleware/multer```
</br>
### /images 라우터
- `/images`로 `HTTP GET`을 받으면, MYSQL에 저장된 이미지들의 정보를 JSON으로 반환합니다.

</br>
### /upload 라우터
- `/upload`로 `HTTP GET`을 받으면, 이미지 업로드 폼을 띄웁니다.
- [PUG 템플릿 엔진](https://www.npmjs.com/package/pug)을 이용하였습니다.
- `/upload`로 `HTTP POST`을 받으면, 폼에 입력된 이미지의 정보를 백엔드 서버의 MYSQL에 저장합니다.
- 이미지 파일 저장은 [multer 미들웨어](https://www.npmjs.com/package/multer)를 이용하였습니다.

<br />
## 실행화면
