Available for hire

Withcamp 해커톤

hhkb_pro2

첫 야외 해커톤에, 첫 하드웨어 해커톤이다.

우리팀은 얼굴 각도를 인식해서 자동으로 뿅망치 맛을 보여주는 참참참 기계를 만들기로 했다. 톱질, 망치질, 사포질을 위해 몸을 쓰는 해커톤이라니! 신선하지 않을 수가 없다.

우리팀 팀원은 기계공학과 대학생과 대학원생들이었다. 설계하는데 다들 알파벳으로 이야기하니까 뭔가 있어보였다. 대충 설계를 끝내고 주최측에서 제공하지 않지만 필요한 물품들을 다이소에서 구매했다. 행사 당일 길거리에서 누가 버린 작은 책장과 목재를 가져다가 프레임을 만들고, 다이소에서 샀던 악력기를 뜯고 부셔서 뿅망치의 스프링으로 사용했다.

이 친구들은 코딩도 어느정도 할 줄 알아서 난 기기간 시리얼 통신만 열어주고, 코드가 작동하지 않으면 검수해서 고쳐주는 정도만 했다. 사실 코딩보다 하드웨어 만지는게 더 재미있어 보여서 대부분의 코드는 C#할 줄 아는 다른 팀원이 짰다. 뜨거운 물에 넣으면 녹아서 모양을 만들 수 있는 물라스틱, 사람 얼굴을 인식해서 데이터를 뽑아주는 인텔 리얼센스, 20만원짜리 모터(이름을 까먹었다)와 시리얼 통신으로 작동하는 하드웨어 모듈까지 조금도 쉴 새 없이 계속 새로웠다.

설계의 착오로 뿅망치 장전을 위해 낚시줄을 사용해 감아서 발표 때 1회 시연하고 망가져 버렸지만, 제대로 작동하는 걸 확인했다. 사회자님 눈은 괜찮으실라나.

모듈과 부품들 잔뜩 사놓고 취미삼아 만져봐도 재밌을 것 같다. 시간만 있다면…

9xd 해커톤

9xd에서 첫번째 해커톤을 한다길래 얼른 신청했다. 9xd 모임 신청이 수강신청만큼이나 경쟁률이 높아서 이번 해커톤도 아마 신청자 수가 만만치 않았으리라.

예전에 몇몇 해커톤에 불평하는 글을 쓰고 페이스북에 링크한 적이 있는데 9xd를 만든 진유림님이 그걸 공유하신 덕에 내 블로그 일일 방문자가 400을 찍었었다. 나와 비슷한 생각을 하고 계신 것 같아서 직접 주최하는 해커톤에 대한 기대가 컸다.

기대한 만큼 만족도 컸다.

팀 구성을 미리 하지 않았다. 참가자를 받으면서 팀을 미리 구성했지만 행사 당일에 팀을 발표했다. 참가 신청을 받을 때 참가자의 기술스택도 파악해서 아웃풋이 없는 팀이 나오지 않도록 적절하게 팀을 구성한 것도 박수.

주제가 어느정도 좁혀져 있었다. 주최측에서 정하는게 아니라 참가자끼리 주제를 여러개 만들고 랜덤으로 뽑아서 선정했다. 다수의 해커톤 경험을 미루어 볼 때, ‘무엇을 만들까’로 이야기가 길어지는 팀은 대부분 실패한다. 이 때문에 모든 팀이 빠르게 구현에 집중할 수 있지 않았나 싶다.

축제 분위기를 위한 많은 장치가 있었다. BM은 신경쓰지 않고 정말 만들고 싶었던 재미있는 장난감을 만들 수 있게 유도하고, 모든 팀이 상을 받고(우리 팀이 받은 한 뼘 크기 쿠키런 피규어가 젤 맘에 든다), 맥락없는 춤 타임도 있었다.

맥락없는 춤 타임은 왜 있는지 모르겠지만 ㅋㅋ

우리팀은 ‘월급 루팡도 측정기’를 만들었다. Rescue Time과 비슷한데, 업무와 연관된 사이트 접속 비율을 측정해서 화면에 을 뿌려주는 크롬 확장 프로그램이다. 크롬 확장 프로그램은 처음 만들어보았는데, 웹 프론트엔드를 조금만 할 수 있다면 누구나 쉽게 만들 수 있다. API 문서도 상당히 깔끔하게 되어 있다. 발표할 때는 네이버를 비업무사이트의 예로 두고 시연했는데, 참가자 중에 네이버 개발자 분이 계셨다. ㅋㅋㅋㅋㅋㅋ

프로그램도 알찼고, 축제 같은 느낌, 무엇보다 내가 좋아하는 ‘어설픈 행사 진행과 사회’가 있어서 만족스러웠다.(공감 못하면 그냥 넘어가자…ㅋㅋ)

Express.js에서 oauth로 서드파티 사용자 인증하기

Express.jsPassport.js를 이용해서 페이스북 계정을 인증해보자. 먼저 아래 과정을 통해 우리가 만든 웹 서버가 페이스북 oauth를 이용할 수 있게 한다.

  1. Facebook for Developer에서 새로운 App을 만든다.
  2. 그 다음 Add product > Facebook login을 setup 한다.
  3. 우측 메뉴에 있는 Facebook login의 setting 페이지에서 ‘Valid OAuth redirect URIs’에 ‘http://localhost:3000/login/facebook/callback’을 추가한다. Save changes를 누른다.

필요한 모듈은 다음과 같다.

npm install express passport passport-facebook

서버 객체를 만든다.

const express = require('express');
const app = express();

passport에 facebook strategy를 사용한다. 아까 만든 App의 대시보드에서 App ID와 App Secret을 찾아서 clientIdclientSecret에 입력한다.

인증되면 페이스북으로부터 accessToken, refreshToken과 사용자 정보를 가져온다. 이걸 적절하게 가공한 후에 리턴하면 /login/facebook/callback 라우트에서 req.user로 사용할 수 있다.

const passport = require('passport');
const FacebookStrategy = require('passport-facebook');

passport.use(new FacebookStrategy({
  clientID: [YOUR_APP_ID],
  clientSecret: [YOUR_APP_SECRET],
  callbackURL: '/login/facebook/callback',
  profileFields: ['id', 'email', 'name'],
}, (accessToken, refreshToken, profile, done) => {
  const { id, email } = profile._json;
  const user = {
    provider: 'facebook',
    providerID: id,
    email: email,
  }
  return done(null, user);
}));
app.use(passport.initialize());

로그인을 수행할 route를 추가한다. /login/facebook으로 접속하면 페이스북이 호스팅하는 페이지로 이동해서 사용 허가를 요구할 것이다. scope는 앱의 권한 범위이고, 사용자에게 앱을 허가 받을때 요구하는 권한이 보여진다. 권한 목록은 Permissions Reference - Facebook Login에서 볼 수 있다.

/login/facebook/callback은 인증 허가 이후 리다이렉트되는 주소. 이 주소들은 화이트리스트로 관리하며, 위에서 ‘Valid OAuth redirect URIs’에 이 주소를 추가하지 않았다면 ‘URL Blocked’ 에러가 뜰 것이다. 인증에 실패하거나 거부하면 failureRedirect로 이동한다. 성공하면 passport strategy에서 반환하는 데이터를 req.user로 이용할 수 있다.

app.get('/login/facebook',
  passport.authenticate('facebook', {
    scope: ['public_profile', 'email'],
  })
);

app.get('/login/facebook/callback',
  passport.authenticate('facebook', {
    session: false,
    failureRedirect: '/login/facebook',
  }), (req, res) => {
    return res.json(req.user);
  }
);

마지막으로 서버를 실행한다.

const port = 3000;
app.listen(port, () => {
  console.log(('App is running at http://localhost:%d'), port);
});

이제 브라우저를 열고 http://localhost:3000/login/facebook 에 접속하자. 페이스북이 호스팅하는 페이지를 경유해야하기 때문에 curl등은 사용할 수 없다. 페이스북에 로그인하고 앱 사용 권한을 허가해주면 http://localhost:3000/login/facebook/callback 로 리다이렉트되면서 사용자 정보를 확인할 수 있다.

{
  "provider": "facebook",
  "providerID": "[YOUR_APP_ID]",
  "email": "[YOUR_FACEBOOK_EMAIL]"
}

전체 코드 보기