Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How we build our app with minimum 3rd party dependencies

How we build our app with minimum 3rd party dependencies

bitFlyer Drink Meetup for iOSエンジニア 登壇資料
https://bitflyer.connpass.com/event/100661

horimislime

October 04, 2018
Tweet

More Decks by horimislime

Other Decks in Programming

Transcript

  1. bitFlyerΞϓϦ͸
    ͍͔ʹͯ͠ϥΠϒϥϦґଘΛ࠷খݶʹ
    ։ൃΛߦ͍ͬͯΔͷ͔


    גࣜձࣾCJU'MZFS
    ງݟफҰ࿠

    View full-size slide

  2. ΞδΣϯμ
    • bitFlyer ͷΞϓϦͱ։ൃελΠϧͷ঺հ
    • ϥΠϒϥϦ࠾༻ͰؕΓ΍͍͢᠘ͱɺ

    bitFlyerͰͷΞϓϩʔν
    • ΞϓϩʔνΛৼΓฦͬͯ

    View full-size slide

  3. bitFlyer ͷΞϓϦͱ։ൃελΠϧͷ঺հ

    View full-size slide

  4. bitFlyer Wallet
    • ೔ຊ࠷େͷԾ૝௨՟औҾॴ
    CJU'MZFSͷJ04޲͚ΞϓϦ
    • ೥͔Β։ൃ։࢝
    • ίʔυϕʔε͸ສߦ௒
    *1 ௐࠪҕୗઌϚΫϩϛϧʢ2018 ೥ 2 ݄ɺΠϯλʔωοτௐࠪʮԾ૝௨՟ɾ҉߸௨՟औҾ

    αʔϏεʹؔ͢ΔΞϯέʔτʯʣɺBitcoin ೔ຊޠ৘ใαΠτௐ΂ɻ
    2016 ೥ 4݄-2018 ೥ 4 ݄ɺࠃ಺औҾॴͷ૯݄ؒग़དྷߴʢݱ෺/ܾࠩۚࡁ/ઌ෺औҾΛؚΉʣ

    View full-size slide

  5. ͲͷΑ͏ʹ࡞͍ͬͯΔ͔
    • ݱࡏ4ਓͰ։ൃத
    • ΞʔΩςΫνϟ͸جຊతʹMVC
    • 3rd partyϥΠϒϥϦʹཔΓ"͗ͣ͢"։ൃ͍ͯ͠Δ

    View full-size slide

  6. bitFlyerͰ࢖͍ͬͯΔϥΠϒϥϦ

    View full-size slide

  7. bitFlyerͰ࢖͍ͬͯΔϥΠϒϥϦ

    View full-size slide

  8. bitFlyerͰ࢖͍ͬͯΔϥΠϒϥϦ

    View full-size slide

  9. bitFlyerͰ࢖͍ͬͯΔϥΠϒϥϦ
    ͘͝Ұ෦Ͱ࢖༻
    ࠷ۙ͸$PEBCMFʹ

    View full-size slide

  10. ຊ೔࿩͞ͳ͍͜ͱ
    • ඪ४SDKݪཧओٛతͳ࿩ɾOSSͷDisΓ
    • ϥΠϒϥϦʹͲΕ͘Β͍པΔ΂͖͔͸ঢ়گʹΑΔ
    • ੒௕ͷݟࠐΊΔαʔϏεɾҰఆͷ։ൃྗ͕͋ΔνʔϜ
    Ͱ͸ࣗલ࣮૷ͷํ͕ϝϦοτ͕ߴ͍

    View full-size slide

  11. ຊ೔࿩͢͜ͱ
    • ϥΠϒϥϦ͸ศར͕ͩɺΉ΍Έʹ࢖͏ͱ଍͔ͤʹ
    • Ͳ͜Ͱ᠘ʹؕΓ΍͍͢ͷ͔ʁ
    • ͦ͜ͰͲ͏࣮૷͍ͯ͠Δͷ͔ʁʹ͍ͭͯ঺հ͠·͢

    View full-size slide

  12. ϥΠϒϥϦ࠾༻ͰؕΓ΍͍͢᠘ͱ
    bitFlyerͰͷΞϓϩʔν

    View full-size slide

  13. ϥΠϒϥϦ࠾༻ͰؕΓ΍͍͢᠘ͱ
    bitFlyerͰͷΞϓϩʔν
    • UIKitͰϥΠϒϥϦΛ࢖͍ͨ͘ͳΔϙΠϯτ
    1. UITableViewͷѻ͍ʹ͘͞
    2. ૒ํ޲όΠϯσΟϯά
    3. Style΍ComponentͷऔΓѻ͍ (Font, Color, IB)
    • Өڹൣғ͕ۃେԽ
    • ֶशίετɾϩοΫΠϯΛͲ͏ղܾ͢Δ͔ʁ

    View full-size slide

  14. 1. UITableViewͷѻ͍ʹ͘͞

    View full-size slide

  15. 1. UITableViewͷѻ͍ʹ͘͞
    • ࣌୅͸એݴతUITableView / CollectionViewઓࠃ࣌୅ʁ
    • RxDataSources Λ࢝ΊɺiOSDCͰ΋࿩୊ʹ
    • ܾఆతͳఆ൪͸·ͩͳ͘ɺͦΕͧΕҰ௕Ұ୹ΞϦ
    • ѻ͍΍͢͞ͱҾ͖׵͑ʹύϥμΠϜ่յ͕ى͜Δ

    View full-size slide

  16. ബ͍ϑϨʔϜϫʔΫͷ੔උ
    • ͱ͸͍͑ૉͷUIKit͸ݫ͍͠
    • ࣗલͰܰྔϑϨʔϜϫʔΫΛ࣮૷͍ͯ͠Δ
    • ࣮૷ίετ͸͔͔Δ͕ɺऔΓճ͠΍͘͢

    ඞཁʹԠ֦ͯ͡ு͠΍͍͢

    View full-size slide

  17. ബ͍ϑϨʔϜϫʔΫͷ࣮૷
    final class HistoryViewController: UIViewController {

    @IBOutlet private weak var tableView: UITableView!

    private var entities = [History]()
    private let dataSource = TableDataSource()
    private let entitiesProvider = EntitiesProvider()
    override func viewDidLoad() {
    super.viewDidLoad()
    dataSource.mapper.register("HistoryCell") { (cell: HistoryCell,
    entity: History) in
    cell.update(with: entity)
    }
    dataSource.provider = entitiesProvider
    tableView.dataSource = dataSource
    tableView.delegate = self
    fetchData()
    }

    View full-size slide

  18. ബ͍ϑϨʔϜϫʔΫͷ࣮૷
    final class HistoryViewController: UIViewController {

    @IBOutlet private weak var tableView: UITableView!

    private var entities = [History]()
    private let dataSource = TableDataSource()
    private let entitiesProvider = EntitiesProvider()
    override func viewDidLoad() {
    super.viewDidLoad()
    dataSource.mapper.register("HistoryCell") { (cell: HistoryCell,
    entity: History) in
    cell.update(with: entity)
    }
    dataSource.provider = entitiesProvider
    tableView.dataSource = dataSource
    tableView.delegate = self
    fetchData()
    }
    EntitiesProvider: ίϯςϯπҰཡͷϚωʔδ
    TableDataSource: UITableViewDataSourceʹ४ڌ

    Provider -> TableView΁ͷڮ౉͠

    View full-size slide

  19. ബ͍ϑϨʔϜϫʔΫͷ࣮૷
    final class HistoryViewController: UIViewController {

    @IBOutlet private weak var tableView: UITableView!

    private var entities = [History]()
    private let dataSource = TableDataSource()
    private let entitiesProvider = EntitiesProvider()
    override func viewDidLoad() {
    super.viewDidLoad()
    dataSource.mapper.register("HistoryCell") { (cell: HistoryCell,
    entity: History) in
    cell.update(with: entity)
    }
    dataSource.provider = entitiesProvider
    tableView.dataSource = dataSource
    tableView.delegate = self
    fetchData()
    }
    EntitiesProvider: ίϯςϯπҰཡͷϚωʔδ
    TableDataSource: UITableViewDataSourceʹ४ڌ

    Provider -> TableView΁ͷڮ౉͠

    View full-size slide

  20. ബ͍ϑϨʔϜϫʔΫͷ࣮૷
    final class HistoryViewController: UIViewController {

    @IBOutlet private weak var tableView: UITableView!

    private var entities = [History]()
    private let dataSource = TableDataSource()
    private let entitiesProvider = EntitiesProvider()
    override func viewDidLoad() {
    super.viewDidLoad()
    dataSource.mapper.register("HistoryCell") { (cell: HistoryCell,
    entity: History) in
    cell.update(with: entity)
    }
    dataSource.provider = entitiesProvider
    tableView.dataSource = dataSource
    tableView.delegate = self
    fetchData()
    }
    reloadData()ͨ͠Βclosure͕ݺ͹ΕΔ (cellForRowAt૬౰)

    View full-size slide

  21. ബ͍ϑϨʔϜϫʔΫͷྑ͞
    • ࠷খݶͷ࣮૷
    • ෆඞཁͳ֓೦͕ಋೖ͞Εͳ͍
    • ཁ݅ɾ໰୊ҙࣝυϦϒϯͰਐԽͰ͖Δ

    View full-size slide

  22. 2. ૒ํ޲όΠϯσΟϯά

    View full-size slide

  23. 2. ૒ํ޲όΠϯσΟϯά
    • ೖྗΛ൐͏6*5BCMF7JFX
    • 5FYUϑΥʔϜɺબ୒ࢶεΠον
    • #JOEJOH͸ΧοίΑ͘ॻ͚Δ͕

    ࿩Λ΍΍͘͜͢͠Δ
    • ෳࡶͳؔ਺Λ࢖͍࢝ΊΔͱ

    σόοάࠔ೉ʹ

    View full-size slide

  24. TableViewCellͷ࠶ར༻Λ΍Ίͯγϯϓϧʹ
    • ΍Γ͍ͨͷ͸ೖྗʹԠͨ͡Πϕϯτॲཧɾೖྗ஋ࢀর
    • Cellͷ࠶ར༻Λ΍Ίͯ͠·͑͹ྑ͍
    • ೖྗϑΥʔϜͱ͸༗ݶͳCellͰߏ੒͞Ε͍ͯΔ͸ͣ

    View full-size slide

  25. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷
    final class InputFormViewController: UIViewController {
    private lazy var userNameCell: TextFieldCell = { ... }()
    private lazy var preferenceCell: SwitchCell = { ... }()

    private lazy var rows: [UITableViewCell] = { 

    [userNameCell, preferenceCell]
    }()
    @IBAction private func doneTapped() {
    API.send(
    name: userNameCell.textField.text,
    preference: preferenceCell.toggle.isOn
    )
    }
    }


    extension InputFormViewController: UITableViewDataSource {

    func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return rows[indexPath.row]
    }
    }

    View full-size slide

  26. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷
    final class InputFormViewController: UIViewController {
    private lazy var userNameCell: TextFieldCell = { ... }()
    private lazy var preferenceCell: SwitchCell = { ... }()

    private lazy var rows: [UITableViewCell] = { 

    [userNameCell, preferenceCell]
    }()
    @IBAction private func doneTapped() {
    API.send(
    name: userNameCell.textField.text,
    preference: preferenceCell.toggle.isOn
    )
    }
    }


    extension InputFormViewController: UITableViewDataSource {

    func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return rows[indexPath.row]
    }
    }

    View full-size slide

  27. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷
    final class InputFormViewController: UIViewController {
    private lazy var userNameCell: TextFieldCell = { ... }()
    private lazy var preferenceCell: SwitchCell = { ... }()

    private lazy var rows: [UITableViewCell] = { 

    [userNameCell, preferenceCell]
    }()
    @IBAction private func doneTapped() {
    API.send(
    name: userNameCell.textField.text,
    preference: preferenceCell.toggle.isOn
    )
    }
    }


    extension InputFormViewController: UITableViewDataSource {

    func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return rows[indexPath.row]
    }
    }

    View full-size slide

  28. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷
    final class InputFormViewController: UIViewController {
    private lazy var userNameCell: TextFieldCell = { ... }()
    private lazy var preferenceCell: SwitchCell = { ... }()

    private lazy var rows: [UITableViewCell] = { 

    [userNameCell, preferenceCell]
    }()
    @IBAction private func doneTapped() {
    API.send(
    name: userNameCell.textField.text,
    preference: preferenceCell.toggle.isOn
    )
    }
    }


    extension InputFormViewController: UITableViewDataSource {

    func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return rows[indexPath.row]
    }
    }
    ֤Form Cell͸໊લͷࢀরΛ͍࣋ͬͯΔ
    ௚઀UIύʔπ͕͍࣋ͬͯΔσʔλΛݟʹ͍͘

    View full-size slide

  29. ࠶ར༻Λ΍ΊΔ͜ͱͷྑ͞
    • γϯϓϧ
    • ૉ௚ͳ࣮૷ͳͷͰ୭͕ಡΜͰ΋෼͔Γ΍͍͢
    • ొ৔ਓ෺Λݶఆ͢ΔͱϝϦοτ͕େ͖͍

    View full-size slide

  30. 3. Style΍ComponentͷऔΓѻ͍

    View full-size slide

  31. 3. Style΍

    ComponentͷऔΓѻ͍
    • 5FYU $PMPSͳͲ޿ൣғʹӨڹ
    • /4"UUSJCVUFE4USJOH΍
    6*4UPSZCPBSE͕ΠϚΠν
    • ඪ४4%,͕ؤுͬͯ΄͍͠
    • 044΋๲େͳ਺
    ग़యWTPV[BBXFTPNFJPTUFYU

    View full-size slide

  32. Text, Color Styles
    • ΞϓϦશମʹίϯϙʔωϯτɾελΠϧΨΠυ੔උࡁ
    • NSAttributedStringͷextension initializerͰશςΩετʹ
    ৭΍ϑΥϯτ౳ͷελΠϧΛద༻

    View full-size slide

  33. Color Paletteͷ࣮૷
    extension UIColor {
    private static func bf_blueColor() -> UIColor {
    return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0)
    }
    private static func bf_lightBlueColor() -> UIColor {
    return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0)
    }
    …

    static func primaryColor() -> UIColor {
    return bf_blueColor()
    }
    static func secondaryTextColor() -> UIColor {
    return bf_grayColor()
    }

    }

    View full-size slide

  34. Color Paletteͷ࣮૷
    extension UIColor {
    private static func bf_blueColor() -> UIColor {
    return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0)
    }
    private static func bf_lightBlueColor() -> UIColor {
    return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0)
    }
    …

    static func primaryColor() -> UIColor {
    return bf_blueColor()
    }
    static func secondaryTextColor() -> UIColor {
    return bf_grayColor()
    }

    }

    View full-size slide

  35. Color Paletteͷ࣮૷
    extension UIColor {
    private static func bf_blueColor() -> UIColor {
    return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0)
    }
    private static func bf_lightBlueColor() -> UIColor {
    return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0)
    }
    …

    static func primaryColor() -> UIColor {
    return bf_blueColor()
    }
    static func secondaryTextColor() -> UIColor {
    return bf_grayColor()
    }

    }
    ΞϓϦ಺Ͱ࢖͏৭

    View full-size slide

  36. Color Paletteͷ࣮૷
    extension UIColor {
    private static func bf_blueColor() -> UIColor {
    return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0)
    }
    private static func bf_lightBlueColor() -> UIColor {
    return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0)
    }
    …

    static func primaryColor() -> UIColor {
    return bf_blueColor()
    }
    static func secondaryTextColor() -> UIColor {
    return bf_grayColor()
    }

    }

    View full-size slide

  37. Color Paletteͷ࣮૷
    extension UIColor {
    private static func bf_blueColor() -> UIColor {
    return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0)
    }
    private static func bf_lightBlueColor() -> UIColor {
    return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0)
    }
    …

    static func primaryColor() -> UIColor {
    return bf_blueColor()
    }
    static func secondaryTextColor() -> UIColor {
    return bf_grayColor()
    }

    }
    ίϯςΩετͷఆٛ

    View full-size slide

  38. Text Stylesͷ࣮૷
    class TextStyle {
    let styleName: String // ελΠϧ໊
    var size: CGFloat // ϑΥϯταΠζ
    var color: UIColor // จࣈͷ৭
    enum Weight {
    case thin, normal, bold
    }
    var weight: Weight // จࣈͷଠ͞
    var textAlignment: NSTextAlignment // จࣈἧ͑
    var kern: CGFloat // จࣈؒͷڑ཭
    enum FontType {
    case proportional, monospaced, compact, monospacedCompact
    }
    var fontType: FontType // ϑΥϯτͷछྨ
    ...

    View full-size slide

  39. Text Stylesͷ࣮૷
    extension TextStyle {
    static var body: TextStyle {
    return TextStyle("body", size: 17, color:
    UIColor.primaryTextColor(),
    weight: .normal, textAlignment: .left, kern: 0.2)
    }
    ...
    }

    View full-size slide

  40. Text Stylesͷ࣮૷
    extension TextStyle {
    static var body: TextStyle {
    return TextStyle("body", size: 17, color:
    UIColor.primaryTextColor(),
    weight: .normal, textAlignment: .left, kern: 0.2)
    }
    ...
    }

    View full-size slide

  41. Text Stylesͷ࣮૷
    extension TextStyle {
    static var body: TextStyle {
    return TextStyle("body", size: 17, color:
    UIColor.primaryTextColor(),
    weight: .normal, textAlignment: .left, kern: 0.2)
    }
    ...
    }

    View full-size slide

  42. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }

    View full-size slide

  43. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }

    View full-size slide

  44. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }

    View full-size slide

  45. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }
    Attributes DictionaryΛੜ੒

    View full-size slide

  46. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }

    View full-size slide

  47. Text Styleͷద༻
    extension NSAttributedString {
    convenience init(string str: String, style: TextStyle, 

    tweak: (_ builder: TextStyle) -> Void) {
    tweak(style)
    self.init(string: str, attributes: style.build())
    }
    }
    message.text = NSAttributedString(string: "Hello!", style: .body)
    name.text = NSAttributedString(string: "Taro", style: .body) { tweak in
    tweak.color = UIColor.secondaryTextColor()
    }
    .bodyʹclosure಺ͷΧελϚΠζΛద༻

    View full-size slide

  48. Storyboard, Xibͷѻ͍
    • SwiftGenͳͲ͸࢖Θͣɺఆ൪ͷprotocol४ڌͷΈ
    protocol StoryboardInitializable: class {
    static var storyboardName: String { get }
    static func instantiateStoryboard(storyboardName: String?) -> Self
    }
    extension StoryboardInitializable where Self: UIViewController {
    static var storyboardName: String {
    return String(describing: self)
    }
    static func instantiateStoryboard() -> Self {
    ...
    }
    }

    View full-size slide

  49. Localizable, Assets౳
    • LocalizedString͸ී௨ʹจࣈྻࢦఆ
    • ิ׬͕ޮ͔ͳ͍ͷ͸ඍົ
    • վमը໘Ҏ֎Ͱ͸ࣄނΔϦεΫ΋গͳ͘ࠔΒͳ͍
    • Α͘ࠔΔͱͨ͠Β։ൃϑϩʔࣗମʹ໰୊͕͋Δ͍ٙ

    View full-size slide

  50. ΞϓϩʔνΛৼΓฦͬͯ

    View full-size slide

  51. ΞϓϩʔνΛৼΓฦͬͯ
    • ଟ͘ͷϥΠϒϥϦ͸՝୊ʹରͯ͠ΦʔόʔΩϧͩͬͨ
    • ࣮͸ࣗલͰ࣮૷ͯ͠΋େม͡Όͳ͔ͬͨέʔε΋ଟ͍
    • ߟ͑ൈ͚͹γϯϓϧɾϕετͳղ๏͕ݟ͔ͭΔ

    View full-size slide

  52. XcodeΞοϓσʔτָ͕ʹ
    • ϥΠϒϥϦͷϝϯςঢ়گʹ։ൃ͕ࠨӈ͞Εʹ͘͘ͳͬͨ
    • Xcode10ରԠ΋εϜʔζ

    View full-size slide

  53. ඪ४SDK΍ຊ࣭తͳઃܭʹٞ࿦ΛूதͰ͖Δ

    View full-size slide

  54. ϥΠϒϥϦ vs ಠ࣮ࣗ૷࿦͸
    νʔϜ։ൃΛݟ௚͖͔͚ͬ͢ʹ΋ͳΔ
    • ϥΠϒϥϦΛ࠾༻ͯ͠ɺԿΛ໨ࢦ͔ͨͬͨ͠ͷ͔
    • ෳࡶͳϥΠϒϥϦ͕ඞཁͳͷ͸࢓༷ʹ໰୊͕ͳ͍͔ʁ
    • σάϨͷසൃ͸ศརϥΠϒϥϦͰղܾͰ͖Δͷ͔ʁ

    View full-size slide

  55. ϥΠϒϥϦ࠾༻ͷצॴ
    • ͢΂ͯࣗલ࣮૷͢Δͷ͸ݱ࣮తͰͳ͍
    • ͋ͱͰҾ͖͸͕͠΍͍͢Ϟϊ͸අ༻ରޮՌ͕ߴ͍
    • ੹຿͕໌֬ͳAPIKitɾNukeɻRx΋࢖͍ํ࣍ୈ
    • ૊৫΍ΤίγεςϜͷਐԽʹద༻͠΍͍ͨ͘͢͠

    View full-size slide

  56. ·ͱΊ
    • bitFlyerΞϓϦͱɺͦͷ։ൃελΠϧͷ঺հ
    • ϥΠϒϥϦ࠾༻ͷ஫ҙ఺ͱɺগͳ͍ґଘͷϝϦοτ
    • ·ͩ·ͩ՝୊ࢁੵΈɺ಺੡ϥΠϒϥϦ΋ۙ೔େվम!?
    ʘ"ຊ࣭"ʹϑΥʔΧε͍ͨ͠ΤϯδχΞɺͥͻฐࣾʹʂʗ

    View full-size slide