오늘은 어제에 이어 Node.js 공부를 마저 한 후에, DB 연동을 위한 사전 작업을 해보았다.
DB 연동에 앞서, 일단 로그인 후에 현재 접속한 id를 shared preference에 저장하는 작업을 해주었다. 막상 DB 연동을 하려다보니 '현재 어떤 유저가 로그인 중인지'를 기반으로 GET, POST 요청을 보내야하기에, 그때마다 현재 로그인 중인 id를 확인하는 것이 번거롭고 어플리케이션 상에서도 시간을 추가적으로 소요하는 것 같았기 때문이다. 최종적으론 토큰으로 확인하도록 해야겠지만 아직 그 부분은 팀원분께서 열심히 구현 중이시기에, 일단은 id를 킵해둘 수 있도록 조치하였다.
shared preference를 쓰기 위해선 몇 가지 작업이 필요한데, 우선 pubspec.yaml에 dependency를 하나 추가해주어야 한다. 추가해준 후에는, 커서를 올렸을 때 나오는 전구버튼을 눌러서 Pub get을 해주어야 한다. (혹은 터미널에서 flutter pub get을 해주어도 된다 )
dependencies:
....
shared_preferences: ^2.0.11
이후엔 shared_preferennce를 사용할 때, 해당 dart 파일 위에 두 줄을 import 해주어야 한다고 한다. 여기서 convert는 JSON을 처리할 수 있는 함수 등 유용한 함수들이 담긴 패키지인데, shared preference에 꼭 필요한거 같지는 않다.
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
이렇게 하면 기본적인 세팅은 끝났고, 이후엔 async, await을 걸어서 저장공간을 불러와서 사용하면 된다.
saveData() async{
var storage = await SharedPreferences.getInstance();
}
우리 프로젝트의 경우엔, 로그인 한 후에 id를 저장하도록 다음과 같이 처리해주었다.
saveData(id) async {
var storage = await SharedPreferences.getInstance();
storage.setInt('id', id);
}
이렇게 한번 저장하고 난 후엔, 다음과 같이 간단하게 현재 로그인 중인 id를 뽑아올 수 있다!
var NowId;
saveData(id) async {
var storage = await SharedPreferences.getInstance();
setState( (){nowId = storage.getInt('id');} );
}
이번에는 POST 요청을 임의로 보내서 만든 샘플데이터가 아니라, 실제 유저가 명함을 만드는 것처럼 imagePicker로 직접 사진을 선택하기 위한 작업을 해주었다. 현재로썬 에뮬레이터에 별 사진이 들어있지 않아서, 서로 다른 계정에 다양한 사진을 넣기가 어려웠다. 그러던 와중에, 안드로이드 에뮬레이터 갤러리에 사진 업로드 하는 방법(꼼수)라는 글을 발견하고, 사전 작업을 해보았다.
사실 이 글에서 첫 번째로 권유해준 방법은 안드로이드 스튜디오 내에서 VIEW > Tool Windows > Device File Explorer를 켜서, sdcard > Pictures에서 업로드해주는 방식이었다. 하지만 이 방법으로 진행하려고 하니까, 진짜 계속 안드로이드 스튜디오가 먹통이 됐다.... 난 RAM 추가도 했는데.... 이게 뭐냐고오.....
그래서 이번엔 '안드로이드 에뮬레이터 상에서 스토리지의 갤러리에 직접 드래그해서 넣는 방법'을 시도해보았는데, 약간의 우여곡절 끝에 성공했다. 글에서는 Storage 내에 가상 SD card로 접근하라고 했으나, 내 에뮬레이터에는 SD card가 없었다.
그래서 다음과 같이 해결했으니, GIF를 참고해보면 되겠다.
step 0 ) 홈에서, 화면을 위로 드래그해서 어플리케이션 목록이 나오게 만들기
step 1 ) Settings 선택
step 2 ) Storage 선택
step 3 ) Images 선택
step 4 ) 폴더 중 하나 선택
step 5 ) 데스크톱에서 원하는 사진 드래그해서 넣기
참고로 반영되기까진 넉넉잡아 한 10분 정도는 소요된 것 같다 😄
10분 기다리고 나니, 테스트 계정용 이미지 NEMO100~NEMO105가 잘 나타났다 !
이렇게 해서 사전 작업을 마치고, 이제는 실제로 에뮬레이터 상에서 카드 생성을 해주었다.
그리고, 각 계정 별로 생성한 카드를 DB에서 현재 id를 기준으로 연동해주었다. 아직 DB에 태그별 이미지, 그리고 자기소개 등은 저장하지 않았기에, 다음과 같이 현재 연동가능한 부분만 일단 GET요청을 통해 가져오도록 해주었다. 추가적인 DB 연동을 위해선 모델을 수정 및 보완해야 하는데, 이 부분은 나 혼자서 바로 처리할 부분은 아니라 내일 팀원들과 논의한 후에 진행하도록 하겠다!
getMyCard(id) async {
try {
var dio = Dio();
Response response = await dio.get('http://34.64.217.3:3000/api/card/$id');
if (response.statusCode == 200) {
final json = response.data;
setState(() {
user = UserProfile(
imagePath: json['img_url'],
nickname: json['nickname'],
introduction: json['intro'],
title: json['intro'], // title로 DB 연동 필요
about: json['intro'], // about로 DB 연동 필요
image: [
'https://images.unsplash.com/photo-1546519638-68e109498ffc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1780&q=80',
'https://images.unsplash.com/photo-1506880018603-83d5b814b5a6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1548&q=80',
'https://wallpaperaccess.com/full/1935243.jpg',
], // tag_image로 DB 연동 필요
tag: [
json['tag_1'],
json['tag_2'],
json['tag_3'],
],
);
});
print('접속 성공!');
return true;
} else {
print('error');
return false;
}
} catch (e) {
return false;
}
}
오늘도 풀어냈다! 바로 설명 들어갑니다.
오늘 풀어본 문제는 모음사전이라는 문제였다.
문제를 본 후에, 우선 AAAA vs AAAE , 그리고 AA vs AAA를 비교해보았다.
해보니까 문제에서 정의하는 사전의 대소비교와 일맥상통해서, 그냥 AEIOU를 가지고 한자리~다섯자리를 만든 후에 정렬하면 되겠다고 생각했다. 근데 처음에는 itertools.product까진 생각났는데, repeat이라는 인자를 미처 떠올리지 못했다. 그래서 그냥 직접 다 만들었다.
# 프로그래머스 # 모음사전
# 첫번째 풀이 # itertools.product( , repeat = ) 랑 L.index()가 생각이 안나서 걍 직접 다 만듬
def solution(word):
answer = 0
L = []
def make(n,now):
L.append(now)
if n == 5:
return
for c in 'AEIOU':
make(n+1, now+c)
for c in 'AEIOU':
make(1,c)
i = 1
while True:
if word == L[i-1]:
return i
i += 1
이렇게 해서 일단 통과는 했는데, 다음에는 더 짧게 풀어내기 위해서 추가적으로 공부 후에 줄여보았다.
# 두번째 풀이 # itertools.product랑 index 사용 # 약간 더 빠름
from itertools import product
def solution(word):
L = []
for i in range(1,6):
L.extend(list(product('AEIOU', repeat=i)))
return sorted((map(lambda x: ''.join(x), L))).index(word)+1
# 이걸 한줄로 줄이면, sorted(["".join(c) for i in range(1,6) for c in product("AEIOU", repeat=i)]).index(word) + 1
# return {''.join(k):v for v,k in enumerate(L,1)}[word] # 이렇게 하면 느림
문제에서 정의해준 그대로 '사전'을 만들고 인덱싱으로 찾는 방법도 생각해봤는데, 직접 해보니까 오히려 느렸다. 어차피 index로 하면 위치를 찾을 수 있는데, 굳이 enumerate를 쓴 후에 인덱싱까지 하니까 더 느린거 같았다.
더 효율적인 풀이를 찾아서 고민해보았지만, 결국은 itertools.product와 리스트의 index 메소드를 쓰는 것으로 귀결....! 다음에는 까먹지말고 잘 기억해내서 빨리 풀어야겠다 💪🏼