Slide 1

Slide 1 text

.PKPMJDJPVTͰ͸͡ΊΔ
 ϚΠΫϩαʔϏεΞʔΩςΫνϟ NBTBLZTU
 ͍͞ͱ͏·͖͋͞

Slide 2

Slide 2 text

w ͍͞ͱ͏·͖͋͞
 !NBTBLZTU w 0LJOBXBQNͷਓ w 8FCϋϧαʔΤϯδχΞ w ೶ۀɺ໦଄ݐங w ԭೄݝಡ୩ଜࡏॅ
 ʢ೔ຊҰਓޱͷଟ͍ଜʂʣ ࣗݾ঺հ

Slide 3

Slide 3 text

΋͘͡ ετʔϦʔ .PKPMJDJPVTͱ͸ "1*Λ࡞੒͢Δ "1*Λू໿͢Δ ηΩϡϦςΟೝূ 0LJOBXBQNͷ͝঺հ

Slide 4

Slide 4 text

ετʔϦʔ

Slide 5

Slide 5 text

ετʔϦʔ w ϞϊϦγοΫʹ·ΈΕͨγεςϜΛɺঃʑʹɺ
 ϚΠΫϩαʔϏεԽ͍ͯͬͨ͠ͻͱͭͷ࿩Ͱ͢ɻ w 1)1 1FSM 1ZUIPOͳͲͰߏங͞ΕͨϞϊϦγοΫΞϓϦ܈ w ֤ΞϓϦ͕௚઀σʔλϕʔεʹ઀ଓͯ͠σʔλΛऔಘߋ৽ w ΞϓϦؒͰɺࣅ༷ͨͳςʔϒϧ͕࡞ΒΕ͍ͯͨ

Slide 6

Slide 6 text

ετʔϦʔ 8FCTFSWFS ΞϓϦ1)1$PEF*HOJUFS ΞϓϦ1)14ZNGPOZ ΞϓϦ1ZUIPO%KBOHP ΞϓϦ1)1$PEF*HOJUFS ΞϓϦ1)1$PEF*HOJUFS ΞϓϦ1)14ZNGPOZ %#TFSWFS 8FCTFSWFS 8FCTFSWFS ΞϓϦ1FSM"NPO ΞϓϦ1)18PSE1SFTT 3FEJT ΞϓϦ1)1$PEF*HOJUFS %#TFSWFS

Slide 7

Slide 7 text

ετʔϦʔ ͯ͞Ͳ͏෼ׂ͢Δ͔ʜ ෼ׂ̍ɿ൚༻తͳ"1*Λ෼͚Δ w ༣ศ൪߸ॅॴ"1*
 w ϝʔϧ഑৴"1* ֤ϑΥʔϜͰ%#͔ΒҾ͍͖ͯͯΔɻ,&/@"--͕ෳ਺͋Δɻ όοΫΤϯυͷ.5"Λ੾Γସ͑Մʹɻ
 QPTUpY KPCRVFVF.JOJPO $POP)B 4FOE(SJE "NB[PO4&4
 w νϟοτ௨஌"1* Τϥʔ௨஌ํ๏ɺϑΥʔϚοτ͕όϥόϥͩͬͨͷͰɺ౷Ұͯ͠)JQ$IBU΁ྲྀ͢
 ϏδωεϩδοΫʹӨڹ͕ͳ͍ҝ΍Γ΍͍͢

Slide 8

Slide 8 text

ετʔϦʔ ͯ͞Ͳ͏෼ׂ͢Δ͔ʜ ෼ׂ̎ɿऔಘܥͷ"1*Λ෼͚Δ σʔλͷഁյͷ৺഑͕ͳ͍ҝ΍Γ΍͍͢ ෼ׂ̏ɿڞ༻͢Δߋ৽ܥͷ"1* ਃ͠ࠐΈ"1*ʜͳͲɺڞ༻͠ͳ͍ΞϓϦ୯ಠͳ෦෼͸ɺ
 ༏ઌͯ͠"1*ʹ͢Δඞཁੑ͕গͳ͍ͷͰɺޙճ͠ʹɻ
 ݺͼग़͠ଆͷґଘΛͳ͘͠ɺγϯϓϧʹ͢Δʹ͸΋ͪΖΜඞཁɻ ʢૄ݁߹ʣ w ళฮ৘ใ"1* w ձһ৘ใ"1* w ΞϑΟϦΤΠτ؅ཧ"1*

Slide 9

Slide 9 text

ετʔϦʔ ԿͰ"1*Λ࡞Δ͔ʜ w ޙํޓ׵ʹ༏Ε͍ͯΔ1FSM͕͍͍ w খ͞ͳ"1*͕ଟ͍ͷͰɺNJDSPGSBNFXPSL͕͍͍ w ґଘϞδϡʔϧ͸গͳ͍ํ͕͍͍͔ͳʁ .PKPMJDJPVT

Slide 10

Slide 10 text

.PKPMJDJPVTͱ͸

Slide 11

Slide 11 text

.PKPMJDJPVTͱ͸ w ඪ४ϞδϡʔϧͷΈͰ࣮૷ 1FSMҎ্ͷ৔߹ w 8FCͰ։ൃ͢Δπʔϧ͕ἧͬͯΔ w ϚΠΫϩϑϨʔϜϫʔΫ͕෇ଐ w ༷ʑͳ8FCαʔόΛαϙʔτ αʔό෇ଐɺ14(*ରԠ

Slide 12

Slide 12 text

1 #!/usr/bin/env perl 2 use Mojolicious::Lite; 3 4 get '/' => sub { 5 my $c = shift; 6 $c->render(json => {yapc => 'kansai!!'}); 7 }; 8 9 app->start; % curl --dump-header - 'http://localhost:3000/' HTTP/1.1 200 OK Content-Length: 19 Date: Tue, 21 Feb 2017 01:54:25 GMT Content-Type: application/json;charset=UTF-8 Server: Mojolicious (Perl) {"yapc":"kansai!!"} .PKPMJDJPVTͱ͸ ϚΠΫϩϑϨʔϜϫʔΫͷ࠷খߏ੒

Slide 13

Slide 13 text

"1*Λ࡞੒͢Δ

Slide 14

Slide 14 text

helper mysql => sub { state $mysql = Mojo::mysql->new($CONFIG->{database}->{dsn}); }; get '/:code' => [code => qr/(\d){7}/] => sub { my $c = shift; my $code = $c->param('code'); my $city = $c->mysql->db->query('SELECT * FROM ken_all WHERE code = ?', $code)->hash; unless ($city) { $city = {}; } $c->render(json => $city); }; ྫ͑͹ɺ༣ศ൪߸͔ΒॅॴΛݕࡧ͢Δ"1* % curl --dump-header - 'http://localhost:3000/9040322' HTTP/1.1 200 OK Server: Mojolicious (Perl) Content-Length: 183 Date: Tue, 21 Feb 2017 07:01:23 GMT Content-Type: application/json;charset=UTF-8 {"code":"9040322","kana1":"ΦΩφϫέϯ","kana2":"φΧΨϛάϯϤϛλϯιϯ","kana3":"φϛώϥ","name1":"ԭೄݝ ","name2":"த಄܊ಡ୩ଜ","name3":"೾ฏ"} "1*Λ࡞੒͢Δ

Slide 15

Slide 15 text

use utf8; use t::Util; use Test::More; use Test::Mojo; use FindBin; require “$FindBin::Bin/../ken_all.pl"; my $t = Test::Mojo->new; $t->get_ok('/9040322') ->status_is(200) ->json_has('/9040322') ->json_is('/9040322/name1' => 'ԭೄݝ') ->json_is('/9040322/kana1' => 'ΦΩφϫέϯ'); +40/ͷςετ ok 1 - GET /9040322 ok 2 - 200 OK ok 3 - has value for JSON Pointer "/9040322" ok 4 - exact match for JSON Pointer "/9040322/name1" ok 5 - exact match for JSON Pointer "/9040322/kana1" 1..5 ok 3034 ms ( 0.00 usr 0.00 sys + 0.44 cusr 0.43 csys = 0.87 CPU) [12:44:50] All tests successful. "1*Λ࡞੒͢Δ { "9040322": { "kana1": "ΦΩφϫέϯ", "kana2": "φΧΨϛάϯϤϛλϯιϯ", "kana3": "φϛώϥ", "name1": "ԭೄݝ", "name2": "த಄܊ಡ୩ଜ", "name3": "೾ฏ" } }

Slide 16

Slide 16 text

$c->delay( # ฒྻϦΫΤετ sub { my $delay = shift; $c->ua->get('127.0.0.1:5000/affiliate/list' => $delay->begin); $c->ua->get('127.0.0.1:5000/course/112345' => $delay->begin); $c->ua->get('127.0.0.1:5000/member/masakyst' => $delay->begin); }, # ݁ՌΛશͯड͚͔ͯΒϨϯμϦϯά sub { my ($delay, $affiliate, $course, $member) = @_; $c->stash({ affiliate => $affiliate->res->json, course => $course->res->json, member => $member->res->json, }); $c->render(template => 'index'); } ); ෳ਺ͷ"1*ݺͼग़͠Λฒྻʹ͢Δ "1*Λ࡞੒͢Δ ˞IZPOPUPBE NPSCPͰͳ͍ͱಈ͖·ͤΜ ˞಺෦"1*ݺͼग़͠ͷྫ

Slide 17

Slide 17 text

"1*Λू໿͢Δ

Slide 18

Slide 18 text

"1*Λू໿͢Δ w ී௨ͳΒ֤"1*ຖʹαʔόΠϯελϯεΛݐͯΔ w ϑϩϯτͷ8FCαʔό͔ΒϦόʔεϓϩΩγ w ֤"1*ʹࢮ׆؂ࢹ ෮چʢ4VQFSWJTPSEʜ ͯ͞ɺ"1*͸୔ࢁͰ͖ͨɺͲ͏΍ͬͯ഑ஔ͠Α͏ʜ ͜ͷล͕খن໛ͩͱඇৗʹΊΜͲ͍ʂʂ

Slide 19

Slide 19 text

ํ๏̍ɿ.PVOUʹΑΔ"1*ͷू໿ "1*Λू໿͢Δ "1*ήʔτ΢ΣΠ ༣ศ൪߸ݕࡧ"1* ϝʔϧૹ৴"1* ձһ؅ཧ"1* ళฮ؅ཧ"1* LFO@BMM NBJMTFOEFS NFNCFST TUPSFT όοΫΤϯυͷ"1*ΛϚ΢ϯτ

Slide 20

Slide 20 text

ํ๏̍ɿ.PVOUʹΑΔ"1*ͷू໿ use Mojolicious::Lite; plugin Mount => {'/ken_all' => 'ken_all.pl' }; plugin Mount => {'/keystone' => 'keystone.pl' }; plugin Mount => {'/mailsender' => 'mailsender.pl' }; plugin Mount => {'/alert' => 'alert.pl' }; plugin Mount => {'/store_info' => 'store_info.pl' }; plugin Mount => {'/members' => 'members.pl' }; app->start; "1*Λू໿͢Δ % carmel exec -- ./api-gateway.pl get -M GET /ken_all/9040322 (git)-[master] [Fri Feb 24 13:44:08 2017] [debug] Your secret passphrase needs to be changed [Fri Feb 24 13:44:08 2017] [debug] GET "/ken_all/9040322" [Fri Feb 24 13:44:08 2017] [debug] Routing to application "Mojolicious::Lite" [Fri Feb 24 13:44:08 2017] [debug] Routing to a callback [Fri Feb 24 13:44:08 2017] [debug] 200 OK (0.007251s, 137.912/s) {"code":"9040322","kana1":"ΦΩφϫέϯ","kana2":"φΧΨϛάϯϤϛλϯιϯ","kana3":"φϛώϥ","name1":"ԭೄݝ ","name2":"த಄܊ಡ୩ଜ","name3":"೾ฏ"} Ϛοϐϯά͍ͨ͠63-ɹɹϑΝΠϧ΁ͷύεʢ"1*͸ผʹ։ൃՄʣ BQJHBUFXBZQM

Slide 21

Slide 21 text

"1*Λू໿͢Δ w ϝϦοτ w "1*ຖʹผͰ։ൃͯ͠౷߹Ͱ͖Δ w "1*ຖʹϓϩηεىಈ͍ͯ͠ͳ͍ͷͰɺݸʑͷ؂ࢹ෮چ͕ෆཁ w σϝϦοτ w ̍ͭͷΞϓϦʹͳΔͷͰɺϓϩηε͕େ͖͘ͳΔ w ಉ͡Ϟδϡʔϧͷผόʔδϣϯ͕࢖༻Ͱ͖ͳ͍ ํ๏̍ɿ.PVOUʹΑΔ"1*ͷू໿ ˞Ұ൪ͷσϝϦοτͰ͕͢ɺখن໛ͩͱͦΜͳʹ໰୊ʹͳΒͳ͍Ͱ͢

Slide 22

Slide 22 text

"1*Λू໿͢Δ "1*ήʔτ΢ΣΠ ༣ศ൪߸ݕࡧ"1* ϝʔϧૹ৴"1* ձһ؅ཧ"1* ೝূ"1* LFO@BMM ํ๏̎ɿ1MBDL"QQ1SPYZʹΑΔ"1*ͷू໿ NBJMTFOEFS NFNCFST LFZTUPOF όοΫΤϯυͷ"1*ʹϦόʔεϓϩΩγ

Slide 23

Slide 23 text

"1*Λू໿͢Δ ํ๏̎ɿ1MBDL"QQ1SPYZʹΑΔ"1*ͷू໿ 14(MԽ use Plack::Builder; use Plack::App::Proxy; sub proxy { Plack::App::Proxy->new(remote => $_[0])->to_app; } builder { enable 'Proxy::RewriteLocation'; mount "/ken_all" => proxy(‘http://127.0.0.1:8810'); mount "/keystone" => proxy(‘http://127.0.0.1:8820'); mount "/members" => proxy(‘http://127.0.0.1:8860'); # ... }; όοΫΤϯυͷ"1*ϓϩηε΁3FWFSTF1SPYZ͢Δ

Slide 24

Slide 24 text

% cat Procfile API Gateway: plackup -a api-gateway.psgi ken all API : morbo ./ken_all.pl -l http://*:8810 keystone API : morbo ./keystone.pl -l http://*:8820 members API : morbo ./members.pl -l http://*:8830 "1*Λू໿͢Δ ํ๏̎ɿ1MBDL"QQ1SPYZʹΑΔ"1*ͷू໿ 1SPDMFUʹΑΔ"1*ىಈͷ؅ཧ 14:38:21 keystone API .1 | Server available at http://127.0.0.1:8820 14:38:21 mailsender API .1 | Server available at http://127.0.0.1:8830 14:38:21 ken all API .1 | Server available at http://127.0.0.1:8810 14:38:21 members API .1 | Server available at http://127.0.0.1:8850 14:38:21 store service API .1 | Server available at http://127.0.0.1:8860 14:38:21 hipchat API .1 | Server available at http://127.0.0.1:8840 14:38:21 API Gateway.1 | HTTP::Server::PSGI: Accepting connections at http://0:5000/ w ෳ਺ͷ"1*ϓϩηεͷҰ੪ىಈ w "1*ϓϩηεͷࢮ׆؂ࢹɺࣗಈ෮چ 'JMF3PUBUF-PHTͰϩά΋ू໿Մೳ

Slide 25

Slide 25 text

"1*Λू໿͢Δ w ϝϦοτ w "1*ຖʹɺ׬શʹಠཱͨ͠ϓϩηεϞδϡʔϧͰ։ൃͰ͖Δ w ̍୆ͷαʔό͔Β࢝Ίͯɺ෦෼తʹผαʔόʹ෼ࢄ͠΍͍͢ w 1SPDMFUͷ͓͔͛Ͱɺ"1*ϓϩηεىಈ෮چͷख͕ؒͳ͘ͳΔ w 1SPDMFU͸ɺຊ൪؀ڥͰ΋࢖͏ͱศར w σϝϦοτ w 1FSMʹΑΔ3FWFSTF1SPYZͳͷͰ/HJOYͳͲͱൺ΂ͯগ͠஗͍ ํ๏̎ɿ1MBDL"QQ1SPYZʹΑΔ"1*ͷू໿ "1*ήʔτ΢ΣΠ͸5XJHHZ͕͍͍Ͱ͢

Slide 26

Slide 26 text

ηΩϡϦςΟೝূ

Slide 27

Slide 27 text

ηΩϡϦςΟೝূ w *%ύεϫʔυೝূ w 5PLFOೝূʢ"DDFTT5PLFOΛൃߦʣ w γϯϓϧͳ΋ͷΛࣗ࡞Ͱ΋͍͍ w 0"VUI w +40/8FC5PLFO "1*ݺͼग़͠ʹೝূΛ͔͚͍ͨ .PKPMJDJPVT1MVHJO0"VUI .PKPMJDJPVT1MVHJO0"VUI4FSWFS

Slide 28

Slide 28 text

ηΩϡϦςΟೝূ w +40/8FC5PLFO +85 δϣοτͱಡΉ w ॺ໊ͷग़དྷΔ+40/ΛؚΜͩ63-4BGFͳτʔΫϯ w ҉߸ԽͰ͸ͳ͍ͷͰɺ+40/ͷத਎͸ݟΒΕΔ w Ͱ͕͢ɺվ͟Μ͢Δͱݕূʹࣦഊ͢ΔͷͰجຊతʹ҆શ w %#ͳͲͰͷτʔΫϯ؅ཧ͕ʢγϯϓϧͳ৔߹ʣෆཁ +40/8FC5PLFOʹΑΔೝূ IUUQTKXUJP

Slide 29

Slide 29 text

use Crypt::JWT qw(encode_jwt decode_jwt); 
 $router->add("/authorize", sub { my ($req, $env) = @_; my $id = $req->body_parameters->{login_id}; my $pass = $req->body_parameters->{password}; ## DB઀ଓͯ͠ೝূ my $user = $db->query('SELECT * FROM users WHERE login_id = ? AND password = ?', $id, $pass)->hash; unless ($user) { die; } # JSON TokenԽ͢Δσʔλߏ଄Λ࡞੒ my $payload = { iss => ‘υϝΠϯ’, # ൃߦݩURL sub => $user->{app_id}, # Ϣʔβࣝผࢠ / ΞϓϦID iat => time, # τʔΫϯੜ੒࣌ࠁ exp => time + (60 * 60), # ༗ޮظݶ }; # ൿີ伴ͰJSONΛॺ໊ my $jws_token = encode_jwt(payload => $payload, alg => 'HS256', key => 'ൿີʂ'); return ["200", ["Content-Type" => "application/json"], [encode_json({token => $jws_token})]]; }); +85ʹΑΔೝূαʔό ηΩϡϦςΟೝূ

Slide 30

Slide 30 text

enable sub { my $app = shift; my $unauthorized = sub { my $body = 'Authorization required jwt'; return [401, ['Content-Type' => 'text/plain', 'Content-Length' => length $body, 'WWW-Authenticate' => 'Bearer realm="invalid_token"'], [ $body ] ]; }; my $authenticator = sub { my $token = shift; my $data = decode_jwt(token => $token, key => 'ൿີ'); # ͜ΕͰtokenͷjsonσʔλ͕෮ݩͰ͖·ͨ͠ʂ }; sub { my $env = shift; if ($env->{PATH_INFO} =~ /^\/authorize$/) { return $app->($env); } my $token = $env->{HTTP_AUTHORIZATION} or return $unauthorized->(); if ($token =~ /^Bearer (.*)$/i) { if ($authenticator->($1, $env)) { return $app->($env); } } return $unauthorized->(); }; }; ηΩϡϦςΟೝূ +85ʹΑΔೝূϓϩΩγ

Slide 31

Slide 31 text

ηΩϡϦςΟೝূ w .PKPMJDJPVT1MVHJO"$.& w "$.&ϓϩτίϧ %7ূ໌ൃߦͷࣗಈԽ w 5XJHHZ5-4 w 5XJHHZʹ5-4TVQQPSU ଞɺศརͳ44-ؔ܎ͷπʔϧͷ঺հ ೝূہ $" -FU`T&ODSZQU

Slide 32

Slide 32 text

ηΩϡϦςΟೝূ .PKPMJDJPVT1MVHJO"$.& #!/usr/bin/env perl use Mojolicious::Lite; plugin 'ACME'; get '/' => {text => 'I ♥ YAPC!'}; app->start; $ sudo ./myapp.pl daemon -l http://*:80 [Tue Feb 28 11:34:06 2017] [info] Listening at "http://*:80" Server available at http://127.0.0.1:80 $ ./myapp.pl acme account register [Tue Feb 28 11:13:32 2017] [debug] Your secret passphrase needs to be changed Account Created Writing account.key $ ./myapp.pl acme cert generate υϝΠϯ [Tue Feb 28 11:21:03 2017] [debug] Your secret passphrase needs to be changed Writing myapp.key Writing myapp.crt requires 'Mojolicious'; requires 'Mojolicious::Plugin::ACME'; requires 'IO::Socket::SSL'; DQBOpMF NZBQQQM 5FSNJOBM

Slide 33

Slide 33 text

ηΩϡϦςΟೝূ 5XJHHZ5-4 #!/usr/bin/env perl use Mojolicious::Lite; # plugin 'ACME'; get '/' => {text => 'I ♥ YAPC!'}; app->start; $ plackup -a ./myapp.pl psgi -s Twiggy::TLS --tls-key myapp.key --tls-cert myapp.crt Twiggy: Accepting connections at https://0.0.0.0:5000/ requires 'Plack'; requires 'Twiggy::TLS'; DQBOpMF NZBQQQM 5FSNJOBM $ curl --dump-header - https://api.υϝΠϯ.com:5000/ HTTP/1.0 200 OK Content-Type: text/html;charset=UTF-8 Date: Tue, 28 Feb 2017 03:05:49 GMT Content-Length: 11 I ♥ YAPC!

Slide 34

Slide 34 text

·ͱΊ w "1*࡞੒͸ɺ.PKPMJDJPVTͰॻ͘ͱָʂ w "1*ήʔ΢ΣΠ΋1FSMͰॻ͘ͱָʂ w ϓϩηε؅ཧ΋1FSM 1SPDMFU Ͱָʂ w ೝূ44-ؔ܎΋1FSMͰָʂ શ෦1FSMͷΈͰͰ͖·͢ʂ ϛυϧ΢ΣΞʹ΍ΒΕͳ͍ʂʂ

Slide 35

Slide 35 text

0LJOBXBQNͷ͝঺հ

Slide 36

Slide 36 text

0LJOBXBQNͷ͝঺հ 0LJOBXBQNʢެࣜʣઃཱ͠·ͨ͠ʂ ˞ਅΜத͸఻આͷϋοΧʔNJZBHBXB͞Μ पΓͷਓ͕ίΞϝϯόʔͰ͢

Slide 37

Slide 37 text

0LJOBXBQNͷ͝঺հ લ਎͸ɺ೥͔Β։࢝ͨ͠ඇެࣜ:PNJUBOQN 5XJUUFSͰ֦ࢄ͚ͨͩͩͬͨ͠ͷͰ͕͢ɺ
 Ͳ͔͜Βͱ΋ͳ͘1FSMϢʔβʔ͕ू·Δʜ

Slide 38

Slide 38 text

0LJOBXBQNͷ͝঺հ ԭೄͷ*5ίϛϡχςΟ૯߹ΠϕϯτʮϋοΧʔζνϟϯϓϧʔʯ ͳΜͱ͋ͷ1FSMϋοΧʔ஄͞Μ͕ԭೄʹʂʂ ࠓ೥ͷϋοΧʔζνϟϯϓϧʔ݄Լ०༧ఆͰ͢ʂ

Slide 39

Slide 39 text

0LJOBXBQNͷ͝঺հ +"846(ԭೄ͞Μͱձ৔߹ಉͰษڧձ ճ໨͘Β͍ʹͳΔͱू·ΔϢʔβʔͷ਺ ΋҆ఆ͢ΔΑ͏ʹͳΓ·ͨ͠ ͦΖͦΖɺ0LJOBXBQNʹ͠Α͏͔ʂ

Slide 40

Slide 40 text

0LJOBXBQNͷ͝঺հ ެࣜQNͷ࡞Γํ IUUQHJIZPKQEFWTFSJBMNPEFSOQFSM ʮୈճ1FSM.POHFSTإͷݟ͑Δ஥ؒΛ૿΍ͦ͏ʯΛख़ಡ XXXQNPSHͷʮQFSM@NPOHFSTYNMʯʹQNΛ௥هͯ͠QVMMSFR IUUQTHJUIVCDPNQFSMPSHXXXQNPSH Ϛʔδ͞ΕͨΒ։࠵͢Δʂ

Slide 41

Slide 41 text

0LJOBXBQNͷ͝঺հ QNΛ΍Δͱɺ৭ʑͳਓ͕༡ͼʹ͖ͯ͘Ε·͢ʂ w ීஈձ͑ͳ͍Α͏ͳϋοΧʔͷਓ͕͖ͯ͘ΕͨΓ w ۀքཪଆͷ࿩͕͖͚ͨΓ w ओ࠵͢ΔࣄͰɺࣗ෼ࣗ਎େ͖ͳษڧʹͳͬͨΓ w ѹ౗తʹֶͼ͕͋Γ·͢ɻ޿͕Γ·͢ɻ

Slide 42

Slide 42 text

0LJOBXBQNͷ͝঺հ QNΛ΍Δͱɺ৭ʑͳਓ͕༡ͼʹ͖ͯ͘Ε·͢ʂ ͢͝ʔ͍ʂͨʔͷ͠ʔʂ

Slide 43

Slide 43 text

0LJOBXBQNͷ͝঺հ QN࡞ͬͯΈ·ͤΜ͔ʁ Ҏ্Ͱ͢ɻ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ